diff --git a/AUTHORS.txt b/AUTHORS.txt index 9117d5b3a01b1..4279650842693 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -16,6 +16,7 @@ Arkaitz Jimenez Armin Ronacher Austin Seipp auREAX +Ben Alpert Ben Blum Ben Striegel Benjamin Herr @@ -49,6 +50,7 @@ Erick Tryzelaar Erik Rose Evan McClanahan Francisco Souza +Franklin Chen Gabriel Gareth Daniel Smith Glenn Willen @@ -91,6 +93,7 @@ Magnus Auvinen Mahmut Bulut Margaret Meyerhofer Marijn Haverbeke +Mark Lacey <641@rudkx.com> Martin DeMello Matt Brubeck Matthew O'Connor @@ -106,6 +109,7 @@ Patrik Kårlin Paul Stansifer Paul Woolcock Peter Hull +Peter Williams Philipp Brüschweiler Rafael Ávila de Espíndola Ralph Giles @@ -119,6 +123,7 @@ Sean Stangl Simon Barber-Dueck startling Stefan Plantikow +Steve Klabnik Taras Shpot Ted Horst Tim Chevalier diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000..6528ffa134db6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,12 @@ +## Pull request procedure + +Pull requests should be targeted at Rust's `incoming` branch (note that by default Github will aim them at the `master` branch) -- see "Changing The Commit Range and Destination Repository" in Github's documentation on [pull requests](https://help.github.com/articles/using-pull-requests). Before pushing to your Github repo and issuing the pull request, please do two things: + +1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your local changes against the `incoming` branch. Resolve any conflicts that arise. +2. Run the full Rust test suite with the `make check` command. You're not off the hook even if you just stick to documentation; code examples in the docs are tested as well! + +Pull requests will be treated as "review requests", and we will give feedback we expect to see corrected on [style](https://github.com/mozilla/rust/wiki/Note-style-guide) and substance before pulling. Changes contributed via pull request should focus on a single issue at a time, like any other. We will not look kindly on pull-requests that try to "sneak" unrelated changes in. + +Normally, all pull requests must include regression tests (see [[Note-testsuite]]) that test your change. Occasionally, a change will be very difficult to test for. In those cases, please include a note in your commit message explaining why. + +For more details, please refer to [[Note-development-policy]]. \ No newline at end of file diff --git a/README.md b/README.md index 9f4ee0a44ff96..877e2b5698722 100644 --- a/README.md +++ b/README.md @@ -65,10 +65,11 @@ API-documentation tool, and `cargo`, the Rust package manager. ## License -Rust is primarily distributed under the terms of the MIT license, with -portions covered by various BSD-like licenses. +Rust is primarily distributed under the terms of both the MIT license +and the Apache License (Version 2.0), with portions covered by various +BSD-like licenses. -See LICENSE.txt for details. +See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details. ## More help diff --git a/configure b/configure index f2afa2d26ef8d..1e1b725ff47e9 100755 --- a/configure +++ b/configure @@ -578,7 +578,7 @@ for t in $CFG_TARGET_TRIPLES do make_dir rt/$t for i in \ - isaac linenoise bigint sync test arch/i386 arch/x86_64 \ + isaac linenoise sync test arch/i386 arch/x86_64 \ libuv libuv/src/ares libuv/src/eio libuv/src/ev do make_dir rt/$t/$i diff --git a/doc/rust.md b/doc/rust.md index 210e07d198acc..b5f045bc13a55 100644 --- a/doc/rust.md +++ b/doc/rust.md @@ -1107,6 +1107,19 @@ let mut a: Animal = Dog; a = Cat; ~~~~ +Enumeration constructors can have either named or unnamed fields: +~~~~ +enum Animal { + Dog (~str, float), + Cat { name: ~str, weight: float } +} + +let mut a: Animal = Dog(~"Cocoa", 37.2); +a = Cat{ name: ~"Spotty", weight: 2.7 }; +~~~~ + +In this example, `Cat` is a _struct-like enum variant_, +whereas `Dog` is simply called an enum variant. ### Constants ~~~~~~~~ {.ebnf .gram} @@ -3245,12 +3258,12 @@ crate name the crate is given a default name that matches the source file, with the extension removed. In that case, to turn on logging for a program compiled from, e.g. `helloworld.rs`, `RUST_LOG` should be set to `helloworld`. -As a convenience, the logging spec can also be set to a special psuedo-crate, +As a convenience, the logging spec can also be set to a special pseudo-crate, `::help`. In this case, when the application starts, the runtime will simply output a list of loaded modules containing log expressions, then exit. The Rust runtime itself generates logging information. The runtime's logs are -generated for a number of artificial modules in the `::rt` psuedo-crate, +generated for a number of artificial modules in the `::rt` pseudo-crate, and can be enabled just like the logs for any standard module. The full list of runtime logging modules follows. @@ -3328,7 +3341,7 @@ have come and gone during the course of Rust's development: * The Newsqueak (1988), Alef (1995), and Limbo (1996) family. These languages were developed by Rob Pike, Phil Winterbottom, Sean Dorward and - others in their group at Bell labs Computing Sciences Research Center + others in their group at Bell Labs Computing Sciences Research Center (Murray Hill, NJ, USA). * The Napier (1985) and Napier88 (1988) family. These languages were diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md index 1def470755c31..af1f9ceb92450 100644 --- a/doc/tutorial-macros.md +++ b/doc/tutorial-macros.md @@ -43,7 +43,7 @@ macro_rules! early_return( _ => {} } ); -); +) // ... early_return!(input_1 special_a); // ... @@ -160,7 +160,7 @@ macro_rules! early_return( _ => {} } ); -); +) // ... early_return!(input_1, [special_a|special_c|special_d]); // ... diff --git a/doc/tutorial.md b/doc/tutorial.md index d20ce43c3d2c8..fb5e9dc07a8d6 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -36,7 +36,7 @@ type system and memory model, generics, and modules. [Additional tutorials](#what-next) cover specific language features in greater depth. -This tutorial assumes that the reader is already familiar with one or more +This tutorial assumes that the reader is already familiar with one or more languages in the C family. Understanding of pointers and general memory management techniques will help. @@ -80,7 +80,7 @@ supported build environments that are most likely to work. > "[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 +> need to be [referred to as `rustc.exe`][bug-3319]. It's a bummer, we > know. [bug-3319]: https://github.com/mozilla/rust/issues/3319 @@ -114,7 +114,7 @@ for more information on them. When complete, `make install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler; `rustdoc`, the -API-documentation tool, `cargo`, the Rust package manager, +API-documentation tool; `cargo`, the Rust package manager; and `rusti`, the Rust REPL. [wiki-start]: https://github.com/mozilla/rust/wiki/Note-getting-started-developing-Rust @@ -181,10 +181,10 @@ in blocks delineated by curly braces; there are control structures for branching and looping, like the familiar `if` and `while`; function calls are written `myfunc(arg1, arg2)`; operators are written the same and mostly have the same precedence as in C; comments are again like C; -module names are separated with double-colon, `::`, as with C++. +module names are separated with double-colon (`::`) as with 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 +the head of control structures like `if` and `while` does not require parentheses, while their bodies *must* be wrapped in braces. Single-statement, unbraced bodies are not allowed. @@ -226,12 +226,12 @@ let monster_size: int = 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 +`monster_size` was first declared as a `float`, and then a second +`monster_size` was declared as an `int`. If you were to actually compile this +example, though, the compiler would determine that the first `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 +names may be prefixed with an underscore to silence the warning, like `let _monster_size = 50;`. Rust identifiers start with an alphabetic @@ -292,7 +292,7 @@ branch has a different value, and `price` gets the value of the branch that was taken. In short, everything that's not a declaration (declarations are `let` for -variables, `fn` for functions, and any top-level named items such as +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. @@ -306,8 +306,8 @@ fn is_four(x: int) -> bool { ## Primitive types and literals -There are general signed and unsigned integer types, `int`, and `uint`, -as well as 8-, 16-, 32-, and 64-bit variations, `i8`, `u16`, etc. +There are general signed and unsigned integer types, `int` and `uint`, +as well as 8-, 16-, 32-, and 64-bit variants, `i8`, `u16`, etc. 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`, @@ -326,14 +326,14 @@ let c = 100u; // c is a uint let d = 1000i32; // d is an i32 ~~~~ -There are three floating point types, `float`, `f32`, and `f64`. -Floating point numbers are written `0.0`, `1e6`, or `2.1e-4`. -Like integers, floating point literals are inferred to the correct type. -Suffixes `f`, `f32` and `f64` can be used to create literals of a specific type. +There are three floating-point types: `float`, `f32`, and `f64`. +Floating-point numbers are written `0.0`, `1e6`, or `2.1e-4`. +Like integers, floating-point literals are inferred to the correct type. +Suffixes `f`, `f32`, and `f64` can be used to create literals of a specific type. The keywords `true` and `false` produce literals of type `bool`. -Characters, the `char` type, are 4-byte unicode codepoints, +Characters, the `char` type, are four-byte Unicode codepoints, whose 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, @@ -345,8 +345,8 @@ The nil type, written `()`, has a single value, also written `()`. ## Operators Rust's set of operators contains very few surprises. Arithmetic is done with -`*`, `/`, `%`, `+`, and `-` (multiply, divide, take remainder, add, subtract). `-` is -also a unary prefix operator that negates numbers. As in C, the bit operators +`*`, `/`, `%`, `+`, and `-` (multiply, divide, take remainder, add, and subtract). `-` is +also a unary prefix operator that negates numbers. As in C, the bitwise operators `>>`, `<<`, `&`, `|`, and `^` are also supported. Note that, if applied to an integer value, `!` flips all the bits (like `~` in @@ -444,7 +444,7 @@ match my_number { } ~~~~ -Unlike in C, there is no 'falling through' between arms: only one arm +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. @@ -494,7 +494,7 @@ fn angle(vector: (float, float)) -> float { 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 +the second element. `(x, y)` matches any two-element tuple, and binds both elements to variables. Any `match` arm can have a guard clause (written `if EXPR`), called a @@ -575,7 +575,7 @@ 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. `match` patterns destructure structs. The basic syntax is -`Name {fieldname: pattern, ...}`: +`Name { fieldname: pattern, ... }`: ~~~~ # struct Point { x: float, y: float } @@ -589,7 +589,7 @@ match mypoint { In general, the field names of a struct do not have to appear in the same order they appear in the type. When you are not interested in all the fields of a struct, a struct pattern may end with `, _` (as in -`Name {field1, _}`) to indicate that you're ignoring all other fields. +`Name { field1, _ }`) to indicate that you're ignoring all other fields. Additionally, struct fields have a shorthand matching form that simply reuses the field name as the binding name. @@ -618,15 +618,15 @@ 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 static guarantees. +"tagged union" pattern in C, but with better static guarantees. 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 +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 `enum` declaration, +Enum variants need not have parameters. This `enum` declaration, for example, is equivalent to a C enum: ~~~~ @@ -659,7 +659,7 @@ variant does not have a discriminator, it defaults to 0. For example, the value of `North` is 0, `East` is 1, `South` is 2, and `West` is 3. When an enum is C-like, you can apply the `as` cast operator to -convert it to its discriminator value as an int. +convert it to its discriminator value as an `int`. @@ -710,7 +710,7 @@ patterns, as in this definition of `area`: fn area(sh: Shape) -> float { match sh { Circle(_, size) => float::consts::pi * size * size, - Rectangle(Point {x, y}, Point {x: x2, y: y2}) => (x2 - x) * (y2 - y) + Rectangle(Point { x, y }, Point { x: x2, y: y2 }) => (x2 - x) * (y2 - y) } } ~~~~ @@ -721,14 +721,34 @@ introduction form, nullary enum patterns are written without parentheses. ~~~~ -# struct 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 { - North => Point {x: 0f, y: 1f}, - East => Point {x: 1f, y: 0f}, - South => Point {x: 0f, y: -1f}, - West => Point {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 } + } +} +~~~~ + +Enum variants may also be structs. For example: + +~~~~ +# use core::float; +# struct Point { x: float, y: float } +# fn square(x: float) -> float { x * x } +enum Shape { + Circle { center: Point, radius: float }, + Rectangle { top_left: Point, bottom_right: Point } +} +fn area(sh: Shape) -> float { + match sh { + Circle { radius: radius, _ } => float::consts::pi * square(radius), + Rectangle { top_left: top_left, bottom_right: bottom_right } => { + (bottom_right.x - top_left.x) * (bottom_right.y - top_left.y) + } } } ~~~~ @@ -781,7 +801,7 @@ fn line(a: int, b: int, x: int) -> int { The `return` keyword immediately returns from the body of a function. It is optionally followed by an expression to return. A function can -also return a value by having its top level block produce an +also return a value by having its top-level block produce an expression. ~~~~ @@ -815,7 +835,7 @@ assert () == oops(5, 3, 1); As with `match` expressions and `let` bindings, function arguments support pattern destructuring. Like `let`, argument patterns must be irrefutable, -as in this example that unpacks a tuple and returns it. +as in this example that unpacks the first value from a tuple and returns it. ~~~ fn first((value, _): (int, float)) -> int { value } @@ -898,7 +918,7 @@ 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 +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. @@ -908,7 +928,7 @@ 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. Rust supports several types of pointers. The safe pointer types are -`@T` for managed boxes allocated on the local heap, `~T`, for +`@T`, for managed boxes allocated on the local heap, `~T`, for uniquely-owned boxes allocated on the exchange heap, and `&T`, for borrowed pointers, which may point to any memory, and whose lifetimes are governed by the call stack. @@ -922,8 +942,8 @@ All pointer types can be dereferenced with the `*` unary operator. ## Managed boxes -Managed boxes are pointers to heap-allocated, garbage collected -memory. Applying the unary `@` operator to an expression creates a +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 managed box, as happens during assignment, only copies a pointer, never the contents of the box. @@ -1018,7 +1038,8 @@ As an example, consider a simple struct type, `Point`: ~~~ struct Point { - x: float, y: float + x: float, + y: float } ~~~~ @@ -1028,9 +1049,9 @@ contains a point, but allocated in a different location: ~~~ # struct Point { x: float, y: float } -let on_the_stack : Point = Point {x: 3.0, y: 4.0}; -let managed_box : @Point = @Point {x: 5.0, y: 1.0}; -let owned_box : ~Point = ~Point {x: 7.0, y: 9.0}; +let on_the_stack : Point = Point { x: 3.0, y: 4.0 }; +let managed_box : @Point = @Point { x: 5.0, y: 1.0 }; +let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 }; ~~~ Suppose we wanted to write a procedure that computed the distance @@ -1059,9 +1080,9 @@ Now we can call `compute_distance()` in various ways: ~~~ # struct Point{ x: float, y: float }; -# let on_the_stack : Point = Point {x: 3.0, y: 4.0}; -# let managed_box : @Point = @Point {x: 5.0, y: 1.0}; -# let owned_box : ~Point = ~Point {x: 7.0, y: 9.0}; +# let on_the_stack : Point = Point { x: 3.0, y: 4.0 }; +# let managed_box : @Point = @Point { x: 5.0, y: 1.0 }; +# let owned_box : ~Point = ~Point { x: 7.0, y: 9.0 }; # fn compute_distance(p1: &Point, p2: &Point) -> float { 0f } compute_distance(&on_the_stack, managed_box); compute_distance(managed_box, owned_box); @@ -1071,14 +1092,14 @@ Here the `&` operator is used to take 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 +`on_the_stack`, because we are creating an alias: that is, another route to the same data. In the case of the boxes `managed_box` and `owned_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 managed/owned box is being lent out. +contents of the managed/owned box are being lent out. 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 @@ -1138,7 +1159,7 @@ let area = (*rect).area(); ~~~ To combat this ugliness the dot operator applies _automatic pointer -dereferencing_ to the receiver (the value on the left hand side of the +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. ~~~ @@ -1180,7 +1201,7 @@ pointers to vectors are also called 'slices'. // A fixed-size stack vector let stack_crayons: [Crayon * 3] = [Almond, AntiqueBrass, Apricot]; -// A borrowed pointer to stack allocated vector +// A borrowed pointer to stack-allocated vector let stack_crayons: &[Crayon] = &[Aquamarine, Asparagus, AtomicTangerine]; // A local heap (managed) vector of crayons @@ -1263,7 +1284,7 @@ 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 +vectors, plain strings are borrowed pointers to read-only (static) memory. All strings are immutable. ~~~ @@ -1507,7 +1528,7 @@ do spawn() || { } ~~~~ -Look at all those bars and parentheses - that's two empty argument +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. @@ -1586,7 +1607,7 @@ fn contains(v: &[int], elt: int) -> bool { ~~~~ Notice that, because `each` passes each value by borrowed pointer, -the iteratee needs to dereference it before using. +the iteratee needs to dereference it before using it. In these situations it can be convenient to lean on Rust's argument patterns to bind `x` to the actual value, not the pointer. @@ -1708,7 +1729,7 @@ s.draw_borrowed(); // ... and dereferenced (& &s).draw_borrowed(); -// ... and dereferenced, and borrowed, and +// ... and dereferenced and borrowed (&@~s).draw_borrowed(); ~~~ @@ -1771,9 +1792,9 @@ Inside a generic function, the names of the type parameters (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 +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 +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. @@ -1794,7 +1815,7 @@ enum Option { ~~~~ These declarations can be instantiated to valid types like `Set`, -`Stack` and `Option`. +`Stack`, and `Option`. The last type in that example, `Option`, appears frequently in Rust code. Because Rust does not have null pointers (except in unsafe code), we need @@ -1803,13 +1824,13 @@ combination of arguments of the appropriate types. The usual way is to write a function that returns `Option` instead of `T`. ~~~~ -# struct Point {x: float, y: float} +# struct Point { x: float, y: float } # enum Shape { Circle(Point, float), Rectangle(Point, Point) } fn radius(shape: Shape) -> Option { - match shape { - Circle(_, radius) => Some(radius), - Rectangle(*) => None - } + match shape { + Circle(_, radius) => Some(radius), + Rectangle(*) => None + } } ~~~~ @@ -1873,12 +1894,12 @@ 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 explicitly with the +* `Copy` - Types that can be copied, either implicitly, or explicitly with the `copy` operator. All types are copyable unless they have destructors or contain types with destructors. * `Owned` - Owned types. Types are owned unless they contain managed - boxes, managed closures, or borrowed pointers. Owned types may or + boxes, managed closures, or borrowed pointers. Owned types may or may not be copyable. * `Const` - Constant (immutable) types. These are types that do not contain @@ -1895,7 +1916,7 @@ garbage collector reclaimed it. ~~~ struct TimeBomb { - explosivity: uint, + explosivity: uint } impl TimeBomb : Drop { @@ -1926,7 +1947,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 the definition, as in the following impls of `Printable` for `int` -and `~str`. +and `&str`. [impls]: #functions-and-methods @@ -1985,12 +2006,12 @@ following trait describes types that support an equality operation: // In a trait, `self` refers both to the self argument // and to the type implementing the trait trait Eq { - fn equals(&self, other: &self) -> bool; + fn equals(&self, other: &self) -> bool; } // In an impl, `self` refers just to the value of the receiver impl int: Eq { - fn equals(&self, other: &int) -> bool { *other == *self } + fn equals(&self, other: &int) -> bool { *other == *self } } ~~~~ @@ -2014,7 +2035,7 @@ impl Circle: Shape { static fn new(area: float) -> Circle { Circle { radius: sqrt(area / pi) } } } impl Square: Shape { - static fn new(area: float) -> Square { Square { length: sqrt(area) } } + static fn new(area: float) -> Square { Square { length: sqrt(area) } } } let area = 42.5; @@ -2084,9 +2105,9 @@ fn draw_all(shapes: ~[T]) { # draw_all(~[c]); ~~~~ -You can call that on an array of circles, or an array of squares +You can call that on an array of circles, or an array of rectangles (assuming those have suitable `Drawable` traits defined), but not on -an array containing both circles and squares. When such behavior is +an array containing both circles and rectangles. When such behavior is needed, a trait name can alternately be used as a type, called an _object_. @@ -2170,10 +2191,10 @@ Now, we can implement `Circle` on a type only if we also implement `Shape`. # fn square(x: float) -> float { x * x } struct CircleStruct { center: Point, radius: float } impl CircleStruct: Circle { - fn radius(&self) -> float { sqrt(self.area() / pi) } + fn radius(&self) -> float { sqrt(self.area() / pi) } } impl CircleStruct: Shape { - fn area(&self) -> float { pi * square(self.radius) } + fn area(&self) -> float { pi * square(self.radius) } } ~~~~ @@ -2247,7 +2268,7 @@ fn chicken_farmer() { ~~~ These farm animal functions have a new keyword, `pub`, attached to -them. The `pub` keyword modifies an item's visibility, making it +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`, @@ -2257,11 +2278,12 @@ 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 this encapsulation is at the module level, not the +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 { +# use farm; # pub fn make_me_a_farm() -> farm::Farm { farm::Farm { chickens: ~[], cows: ~[], farmer: Human(0) } } pub struct Farm { priv mut chickens: ~[Chicken], @@ -2300,7 +2322,7 @@ fn main() { 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. +library or an executable. When compiling a single `.rs` source file, the file acts as the whole crate. You can compile it with the `--lib` compiler switch to create a shared @@ -2348,7 +2370,7 @@ Compiling this file will cause `rustc` to look for files named `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, +executable. (If the line `#[crate_type = "lib"];` was omitted, `rustc` would create an executable.) The `#[link(...)]` attribute provides meta information about the diff --git a/mk/docs.mk b/mk/docs.mk index 2a7b3eccbf6be..9f64712b9c860 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -152,7 +152,7 @@ else doc/rust.g: rust.md $(S)src/etc/extract_grammar.py @$(call E, extract_grammar: $@) - $(Q)$(S)src/etc/extract_grammar.py $< >$@ + $(Q)$(CFG_PYTHON) $(S)src/etc/extract_grammar.py $< >$@ verify-grammar: doc/rust.g @$(call E, LLnextgen: $<) diff --git a/mk/snap.mk b/mk/snap.mk index 382f3cb4a8849..21bdc3b80d854 100644 --- a/mk/snap.mk +++ b/mk/snap.mk @@ -14,10 +14,10 @@ define DEF_SNAP_FOR_STAGE_H ifdef CFG_INSTALL_SNAP snap-stage$(1)-H-$(2): $$(HSREQ$(1)_H_$(2)) - $(S)src/etc/make-snapshot.py stage$(1) $(2) install + $(CFG_PYTHON) $(S)src/etc/make-snapshot.py stage$(1) $(2) install else snap-stage$(1)-H-$(2): $$(HSREQ$(1)_H_$(2)) - $(S)src/etc/make-snapshot.py stage$(1) $(2) + $(CFG_PYTHON) $(S)src/etc/make-snapshot.py stage$(1) $(2) endif endef @@ -30,4 +30,4 @@ snap-stage1: snap-stage1-H-$(CFG_HOST_TRIPLE) snap-stage2: snap-stage2-H-$(CFG_HOST_TRIPLE) -snap-stage3: snap-stage3-H-$(CFG_HOST_TRIPLE) \ No newline at end of file +snap-stage3: snap-stage3-H-$(CFG_HOST_TRIPLE) diff --git a/mk/stage0.mk b/mk/stage0.mk index b64f5df9ca038..e1a83c18f4d46 100644 --- a/mk/stage0.mk +++ b/mk/stage0.mk @@ -11,7 +11,7 @@ $(HBIN0_H_$(CFG_HOST_TRIPLE))/rustc$(X): \ ifdef CFG_ENABLE_LOCAL_RUST $(Q)$(S)src/etc/local_stage0.sh $(CFG_HOST_TRIPLE) $(CFG_LOCAL_RUST_ROOT) else - $(Q)$(S)src/etc/get-snapshot.py $(CFG_HOST_TRIPLE) $(SNAPSHOT_FILE) + $(Q)$(CFG_PYTHON) $(S)src/etc/get-snapshot.py $(CFG_HOST_TRIPLE) $(SNAPSHOT_FILE) ifdef CFG_ENABLE_PAX_FLAGS @$(call E, apply PaX flags: $@) @"$(CFG_PAXCTL)" -cm "$@" diff --git a/mk/tests.mk b/mk/tests.mk index 3f085494f567d..454d540d84db9 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -701,7 +701,7 @@ tmp/$(FT).rc tmp/$(FT_DRIVER).rs: \ $(RPASS_TESTS) \ $(S)src/etc/combine-tests.py @$(call E, check: building combined stage2 test runner) - $(Q)$(S)src/etc/combine-tests.py + $(Q)$(CFG_PYTHON) $(S)src/etc/combine-tests.py define DEF_CHECK_FAST_FOR_T_H # $(1) unused diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 20b7e32d0c995..136f40c9c207a 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use cmp; + enum mode { mode_compile_fail, mode_run_fail, mode_run_pass, mode_pretty, } impl mode : cmp::Eq { diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc index 8505e48163869..ba6862039d44d 100644 --- a/src/compiletest/compiletest.rc +++ b/src/compiletest/compiletest.rc @@ -211,7 +211,7 @@ fn is_test(config: config, testfile: &Path) -> bool { fn make_test(config: config, testfile: &Path) -> test::TestDesc { - { + test::TestDesc { name: make_test_name(config, testfile), testfn: make_test_closure(config, testfile), ignore: header::is_test_ignored(config, testfile), diff --git a/src/compiletest/errors.rs b/src/compiletest/errors.rs index 632619f138103..62961f6c6e4eb 100644 --- a/src/compiletest/errors.rs +++ b/src/compiletest/errors.rs @@ -9,7 +9,9 @@ // except according to those terms. use common::config; +use io; use io::ReaderUtil; +use str; export load_errors; export expected_error; @@ -33,8 +35,8 @@ fn parse_expected(line_num: uint, line: ~str) -> ~[expected_error] unsafe { let error_tag = ~"//~"; let mut idx; match str::find_str(line, error_tag) { - option::None => return ~[], - option::Some(nn) => { idx = (nn as uint) + str::len(error_tag); } + None => return ~[], + Some(nn) => { idx = (nn as uint) + str::len(error_tag); } } // "//~^^^ kind msg" denotes a message expected diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 24645e02b2008..730e863d04d4e 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use common; use common::config; +use io; use io::ReaderUtil; +use os; +use str; export test_props; export load_props; @@ -34,12 +38,12 @@ fn load_props(testfile: &Path) -> test_props { let mut error_patterns = ~[]; let mut aux_builds = ~[]; let mut exec_env = ~[]; - let mut compile_flags = option::None; - let mut pp_exact = option::None; + let mut compile_flags = None; + let mut pp_exact = None; for iter_header(testfile) |ln| { match parse_error_pattern(ln) { - option::Some(ep) => error_patterns.push(ep), - option::None => () + Some(ep) => error_patterns.push(ep), + None => () }; if compile_flags.is_none() { @@ -78,7 +82,7 @@ fn is_test_ignored(config: config, testfile: &Path) -> bool { return found; fn xfail_target() -> ~str { - ~"xfail-" + os::sysname() + ~"xfail-" + str::from_slice(os::SYSNAME) } } @@ -124,12 +128,12 @@ fn parse_exec_env(line: ~str) -> Option<(~str, ~str)> { fn parse_pp_exact(line: ~str, testfile: &Path) -> Option { match parse_name_value_directive(line, ~"pp-exact") { - option::Some(s) => option::Some(Path(s)), - option::None => { + Some(s) => Some(Path(s)), + None => { if parse_name_directive(line, ~"pp-exact") { - option::Some(testfile.file_path()) + Some(testfile.file_path()) } else { - option::None + None } } } @@ -143,12 +147,12 @@ fn parse_name_value_directive(line: ~str, directive: ~str) -> Option<~str> unsafe { let keycolon = directive + ~":"; match str::find_str(line, keycolon) { - option::Some(colon) => { + Some(colon) => { let value = str::slice(line, colon + str::len(keycolon), str::len(line)); debug!("%s: %s", directive, value); - option::Some(value) + Some(value) } - option::None => option::None + None => None } } diff --git a/src/compiletest/procsrv.rs b/src/compiletest/procsrv.rs index 23f9e819bc4de..666deeca191fd 100644 --- a/src/compiletest/procsrv.rs +++ b/src/compiletest/procsrv.rs @@ -8,9 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use run::spawn_process; +use io; use io::{ReaderUtil, WriterUtil}; +use libc; use libc::{c_int, pid_t}; +use os; +use run; +use run::spawn_process; +use pipes; +use str; +use task; export run; diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 959bc344f1d50..a7dbfb9a3b279 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -8,15 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use io; use io::WriterUtil; +use os; +use str; +use uint; +use vec; +use common; use common::mode_run_pass; use common::mode_run_fail; use common::mode_compile_fail; use common::mode_pretty; use common::config; +use errors; +use header; use header::load_props; use header::test_props; +use procsrv; +use util; use util::logv; export run; @@ -117,7 +127,7 @@ fn run_pretty_test(config: config, props: test_props, testfile: &Path) { } else { logv(config, ~"testing for converging pretty-printing"); } let rounds = - match props.pp_exact { option::Some(_) => 1, option::None => 2 }; + match props.pp_exact { Some(_) => 1, None => 2 }; let mut srcs = ~[io::read_whole_file_str(testfile).get()]; @@ -137,11 +147,11 @@ fn run_pretty_test(config: config, props: test_props, testfile: &Path) { let mut expected = match props.pp_exact { - option::Some(file) => { + Some(file) => { let filepath = testfile.dir_path().push_rel(&file); io::read_whole_file_str(&filepath).get() } - option::None => { srcs[vec::len(srcs) - 2u] } + None => { srcs[vec::len(srcs) - 2u] } }; let mut actual = srcs[vec::len(srcs) - 1u]; @@ -165,7 +175,7 @@ fn run_pretty_test(config: config, props: test_props, testfile: &Path) { fn print_source(config: config, testfile: &Path, src: ~str) -> procres { compose_and_run(config, testfile, make_pp_args(config, testfile), - ~[], config.compile_lib_path, option::Some(src)) + ~[], config.compile_lib_path, Some(src)) } fn make_pp_args(config: config, _testfile: &Path) -> procargs { @@ -199,7 +209,7 @@ actual:\n\ compose_and_run_compiler( config, props, testfile, make_typecheck_args(config, testfile), - option::Some(src)) + Some(src)) } fn make_typecheck_args(config: config, testfile: &Path) -> procargs { @@ -418,7 +428,7 @@ fn exec_compiled_test(config: config, props: test_props, compose_and_run(config, testfile, make_run_args(config, props, testfile), props.exec_env, - config.run_lib_path, option::None) + config.run_lib_path, None) } fn compose_and_run_compiler( @@ -441,7 +451,7 @@ fn compose_and_run_compiler( make_compile_args(config, props, ~[~"--lib"] + extra_link_args, |a,b| make_lib_name(a, b, testfile), &abs_ab); let auxres = compose_and_run(config, &abs_ab, aux_args, ~[], - config.compile_lib_path, option::None); + config.compile_lib_path, None); if auxres.status != 0 { fatal_procres( fmt!("auxiliary build of %s failed to compile: ", @@ -491,7 +501,8 @@ fn make_lib_name(config: config, auxfile: &Path, testfile: &Path) -> Path { } fn make_exe_name(config: config, testfile: &Path) -> Path { - Path(output_base_name(config, testfile).to_str() + os::exe_suffix()) + Path(output_base_name(config, testfile).to_str() + + str::from_slice(os::EXE_SUFFIX)) } fn make_run_args(config: config, _props: test_props, testfile: &Path) -> @@ -501,8 +512,8 @@ fn make_run_args(config: config, _props: test_props, testfile: &Path) -> // then split apart its command let runtool = match config.runtool { - option::Some(s) => option::Some(s), - option::None => option::None + Some(s) => Some(s), + None => None }; split_maybe_args(runtool) }; @@ -517,8 +528,8 @@ fn split_maybe_args(argstr: Option<~str>) -> ~[~str] { } match argstr { - option::Some(s) => rm_whitespace(str::split_char(s, ' ')), - option::None => ~[] + Some(s) => rm_whitespace(str::split_char(s, ' ')), + None => ~[] } } diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs index 569d89fd3fe52..fe3bf4672c727 100644 --- a/src/compiletest/util.rs +++ b/src/compiletest/util.rs @@ -8,8 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use io; +use os; use os::getenv; +use common; use common::config; fn make_new_path(path: ~str) -> ~str { @@ -17,10 +20,10 @@ fn make_new_path(path: ~str) -> ~str { // Windows just uses PATH as the library search path, so we have to // maintain the current value while adding our own match getenv(lib_path_env_var()) { - option::Some(curr) => { + Some(curr) => { fmt!("%s%s%s", path, path_div(), curr) } - option::None => path + None => path } } diff --git a/src/driver/driver.rs b/src/driver/driver.rs index 5801c23f81462..0c1cc566fe2ec 100644 --- a/src/driver/driver.rs +++ b/src/driver/driver.rs @@ -12,18 +12,18 @@ extern mod core(vers = "0.6"); #[cfg(cargo)] -extern mod self(name = "cargo", vers = "0.6"); +extern mod this(name = "cargo", vers = "0.6"); #[cfg(fuzzer)] -extern mod self(name = "fuzzer", vers = "0.6"); +extern mod this(name = "fuzzer", vers = "0.6"); #[cfg(rustdoc)] -extern mod self(name = "rustdoc", vers = "0.6"); +extern mod this(name = "rustdoc", vers = "0.6"); #[cfg(rusti)] -extern mod self(name = "rusti", vers = "0.6"); +extern mod this(name = "rusti", vers = "0.6"); #[cfg(rustc)] -extern mod self(name = "rustc", vers = "0.6"); +extern mod this(name = "rustc", vers = "0.6"); -fn main() { self::main() } \ No newline at end of file +fn main() { this::main() } diff --git a/src/etc/sugarise-doc-comments.py b/src/etc/sugarise-doc-comments.py index 04c8a4ebff25e..bd21447ffcc50 100755 --- a/src/etc/sugarise-doc-comments.py +++ b/src/etc/sugarise-doc-comments.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # this script attempts to turn doc comment attributes (#[doc = "..."]) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index d71b9fbcf959d..af308f23a3182 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -2,7 +2,7 @@ " Language: Rust " Maintainer: Patrick Walton " Maintainer: Ben Blum -" Last Change: 2012 Dec 14 +" Last Change: 2012 Dec 25 if version < 600 syntax clear @@ -44,8 +44,8 @@ syn keyword rustType off_t dev_t ino_t pid_t mode_t ssize_t syn keyword rustTrait Const Copy Send Owned " inherent traits syn keyword rustTrait Eq Ord Num Ptr -syn keyword rustTrait Add Sub Mul Div Modulo Neg BitAnd BitOr BitXor -syn keyword rustTrait Shl Shr Index +syn keyword rustTrait Drop Add Sub Mul Div Modulo Neg BitAnd BitOr +syn keyword rustTrait BitXor Shl Shr Index syn keyword rustSelf self syn keyword rustBoolean true false diff --git a/src/libcargo/cargo.rc b/src/libcargo/cargo.rc index d4e68746fd4c4..f089c9e04c40d 100644 --- a/src/libcargo/cargo.rc +++ b/src/libcargo/cargo.rc @@ -401,7 +401,7 @@ fn load_crate(filename: &Path) -> Option { let e = @{ mut deps: ~[] }; - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_view_item: |a| goto_view_item(sess, e, a), visit_item: |a| goto_item(e, a), .. *visit::default_simple_visitor() @@ -805,7 +805,7 @@ fn install_one_crate(c: &Cargo, path: &Path, cf: &Path) { Some(bp) => bp }; let newv = os::list_dir_path(&buildpath); - let exec_suffix = os::exe_suffix(); + let exec_suffix = str::from_slice(os::EXE_SUFFIX); for newv.each |ct| { if (exec_suffix != ~"" && str::ends_with(ct.to_str(), exec_suffix)) || diff --git a/src/libcargo/pgp.rs b/src/libcargo/pgp.rs index 6659ed031ca79..e05260bace208 100644 --- a/src/libcargo/pgp.rs +++ b/src/libcargo/pgp.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::os; +use core::run; + fn gpgv(args: ~[~str]) -> { status: int, out: ~str, err: ~str } { return run::program_output(~"gpgv", args); } diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs index dc5faf49ea4c7..4f3f63c83fcd6 100644 --- a/src/libcore/at_vec.rs +++ b/src/libcore/at_vec.rs @@ -15,13 +15,18 @@ #[forbid(deprecated_pattern)]; use cast::transmute; +use iter; +use libc; use ptr::addr_of; +use sys; +use uint; +use vec; /// Code for dealing with @-vectors. This is pretty incomplete, and /// contains a bunch of duplication from the code for ~-vectors. #[abi = "cdecl"] -extern mod rustrt { +pub extern mod rustrt { #[legacy_exports]; fn vec_reserve_shared_actual(++t: *sys::TypeDesc, ++v: **vec::raw::VecRepr, @@ -29,7 +34,7 @@ extern mod rustrt { } #[abi = "rust-intrinsic"] -extern mod rusti { +pub extern mod rusti { #[legacy_exports]; fn move_val_init(dst: &mut T, -src: T); } @@ -95,7 +100,7 @@ pub pure fn build(builder: &fn(push: pure fn(v: A))) -> @[A] { #[inline(always)] pub pure fn build_sized_opt(size: Option, builder: &fn(push: pure fn(v: A))) -> @[A] { - build_sized(size.get_default(4), builder) + build_sized(size.get_or_default(4), builder) } // Appending @@ -157,6 +162,13 @@ pub mod traits { pub mod traits {} pub mod raw { + use at_vec::{rusti, rustrt}; + use libc; + use ptr; + use sys; + use uint; + use vec; + pub type VecRepr = vec::raw::VecRepr; pub type SliceRepr = vec::raw::SliceRepr; diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index 6d2ed9b423e64..3181cb24ea787 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -16,6 +16,8 @@ //! Boolean logic +use bool; +use cmp; use cmp::Eq; /// Negation / inverse diff --git a/src/libcore/char.rs b/src/libcore/char.rs index f16268c34583f..4fe60810dc39b 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -14,7 +14,12 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use char; use cmp::Eq; +use str; +use u32; +use uint; +use unicode; /* Lu Uppercase_Letter an uppercase letter diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs index df8063772a6d2..9ea48a45d3c33 100644 --- a/src/libcore/condition.rs +++ b/src/libcore/condition.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use task; +use task::local_data::{local_data_pop, local_data_set}; + // helper for transmutation, shown below. -type RustClosure = (int,int); +type RustClosure = (int, int); + pub struct Handler { handle: RustClosure, prev: Option<@Handler>, @@ -17,109 +21,97 @@ pub struct Handler { pub struct Condition { name: &static/str, - key: task::local_data::LocalDataKey> + key: task::local_data::LocalDataKey> } -impl Condition { - - fn trap(&self, h: &self/fn(&T) ->U) -> Trap/&self { +impl Condition { + fn trap(&self, h: &self/fn(T) -> U) -> Trap/&self { unsafe { let p : *RustClosure = ::cast::transmute(&h); let prev = task::local_data::local_data_get(self.key); - let h = @Handler{handle: *p, prev: prev}; - move Trap { cond: self, handler: h } + let h = @Handler { handle: *p, prev: prev }; + Trap { cond: self, handler: h } } } - fn raise(t:&T) -> U { - do self.raise_default(t) { - fail fmt!("Unhandled condition: %s: %?", - self.name, - t); - } + fn raise(t: T) -> U { + let msg = fmt!("Unhandled condition: %s: %?", self.name, t); + self.raise_default(t, || fail msg) } - fn raise_default(t:&T, default: fn() -> U) -> U { + fn raise_default(t: T, default: &fn() -> U) -> U { unsafe { - match task::local_data::local_data_pop(self.key) { + match local_data_pop(self.key) { None => { debug!("Condition.raise: found no handler"); default() } - Some(handler) => { debug!("Condition.raise: found handler"); match handler.prev { - None => (), - Some(hp) => - task::local_data::local_data_set(self.key, hp) + None => {} + Some(hp) => local_data_set(self.key, hp) } - let handle : &fn(&T) -> U = + let handle : &fn(T) -> U = ::cast::transmute(handler.handle); let u = handle(t); - task::local_data::local_data_set(self.key, - handler); - move u + local_data_set(self.key, handler); + u } } } } } - - struct Trap { - cond: &Condition, + cond: &Condition, handler: @Handler } -impl Trap { +impl Trap { fn in(&self, inner: &self/fn() -> V) -> V { unsafe { let _g = Guard { cond: self.cond }; debug!("Trap: pushing handler to TLS"); - task::local_data::local_data_set(self.cond.key, self.handler); + local_data_set(self.cond.key, self.handler); inner() } } } struct Guard { - cond: &Condition, - drop { + cond: &Condition +} + +impl Guard : Drop { + fn finalize(&self) { unsafe { debug!("Guard: popping handler from TLS"); - let curr = task::local_data::local_data_pop(self.cond.key); + let curr = local_data_pop(self.cond.key); match curr { - None => (), - Some(h) => - match h.prev { - None => (), - Some(hp) => { - task::local_data::local_data_set(self.cond.key, hp) - } + None => {} + Some(h) => match h.prev { + None => {} + Some(hp) => local_data_set(self.cond.key, hp) } } } } } - #[cfg(test)] mod test { - condition! { sadness: int -> int; } fn trouble(i: int) { - debug!("trouble: raising conition"); - let j = sadness::cond.raise(&i); + debug!("trouble: raising condition"); + let j = sadness::cond.raise(i); debug!("trouble: handler recovered with %d", j); } fn nested_trap_test_inner() { - let mut inner_trapped = false; do sadness::cond.trap(|_j| { @@ -136,7 +128,6 @@ mod test { #[test] fn nested_trap_test_outer() { - let mut outer_trapped = false; do sadness::cond.trap(|_j| { @@ -152,7 +143,6 @@ mod test { } fn nested_reraise_trap_test_inner() { - let mut inner_trapped = false; do sadness::cond.trap(|_j| { @@ -160,7 +150,7 @@ mod test { inner_trapped = true; let i = 10; debug!("nested_reraise_trap_test_inner: handler re-raising"); - sadness::cond.raise(&i) + sadness::cond.raise(i) }).in { debug!("nested_reraise_trap_test_inner: in protected block"); trouble(1); @@ -171,7 +161,6 @@ mod test { #[test] fn nested_reraise_trap_test_outer() { - let mut outer_trapped = false; do sadness::cond.trap(|_j| { @@ -187,12 +176,11 @@ mod test { #[test] fn test_default() { - let mut trapped = false; do sadness::cond.trap(|j| { debug!("test_default: in handler"); - sadness::cond.raise_default(j, || {trapped=true; 5}) + sadness::cond.raise_default(j, || { trapped=true; 5 }) }).in { debug!("test_default: in protected block"); trouble(1); @@ -200,5 +188,4 @@ mod test { assert trapped; } - } diff --git a/src/libcore/core.rc b/src/libcore/core.rc index bac6bae90a0ab..13e0e3002424a 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -235,7 +235,7 @@ mod stackwalk; // 'core' so that macro-expanded references to core::error and such // can be resolved within libcore. #[doc(hidden)] // FIXME #3538 -mod core { +pub mod core { pub const error : u32 = 1_u32; pub const warn : u32 = 2_u32; pub const info : u32 = 3_u32; @@ -246,14 +246,6 @@ mod core { } -// Similar to above. Some magic to make core testable. -#[cfg(test)] -mod std { - extern mod std(vers = "0.6"); - pub use std::std::test; -} - - // Local Variables: // mode: rust; // fill-column: 78; diff --git a/src/libcore/dlist.rs b/src/libcore/dlist.rs index 35ff98ac17dae..89789a38b24da 100644 --- a/src/libcore/dlist.rs +++ b/src/libcore/dlist.rs @@ -22,6 +22,10 @@ Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate. #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use managed; +use option; +use vec; + type DListLink = Option>; enum DListNode = @{ @@ -469,6 +473,10 @@ impl DList { #[cfg(test)] mod tests { #[legacy_exports]; + + use iter; + use vec; + #[test] fn test_dlist_concat() { let a = from_vec(~[1,2]); diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs index 236d6bce9f033..dd6b072112139 100644 --- a/src/libcore/dvec.rs +++ b/src/libcore/dvec.rs @@ -23,8 +23,10 @@ Note that recursive use is not permitted. #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use cast; use cast::reinterpret_cast; use ptr::null; +use vec; /** * A growable, modifiable vector type that accumulates elements into a diff --git a/src/libcore/either.rs b/src/libcore/either.rs index 6c0254ff77902..b2c70916a0003 100644 --- a/src/libcore/either.rs +++ b/src/libcore/either.rs @@ -14,8 +14,11 @@ //! A type that represents one of two alternatives +use cmp; use cmp::Eq; +use result; use result::Result; +use vec; /// The either type #[deriving_eq] @@ -66,8 +69,7 @@ pub fn rights(eithers: &[Either]) -> ~[U] { } } -// XXX bad copies. take arg by val -pub fn partition(eithers: &[Either]) +pub fn partition(eithers: ~[Either]) -> (~[T], ~[U]) { /*! * Extracts from a vector of either all the left values and right values @@ -78,27 +80,25 @@ pub fn partition(eithers: &[Either]) let mut lefts: ~[T] = ~[]; let mut rights: ~[U] = ~[]; - for vec::each(eithers) |elt| { - match *elt { - Left(copy l) => lefts.push(l), - Right(copy r) => rights.push(r) + do vec::consume(eithers) |_i, elt| { + match elt { + Left(l) => lefts.push(l), + Right(r) => rights.push(r) } } return (move lefts, move rights); } -// XXX bad copies -pub pure fn flip(eith: &Either) -> Either { +pub pure fn flip(eith: Either) -> Either { //! Flips between left and right of a given either - match *eith { - Right(copy r) => Left(r), - Left(copy l) => Right(l) + match eith { + Right(r) => Left(r), + Left(l) => Right(l) } } -// XXX bad copies -pub pure fn to_result(eith: &Either) +pub pure fn to_result(eith: Either) -> Result { /*! * Converts either::t to a result::t @@ -107,9 +107,9 @@ pub pure fn to_result(eith: &Either) * an ok result, and the "left" choice a fail */ - match *eith { - Right(copy r) => result::Ok(r), - Left(copy l) => result::Err(l) + match eith { + Right(r) => result::Ok(r), + Left(l) => result::Err(l) } } @@ -125,7 +125,6 @@ pub pure fn is_right(eith: &Either) -> bool { match *eith { Right(_) => true, _ => false } } -// tjc: fix the next two after a snapshot pub pure fn unwrap_left(eith: Either) -> T { //! Retrieves the value in the left branch. Fails if the either is Right. diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs index 1c9ad6ba81a2a..312fc18a033c1 100644 --- a/src/libcore/extfmt.rs +++ b/src/libcore/extfmt.rs @@ -82,7 +82,7 @@ debug!("hello, %s!", "world"); use cmp::Eq; use option::{Some, None}; - +use str; /* * We have a 'ct' (compile-time) module that parses format strings into a @@ -98,8 +98,17 @@ use option::{Some, None}; // Functions used by the fmt extension at compile time #[doc(hidden)] pub mod ct { + use char; + use str; + use vec; + + #[deriving_eq] pub enum Signedness { Signed, Unsigned, } + + #[deriving_eq] pub enum Caseness { CaseUpper, CaseLower, } + + #[deriving_eq] pub enum Ty { TyBool, TyStr, @@ -111,6 +120,8 @@ pub mod ct { TyFloat, TyPoly, } + + #[deriving_eq] pub enum Flag { FlagLeftJustify, FlagLeftZeroPad, @@ -118,6 +129,8 @@ pub mod ct { FlagSignAlways, FlagAlternate, } + + #[deriving_eq] pub enum Count { CountIs(uint), CountIsParam(uint), @@ -125,204 +138,324 @@ pub mod ct { CountImplied, } - // A formatted conversion from an expression to a string - pub type Conv = - {param: Option, - flags: ~[Flag], - width: Count, - precision: Count, - ty: Ty}; + #[deriving_eq] + struct Parsed { + val: T, + next: uint + } + impl Parsed { + static pure fn new(val: T, next: uint) -> Parsed { + Parsed {val: val, next: next} + } + } + + // A formatted conversion from an expression to a string + #[deriving_eq] + pub struct Conv { + param: Option, + flags: ~[Flag], + width: Count, + precision: Count, + ty: Ty + } // A fragment of the output sequence + #[deriving_eq] pub enum Piece { PieceString(~str), PieceConv(Conv), } - pub type ErrorFn = fn@(&str) -> ! ; + + pub type ErrorFn = @fn(&str) -> !; pub fn parse_fmt_string(s: &str, err: ErrorFn) -> ~[Piece] { - let mut pieces: ~[Piece] = ~[]; - let lim = str::len(s); - let mut buf = ~""; - fn flush_buf(buf: ~str, pieces: &mut ~[Piece]) -> ~str { - if buf.len() > 0 { - let piece = PieceString(move buf); - pieces.push(move piece); + fn push_slice(ps: &mut ~[Piece], s: &str, from: uint, to: uint) { + if to > from { + ps.push(PieceString(s.slice(from, to))); } - return ~""; } + + let lim = s.len(); + let mut h = 0; let mut i = 0; + let mut pieces = ~[]; + while i < lim { - let size = str::utf8_char_width(s[i]); - let curr = str::slice(s, i, i+size); - if curr == ~"%" { + if s[i] == '%' as u8 { i += 1; + if i >= lim { err(~"unterminated conversion at end of string"); - } - let curr2 = str::slice(s, i, i+1); - if curr2 == ~"%" { - buf += curr2; + } else if s[i] == '%' as u8 { + push_slice(&mut pieces, s, h, i); i += 1; } else { - buf = flush_buf(move buf, &mut pieces); - let rs = parse_conversion(s, i, lim, err); - pieces.push(copy rs.piece); - i = rs.next; + push_slice(&mut pieces, s, h, i - 1); + let Parsed {val, next} = parse_conversion(s, i, lim, err); + pieces.push(val); + i = next; } - } else { buf += curr; i += size; } + + h = i; + } else { + i += str::utf8_char_width(s[i]); + } } - flush_buf(move buf, &mut pieces); - move pieces + + push_slice(&mut pieces, s, h, i); + pieces } - pub fn peek_num(s: &str, i: uint, lim: uint) -> - Option<{num: uint, next: uint}> { - let mut j = i; - let mut accum = 0u; + + pub fn peek_num(s: &str, i: uint, lim: uint) -> Option> { + let mut i = i; + let mut accum = 0; let mut found = false; - while j < lim { - match char::to_digit(s[j] as char, 10) { + + while i < lim { + match char::to_digit(s[i] as char, 10) { Some(x) => { found = true; accum *= 10; accum += x; - j += 1; - }, + i += 1; + } None => break } } + if found { - Some({num: accum, next: j}) + Some(Parsed::new(accum, i)) } else { None } } - pub fn parse_conversion(s: &str, i: uint, lim: uint, - err: ErrorFn) -> - {piece: Piece, next: uint} { - let parm = parse_parameter(s, i, lim); - let flags = parse_flags(s, parm.next, lim); - let width = parse_count(s, flags.next, lim); + + pub fn parse_conversion(s: &str, i: uint, lim: uint, err: ErrorFn) -> + Parsed { + let param = parse_parameter(s, i, lim); + // avoid copying ~[Flag] by destructuring + let Parsed {val: flags_val, next: flags_next} = parse_flags(s, + param.next, lim); + let width = parse_count(s, flags_next, lim); let prec = parse_precision(s, width.next, lim); let ty = parse_type(s, prec.next, lim, err); - return {piece: - PieceConv({param: parm.param, - flags: copy flags.flags, - width: width.count, - precision: prec.count, - ty: ty.ty}), - next: ty.next}; + + Parsed::new(PieceConv(Conv { + param: param.val, + flags: flags_val, + width: width.val, + precision: prec.val, + ty: ty.val}), ty.next) } + pub fn parse_parameter(s: &str, i: uint, lim: uint) -> - {param: Option, next: uint} { - if i >= lim { return {param: None, next: i}; } - let num = peek_num(s, i, lim); - return match num { - None => {param: None, next: i}, - Some(t) => { - let n = t.num; - let j = t.next; - if j < lim && s[j] == '$' as u8 { - {param: Some(n), next: j + 1} - } else { {param: None, next: i} } - } + Parsed> { + if i >= lim { return Parsed::new(None, i); } + + match peek_num(s, i, lim) { + Some(num) if num.next < lim && s[num.next] == '$' as u8 => + Parsed::new(Some(num.val), num.next + 1), + _ => Parsed::new(None, i) + } + } + + pub fn parse_flags(s: &str, i: uint, lim: uint) -> Parsed<~[Flag]> { + let mut i = i; + let mut flags = ~[]; + + while i < lim { + let f = match s[i] { + '-' as u8 => FlagLeftJustify, + '0' as u8 => FlagLeftZeroPad, + ' ' as u8 => FlagSpaceForSign, + '+' as u8 => FlagSignAlways, + '#' as u8 => FlagAlternate, + _ => break }; + + flags.push(f); + i += 1; + } + + Parsed::new(flags, i) } - pub fn parse_flags(s: &str, i: uint, lim: uint) -> - {flags: ~[Flag], next: uint} { - let noflags: ~[Flag] = ~[]; - if i >= lim { return {flags: move noflags, next: i}; } - - fn more(f: Flag, s: &str, i: uint, lim: uint) -> - {flags: ~[Flag], next: uint} { - let next = parse_flags(s, i + 1u, lim); - let rest = copy next.flags; - let j = next.next; - let curr: ~[Flag] = ~[f]; - return {flags: vec::append(move curr, rest), next: j}; + + pub fn parse_count(s: &str, i: uint, lim: uint) -> Parsed { + if i >= lim { + Parsed::new(CountImplied, i) + } else if s[i] == '*' as u8 { + let param = parse_parameter(s, i + 1, lim); + let j = param.next; + + match param.val { + None => Parsed::new(CountIsNextParam, j), + Some(n) => Parsed::new(CountIsParam(n), j) + } + } else { + match peek_num(s, i, lim) { + None => Parsed::new(CountImplied, i), + Some(num) => Parsed::new(CountIs(num.val), num.next) + } } - // Unfortunate, but because s is borrowed, can't use a closure - // fn more(f: Flag, s: &str) { more_(f, s, i, lim); } - let f = s[i]; - return if f == '-' as u8 { - more(FlagLeftJustify, s, i, lim) - } else if f == '0' as u8 { - more(FlagLeftZeroPad, s, i, lim) - } else if f == ' ' as u8 { - more(FlagSpaceForSign, s, i, lim) - } else if f == '+' as u8 { - more(FlagSignAlways, s, i, lim) - } else if f == '#' as u8 { - more(FlagAlternate, s, i, lim) - } else { {flags: move noflags, next: i} }; - } - pub fn parse_count(s: &str, i: uint, lim: uint) - -> {count: Count, next: uint} { - return if i >= lim { - {count: CountImplied, next: i} - } else if s[i] == '*' as u8 { - let param = parse_parameter(s, i + 1, lim); - let j = param.next; - match param.param { - None => {count: CountIsNextParam, next: j}, - Some(n) => {count: CountIsParam(n), next: j} - } - } else { - let num = peek_num(s, i, lim); - match num { - None => {count: CountImplied, next: i}, - Some(num) => { - count: CountIs(num.num), - next: num.next - } - } - }; } - pub fn parse_precision(s: &str, i: uint, lim: uint) -> - {count: Count, next: uint} { - return if i >= lim { - {count: CountImplied, next: i} - } else if s[i] == '.' as u8 { - let count = parse_count(s, i + 1u, lim); + pub fn parse_precision(s: &str, i: uint, lim: uint) -> Parsed { + if i < lim && s[i] == '.' as u8 { + let count = parse_count(s, i + 1, lim); - // If there were no digits specified, i.e. the precision - // was ".", then the precision is 0 - match count.count { - CountImplied => {count: CountIs(0), next: count.next}, - _ => count - } - } else { {count: CountImplied, next: i} }; + // If there were no digits specified, i.e. the precision + // was ".", then the precision is 0 + match count.val { + CountImplied => Parsed::new(CountIs(0), count.next), + _ => count + } + } else { + Parsed::new(CountImplied, i) + } } + pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) -> - {ty: Ty, next: uint} { + Parsed { if i >= lim { err(~"missing type in conversion"); } - let tstr = str::slice(s, i, i+1u); + // FIXME (#2249): Do we really want two signed types here? // How important is it to be printf compatible? - let t = - if tstr == ~"b" { - TyBool - } else if tstr == ~"s" { - TyStr - } else if tstr == ~"c" { - TyChar - } else if tstr == ~"d" || tstr == ~"i" { - TyInt(Signed) - } else if tstr == ~"u" { - TyInt(Unsigned) - } else if tstr == ~"x" { - TyHex(CaseLower) - } else if tstr == ~"X" { - TyHex(CaseUpper) - } else if tstr == ~"t" { - TyBits - } else if tstr == ~"o" { - TyOctal - } else if tstr == ~"f" { - TyFloat - } else if tstr == ~"?" { - TyPoly - } else { err(~"unknown type in conversion: " + tstr) }; - return {ty: t, next: i + 1u}; + let t = match s[i] { + 'b' as u8 => TyBool, + 's' as u8 => TyStr, + 'c' as u8 => TyChar, + 'd' as u8 | 'i' as u8 => TyInt(Signed), + 'u' as u8 => TyInt(Unsigned), + 'x' as u8 => TyHex(CaseLower), + 'X' as u8 => TyHex(CaseUpper), + 't' as u8 => TyBits, + 'o' as u8 => TyOctal, + 'f' as u8 => TyFloat, + '?' as u8 => TyPoly, + _ => err(~"unknown type in conversion: " + s.substr(i, 1)) + }; + + Parsed::new(t, i + 1) + } + + #[cfg(test)] + fn die(s: &str) -> ! { fail s.to_owned() } + + #[test] + fn test_parse_count() { + fn test(s: &str, count: Count, next: uint) -> bool { + parse_count(s, 0, s.len()) == Parsed::new(count, next) + } + + assert test("", CountImplied, 0); + assert test("*", CountIsNextParam, 1); + assert test("*1", CountIsNextParam, 1); + assert test("*1$", CountIsParam(1), 3); + assert test("123", CountIs(123), 3); + } + + #[test] + fn test_parse_flags() { + fn pack(fs: &[Flag]) -> uint { + fs.foldl(0, |&p, &f| p | (1 << f as uint)) + } + + fn test(s: &str, flags: &[Flag], next: uint) { + let f = parse_flags(s, 0, s.len()); + assert pack(f.val) == pack(flags); + assert f.next == next; + } + + test("", [], 0); + test("!#-+ 0", [], 0); + test("#-+", [FlagAlternate, FlagLeftJustify, FlagSignAlways], 3); + test(" 0", [FlagSpaceForSign, FlagLeftZeroPad], 2); + } + + #[test] + fn test_parse_fmt_string() { + assert parse_fmt_string("foo %s bar", die) == ~[ + PieceString(~"foo "), + PieceConv(Conv {param: None, flags: ~[], width: CountImplied, + precision: CountImplied, ty: TyStr}), + PieceString(~" bar")]; + + assert parse_fmt_string("%s", die) == ~[ + PieceConv(Conv {param: None, flags: ~[], width: CountImplied, + precision: CountImplied, ty: TyStr })]; + + assert parse_fmt_string("%%%%", die) == ~[ + PieceString(~"%"), PieceString(~"%")]; + } + + #[test] + fn test_parse_parameter() { + fn test(s: &str, param: Option, next: uint) -> bool { + parse_parameter(s, 0, s.len()) == Parsed::new(param, next) + } + + assert test("", None, 0); + assert test("foo", None, 0); + assert test("123", None, 0); + assert test("123$", Some(123), 4); + } + + #[test] + fn test_parse_precision() { + fn test(s: &str, count: Count, next: uint) -> bool { + parse_precision(s, 0, s.len()) == Parsed::new(count, next) + } + + assert test("", CountImplied, 0); + assert test(".", CountIs(0), 1); + assert test(".*", CountIsNextParam, 2); + assert test(".*1", CountIsNextParam, 2); + assert test(".*1$", CountIsParam(1), 4); + assert test(".123", CountIs(123), 4); + } + + #[test] + fn test_parse_type() { + fn test(s: &str, ty: Ty) -> bool { + parse_type(s, 0, s.len(), die) == Parsed::new(ty, 1) + } + + assert test("b", TyBool); + assert test("c", TyChar); + assert test("d", TyInt(Signed)); + assert test("f", TyFloat); + assert test("i", TyInt(Signed)); + assert test("o", TyOctal); + assert test("s", TyStr); + assert test("t", TyBits); + assert test("x", TyHex(CaseLower)); + assert test("X", TyHex(CaseUpper)); + assert test("?", TyPoly); + } + + #[test] + #[should_fail] + fn test_parse_type_missing() { + parse_type("", 0, 0, die); + } + + #[test] + #[should_fail] + fn test_parse_type_unknown() { + parse_type("!", 0, 1, die); + } + + #[test] + fn test_peek_num() { + let s1 = ""; + assert peek_num(s1, 0, s1.len()).is_none(); + + let s2 = "foo"; + assert peek_num(s2, 0, s2.len()).is_none(); + + let s3 = "123"; + assert peek_num(s3, 0, s3.len()) == Some(Parsed::new(123, 3)); + + let s4 = "123foo"; + assert peek_num(s4, 0, s4.len()) == Some(Parsed::new(123, 3)); } } @@ -332,6 +465,12 @@ pub mod ct { // implement it 0this way, I think. #[doc(hidden)] pub mod rt { + use float; + use str; + use sys; + use uint; + use vec; + pub const flag_none : u32 = 0u32; pub const flag_left_justify : u32 = 0b00000000000001u32; pub const flag_left_zero_pad : u32 = 0b00000000000010u32; diff --git a/src/libcore/f32.rs b/src/libcore/f32.rs index 5e34c7c5530b6..ce90f757769be 100644 --- a/src/libcore/f32.rs +++ b/src/libcore/f32.rs @@ -14,6 +14,9 @@ //! Operations and constants for `f32` +use cmp; +use num; + pub use cmath::c_float_utils::*; pub use cmath::c_float_targ_consts::*; diff --git a/src/libcore/f64.rs b/src/libcore/f64.rs index 2e35d0360b62e..97d9e8e758452 100644 --- a/src/libcore/f64.rs +++ b/src/libcore/f64.rs @@ -14,6 +14,11 @@ //! Operations and constants for `f64` +use cmath; +use cmp; +use libc; +use num; + pub use cmath::c_double_utils::*; pub use cmath::c_double_targ_consts::*; diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs index 506937f053fd0..220b1a653af08 100644 --- a/src/libcore/flate.rs +++ b/src/libcore/flate.rs @@ -18,7 +18,11 @@ Simple compression #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use libc; use libc::{c_void, size_t, c_int}; +use ptr; +use rand; +use vec; extern mod rustrt { fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void, @@ -88,8 +92,8 @@ fn test_flate_round_trip() { } debug!("de/inflate of %u bytes of random word-sequences", in.len()); - let cmp = flate::deflate_bytes(in); - let out = flate::inflate_bytes(cmp); + let cmp = deflate_bytes(in); + let out = inflate_bytes(cmp); debug!("%u bytes deflated to %u (%.1f%% size)", in.len(), cmp.len(), 100.0 * ((cmp.len() as float) / (in.len() as float))); diff --git a/src/libcore/float.rs b/src/libcore/float.rs index 02ba4419bcc3e..34269b8874899 100644 --- a/src/libcore/float.rs +++ b/src/libcore/float.rs @@ -26,6 +26,14 @@ use m_float = f64; +use cmp::{Eq, Ord}; +use cmp; +use f64; +use num; +use num::Num::from_int; +use str; +use uint; + pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt}; pub use f64::logarithm; pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor}; @@ -35,8 +43,6 @@ pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix}; pub use f64::{modf, pow, round, sinh, tanh, tgamma, trunc}; pub use f64::signbit; pub use f64::{j0, j1, jn, y0, y1, yn}; -use cmp::{Eq, Ord}; -use num::Num::from_int; pub const NaN: float = 0.0/0.0; diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs index 81936d1777498..89f5a4eb8f066 100644 --- a/src/libcore/gc.rs +++ b/src/libcore/gc.rs @@ -39,10 +39,15 @@ with destructors. #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; -pub use stackwalk::Word; -use libc::size_t; -use libc::uintptr_t; +use cast; +use io; +use libc::{size_t, uintptr_t}; +use ptr; use send_map::linear::LinearMap; +use stackwalk; +use sys; + +pub use stackwalk::Word; // Mirrors rust_stack.h stk_seg struct StackSegment { diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs index 5331019e5f335..d3d6c5ae2424b 100644 --- a/src/libcore/hash.rs +++ b/src/libcore/hash.rs @@ -23,9 +23,12 @@ * CPRNG like rand::rng. */ -use io::Writer; -use io::WriterUtil; +use io; +use io::{Writer, WriterUtil}; +use os; use to_bytes::IterBytes; +use uint; +use vec; /** * Types that can meaningfully be hashed should implement this. diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index c3fe24fff321b..d04123fdb2b2b 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -14,9 +14,16 @@ use T = self::inst::T; +use char; use cmp::{Eq, Ord}; +use cmp; use from_str::FromStr; +use iter; +use num; use num::Num::from_int; +use str; +use uint; +use vec; pub const bits : uint = inst::bits; pub const bytes : uint = (inst::bits / 8); diff --git a/src/libcore/int-template/i16.rs b/src/libcore/int-template/i16.rs index 3effa40bd1607..da60b567f665a 100644 --- a/src/libcore/int-template/i16.rs +++ b/src/libcore/int-template/i16.rs @@ -12,5 +12,5 @@ mod inst { pub type T = i16; - pub const bits: uint = u16::bits; -} \ No newline at end of file + pub const bits: uint = ::u16::bits; +} diff --git a/src/libcore/int-template/i32.rs b/src/libcore/int-template/i32.rs index 710868fcb8da0..1bc45bb71af7e 100644 --- a/src/libcore/int-template/i32.rs +++ b/src/libcore/int-template/i32.rs @@ -12,5 +12,5 @@ mod inst { pub type T = i32; - pub const bits: uint = u32::bits; + pub const bits: uint = ::u32::bits; } diff --git a/src/libcore/int-template/i64.rs b/src/libcore/int-template/i64.rs index 0612322dab6b0..83d15aa857d95 100644 --- a/src/libcore/int-template/i64.rs +++ b/src/libcore/int-template/i64.rs @@ -12,5 +12,5 @@ mod inst { pub type T = i64; - pub const bits: uint = u64::bits; -} \ No newline at end of file + pub const bits: uint = ::u64::bits; +} diff --git a/src/libcore/int-template/i8.rs b/src/libcore/int-template/i8.rs index 37d7e610566a1..740442ed725be 100644 --- a/src/libcore/int-template/i8.rs +++ b/src/libcore/int-template/i8.rs @@ -12,5 +12,5 @@ mod inst { pub type T = i8; - pub const bits: uint = u8::bits; -} \ No newline at end of file + pub const bits: uint = ::u8::bits; +} diff --git a/src/libcore/int-template/int.rs b/src/libcore/int-template/int.rs index 61a7c3bd07ab3..9e06cc95270e1 100644 --- a/src/libcore/int-template/int.rs +++ b/src/libcore/int-template/int.rs @@ -14,7 +14,7 @@ pub use self::inst::pow; mod inst { pub type T = int; - pub const bits: uint = uint::bits; + pub const bits: uint = ::uint::bits; /// Returns `base` raised to the power of `exponent` pub pure fn pow(base: int, exponent: uint) -> int { diff --git a/src/libcore/io.rs b/src/libcore/io.rs index e76eb9f2f99d8..ade4f9d7fc82b 100644 --- a/src/libcore/io.rs +++ b/src/libcore/io.rs @@ -21,9 +21,18 @@ use result::Result; use cmp::Eq; use dvec::DVec; +use int; +use libc; use libc::{c_int, c_long, c_uint, c_void, size_t, ssize_t}; use libc::consts::os::posix88::*; use libc::consts::os::extra::*; +use option; +use os; +use ptr; +use result; +use str; +use uint; +use vec; #[allow(non_camel_case_types)] // not sure what to do about this type fd_t = c_int; @@ -1019,6 +1028,9 @@ pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> { // fsync related pub mod fsync { + use libc; + use option; + use os; pub enum Level { // whatever fsync does on that platform @@ -1101,6 +1113,12 @@ pub mod fsync { #[cfg(test)] mod tests { + use i32; + use io; + use result; + use str; + use u64; + use vec; #[test] fn test_simple() { diff --git a/src/libcore/iter-trait.rs b/src/libcore/iter-trait.rs index 644a0fd76b754..59eb9fbae8eea 100644 --- a/src/libcore/iter-trait.rs +++ b/src/libcore/iter-trait.rs @@ -16,6 +16,7 @@ #[forbid(deprecated_pattern)]; use cmp::{Eq, Ord}; +use iter; use self::inst::{IMPL_T, EACH, SIZE_HINT}; diff --git a/src/libcore/iter-trait/dlist.rs b/src/libcore/iter-trait/dlist.rs index ce5f775878cf3..42ed4b5f73cc0 100644 --- a/src/libcore/iter-trait/dlist.rs +++ b/src/libcore/iter-trait/dlist.rs @@ -9,6 +9,10 @@ // except according to those terms. mod inst { + use dlist; + use managed; + use option; + #[allow(non_camel_case_types)] pub type IMPL_T = dlist::DList; @@ -45,4 +49,4 @@ mod inst { pub pure fn SIZE_HINT(self: &IMPL_T) -> Option { Some(self.len()) } -} \ No newline at end of file +} diff --git a/src/libcore/iter-trait/dvec.rs b/src/libcore/iter-trait/dvec.rs index 9b7016c17d5c1..f338578d1432a 100644 --- a/src/libcore/iter-trait/dvec.rs +++ b/src/libcore/iter-trait/dvec.rs @@ -9,6 +9,8 @@ // except according to those terms. mod inst { + use dvec; + #[allow(non_camel_case_types)] pub type IMPL_T = dvec::DVec; @@ -29,4 +31,4 @@ mod inst { pub pure fn SIZE_HINT(self: &IMPL_T) -> Option { Some(self.len()) } -} \ No newline at end of file +} diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index a9b3401aa6f2d..db82fa14950a0 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -18,6 +18,7 @@ The iteration traits and common implementation #[forbid(deprecated_pattern)]; use cmp::{Eq, Ord}; +use vec; /// A function used to initialize the elements of a sequence pub type InitOp = &fn(uint) -> T; @@ -266,7 +267,7 @@ pub pure fn build_sized_opt>( size: Option, builder: fn(push: pure fn(A))) -> B { - Buildable::build_sized(size.get_default(4), builder) + Buildable::build_sized(size.get_or_default(4), builder) } // Functions that combine iteration and building diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 80e3a22dcba22..ae29bbe308512 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -1309,6 +1309,8 @@ pub mod funcs { overwrite: c_int) -> c_int; fn unsetenv(name: *c_char) -> c_int; fn putenv(string: *c_char) -> c_int; + + fn symlink(path1: *c_char, path2: *c_char) -> c_int; } #[nolink] @@ -1365,7 +1367,6 @@ pub mod funcs { pub mod bsd44 { } - #[cfg(target_os = "macos")] #[nolink] #[abi = "cdecl"] diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs index d8bcab62b8fa4..cb8f2b7088657 100644 --- a/src/libcore/logging.rs +++ b/src/libcore/logging.rs @@ -15,6 +15,10 @@ #[forbid(deprecated_pattern)]; use cast::transmute; +use io; +use libc; +use repr; +use vec; #[nolink] extern mod rustrt { diff --git a/src/libcore/managed.rs b/src/libcore/managed.rs index bc6a56868a5c4..5bbb5f6bec20d 100644 --- a/src/libcore/managed.rs +++ b/src/libcore/managed.rs @@ -16,6 +16,7 @@ use cmp::{Eq, Ord}; use intrinsic::TyDesc; +use ptr; pub mod raw { pub struct BoxHeaderRepr { diff --git a/src/libcore/oldcomm.rs b/src/libcore/oldcomm.rs index a5b0336ab60d9..2ce2c323cbffe 100644 --- a/src/libcore/oldcomm.rs +++ b/src/libcore/oldcomm.rs @@ -46,8 +46,17 @@ will once again be the preferred module for intertask communication. #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use cast; +use either; use either::Either; +use iter; +use libc; use libc::size_t; +use ptr; +use result; +use sys; +use task; +use vec; // After snapshot, change p2::addr_of => addr_of /** diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 3c6f5638d8d7c..22c363ba9c053 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -15,7 +15,7 @@ #[lang="drop"] pub trait Drop { - fn finalize(&self); // XXX: Rename to "drop"? --pcwalton + fn finalize(&self); // FIXME(#4332): Rename to "drop"? --pcwalton } #[lang="add"] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a4f385ea12cd8..a46736055a098 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -45,6 +45,11 @@ let unwrapped_msg = match move msg { #[forbid(deprecated_pattern)]; use cmp::Eq; +use option; +use ptr; +use str; +use util; +use num::Zero; /// The option type #[deriving_eq] @@ -166,7 +171,13 @@ 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_or_zero(opt: Option) -> T { + //! Returns the contained value or zero (for this type) + + match opt { Some(copy x) => x, None => Zero::zero() } +} + +pub pure fn get_or_default(opt: Option, def: T) -> T { //! Returns the contained value or a default match opt { Some(copy x) => x, None => def } @@ -320,7 +331,7 @@ impl Option { pure fn get(self) -> T { get(self) } #[inline(always)] - pure fn get_default(self, def: T) -> T { get_default(self, def) } + pure fn get_or_default(self, def: T) -> T { get_or_default(self, def) } /// Applies a function zero or more times until the result is none. #[inline(always)] @@ -329,6 +340,11 @@ impl Option { } } +impl Option { + #[inline(always)] + pure fn get_or_zero(self) -> T { get_or_zero(self) } +} + #[test] fn test_unwrap_ptr() { let x = ~0; @@ -403,6 +419,14 @@ fn test_option_while_some() { assert i == 11; } +#[test] +fn test_get_or_zero() { + let some_stuff = Some(42); + assert some_stuff.get_or_zero() == 42; + let no_stuff: Option = None; + assert no_stuff.get_or_zero() == 0; +} + // Local Variables: // mode: rust; // fill-column: 78; diff --git a/src/libcore/os.rs b/src/libcore/os.rs index b5e0983a420d1..b42d6d363e358 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -30,14 +30,24 @@ * to write OS-ignorant code by default. */ -use libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t, - mode_t, pid_t, FILE}; -pub use libc::{close, fclose}; - +use cast; +use either; +use io; +use libc; +use libc::{c_char, c_void, c_int, c_uint, size_t, ssize_t}; +use libc::{mode_t, pid_t, FILE}; +use option; use option::{Some, None}; +use private; +use ptr; +use str; +use task; +use task::TaskBuilder; +use uint; +use vec; +pub use libc::{close, fclose}; pub use os::consts::*; -use task::TaskBuilder; // FIXME: move these to str perhaps? #2620 @@ -78,6 +88,10 @@ pub fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool) #[cfg(windows)] pub mod win32 { + use libc; + use vec; + use str; + use option; use libc::types::os::arch::extra::DWORD; pub fn fill_utf16_buf_and_decode(f: fn(*mut u16, DWORD) -> DWORD) @@ -127,6 +141,12 @@ pub fn env() -> ~[(~str,~str)] { mod global_env { //! Internal module for serializing access to getenv/setenv + use either; + use libc; + use oldcomm; + use private; + use str; + use task; extern mod rustrt { fn rust_global_env_chan_ptr() -> *libc::uintptr_t; @@ -142,7 +162,7 @@ mod global_env { let env_ch = get_global_env_chan(); let po = oldcomm::Port(); oldcomm::send(env_ch, MsgGetEnv(str::from_slice(n), - oldcomm::Chan(&po))); + oldcomm::Chan(&po))); oldcomm::recv(po) } @@ -150,8 +170,8 @@ mod global_env { let env_ch = get_global_env_chan(); let po = oldcomm::Port(); oldcomm::send(env_ch, MsgSetEnv(str::from_slice(n), - str::from_slice(v), - oldcomm::Chan(&po))); + str::from_slice(v), + oldcomm::Chan(&po))); oldcomm::recv(po) } @@ -195,6 +215,13 @@ mod global_env { } mod impl_ { + use cast; + use libc; + use option; + use ptr; + use str; + use vec; + extern mod rustrt { fn rust_env_pairs() -> ~[~str]; } @@ -355,13 +382,8 @@ fn dup2(src: c_int, dst: c_int) -> c_int { pub fn dll_filename(base: &str) -> ~str { - return pre() + str::from_slice(base) + dll_suffix(); - - #[cfg(unix)] - fn pre() -> ~str { ~"lib" } - - #[cfg(windows)] - fn pre() -> ~str { ~"" } + return str::from_slice(DLL_PREFIX) + str::from_slice(base) + + str::from_slice(DLL_SUFFIX) } @@ -483,14 +505,14 @@ pub fn tmpdir() -> Path { #[cfg(unix)] #[allow(non_implicitly_copyable_typarams)] fn lookup() -> Path { - option::get_default(getenv_nonempty("TMPDIR"), + option::get_or_default(getenv_nonempty("TMPDIR"), Path("/tmp")) } #[cfg(windows)] #[allow(non_implicitly_copyable_typarams)] fn lookup() -> Path { - option::get_default( + option::get_or_default( option::or(getenv_nonempty("TMP"), option::or(getenv_nonempty("TEMP"), option::or(getenv_nonempty("USERPROFILE"), @@ -851,52 +873,94 @@ extern { pub fn _NSGetArgv() -> ***c_char; } -#[cfg(unix)] -pub fn family() -> ~str { ~"unix" } +mod consts { -#[cfg(windows)] -pub fn family() -> ~str { ~"windows" } + #[cfg(unix)] + use os::consts::unix::*; -#[cfg(target_os = "macos")] -mod consts { - pub fn sysname() -> ~str { ~"macos" } - pub fn exe_suffix() -> ~str { ~"" } - pub fn dll_suffix() -> ~str { ~".dylib" } -} + #[cfg(windows)] + use os::consts::windows::*; -#[cfg(target_os = "freebsd")] -mod consts { - pub fn sysname() -> ~str { ~"freebsd" } - pub fn exe_suffix() -> ~str { ~"" } - pub fn dll_suffix() -> ~str { ~".so" } -} + pub mod unix { + pub const FAMILY: &str = "unix"; + } -#[cfg(target_os = "linux")] -mod consts { - pub fn sysname() -> ~str { ~"linux" } - pub fn exe_suffix() -> ~str { ~"" } - pub fn dll_suffix() -> ~str { ~".so" } -} + pub mod windows { + pub const FAMILY: &str = "windows"; + } -#[cfg(target_os = "win32")] -mod consts { - pub fn sysname() -> ~str { ~"win32" } - pub fn exe_suffix() -> ~str { ~".exe" } - pub fn dll_suffix() -> ~str { ~".dll" } -} -#[cfg(target_arch = "x86")] -pub fn arch() -> ~str { ~"x86" } + #[cfg(target_os = "macos")] + use os::consts::macos::*; + + #[cfg(target_os = "freebsd")] + use os::consts::freebsd::*; + + #[cfg(target_os = "linux")] + use os::consts::linux::*; + + #[cfg(target_os = "win32")] + use os::consts::win32::*; + + pub mod macos { + pub const SYSNAME: &str = "macos"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".dylib"; + pub const EXE_SUFFIX: &str = ""; + } + + pub mod freebsd { + pub const SYSNAME: &str = "freebsd"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const EXE_SUFFIX: &str = ""; + } + + pub mod linux { + pub const SYSNAME: &str = "linux"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const EXE_SUFFIX: &str = ""; + } + + pub mod win32 { + pub const SYSNAME: &str = "win32"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".dll"; + pub const EXE_SUFFIX: &str = ".exe"; + } + -#[cfg(target_arch = "x86_64")] -pub fn arch() -> ~str { ~"x86_64" } + #[cfg(target_arch = "x86")] + use os::consts::x86::*; -#[cfg(target_arch = "arm")] -pub fn arch() -> str { ~"arm" } + #[cfg(target_arch = "x86_64")] + use os::consts::x86_64::*; + + #[cfg(target_arch = "arm")] + use os::consts::arm::*; + + pub mod x86 { + pub const ARCH: &str = "x86"; + } + pub mod x86_64 { + pub const ARCH: &str = "x86_64"; + } + pub mod arm { + pub const ARCH: &str = "arm"; + } +} #[cfg(test)] #[allow(non_implicitly_copyable_typarams)] mod tests { + use libc; + use option; + use os; + use rand; + use run; + use str; + use vec; #[test] pub fn last_os_error() { diff --git a/src/libcore/path.rs b/src/libcore/path.rs index 65ed35159314b..115983e5fdb49 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -19,6 +19,9 @@ Cross-platform file path handling #[forbid(deprecated_pattern)]; use cmp::Eq; +use libc; +use ptr; +use str; #[deriving_eq] pub struct WindowsPath { @@ -87,6 +90,8 @@ pub pure fn Path(s: &str) -> Path { mod stat { #[cfg(target_arch = "x86")] pub mod arch { + use libc; + pub fn default_stat() -> libc::stat { libc::stat { st_dev: 0, @@ -115,6 +120,8 @@ mod stat { #[cfg(target_arch = "x86_64")] pub mod arch { + use libc; + pub fn default_stat() -> libc::stat { libc::stat { st_dev: 0, @@ -144,6 +151,8 @@ mod stat { mod stat { #[cfg(target_arch = "x86_64")] pub mod arch { + use libc; + pub fn default_stat() -> libc::stat { libc::stat { st_dev: 0, @@ -176,6 +185,8 @@ mod stat { #[cfg(target_os = "macos")] mod stat { pub mod arch { + use libc; + pub fn default_stat() -> libc::stat { libc::stat { st_dev: 0, @@ -208,6 +219,7 @@ mod stat { #[cfg(target_os = "win32")] mod stat { pub mod arch { + use libc; pub fn default_stat() -> libc::stat { libc::stat { st_dev: 0, @@ -737,7 +749,9 @@ pub pure fn normalize(components: &[~str]) -> ~[~str] { } // Various windows helpers, and tests for the impl. -mod windows { +pub mod windows { + use libc; + #[inline(always)] pub pure fn is_sep(u: u8) -> bool { u == '/' as u8 || u == '\\' as u8 @@ -779,6 +793,9 @@ mod windows { #[cfg(test)] mod tests { + use path::windows; + use str; + #[test] fn test_double_slash_collapsing() { let path = PosixPath("tmp/"); diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 59d59d3351896..a129a9f4c5af8 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -90,7 +90,14 @@ bounded and unbounded protocols allows for less code duplication. use cmp::Eq; use cast::{forget, reinterpret_cast, transmute}; use either::{Either, Left, Right}; +use libc; +use option; use option::unwrap; +use pipes; +use ptr; +use private; +use task; +use vec; #[doc(hidden)] const SPIN_COUNT: uint = 0; @@ -1239,6 +1246,9 @@ pub mod rt { #[cfg(test)] pub mod test { + use pipes::oneshot; + use pipes; + #[test] pub fn test_select2() { let (p1, c1) = pipes::stream(); diff --git a/src/libcore/private.rs b/src/libcore/private.rs index 2d597bfb1b5f3..efa5062ad98eb 100644 --- a/src/libcore/private.rs +++ b/src/libcore/private.rs @@ -15,8 +15,17 @@ #[doc(hidden)]; -use task::TaskBuilder; -use task::atomically; +use cast; +use iter; +use libc; +use oldcomm; +use option; +use pipes; +use ptr; +use result; +use task; +use task::{TaskBuilder, atomically}; +use uint; extern mod rustrt { #[legacy_exports]; @@ -571,6 +580,12 @@ pub fn unwrap_exclusive(arc: Exclusive) -> T { #[cfg(test)] pub mod tests { + use option; + use pipes; + use result; + use task; + use uint; + #[test] pub fn exclusive_arc() { let mut futures = ~[]; diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index c838af700f65e..0bca8729d970d 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -13,8 +13,14 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use cast; use cmp::{Eq, Ord}; +use libc; use libc::{c_void, size_t}; +use ptr; +use str; +use sys; +use vec; #[nolink] #[abi = "cdecl"] diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs index 8ee857ef927d1..d816f23d4c0ad 100644 --- a/src/libcore/rand.rs +++ b/src/libcore/rand.rs @@ -14,6 +14,14 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use int; +use str; +use task; +use u32; +use uint; +use util; +use vec; + #[allow(non_camel_case_types)] // runtime type enum rctx {} @@ -354,6 +362,9 @@ pub fn random() -> uint { #[cfg(test)] pub mod tests { + use option::Option; + use rand; + #[test] pub fn rng_seeded() { let seed = rand::seed(); diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs index 268d5e1baa6e5..55eb53bc0266a 100644 --- a/src/libcore/reflect.rs +++ b/src/libcore/reflect.rs @@ -19,6 +19,8 @@ Runtime type reflection use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor}; use libc::c_void; +use sys; +use vec; /** * Trait for visitor that wishes to reflect on data. To use this, create a diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs index 111070e5b24c7..9a597bd814cdd 100644 --- a/src/libcore/repr.rs +++ b/src/libcore/repr.rs @@ -17,16 +17,31 @@ More runtime type reflection #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; -use io::{Writer, WriterUtil}; -use libc::c_void; -use to_str::ToStr; use cast::transmute; +use cast; +use char; +use dvec::DVec; +use intrinsic; use intrinsic::{TyDesc, TyVisitor, visit_tydesc}; +use io; +use io::{Writer, WriterUtil}; +use libc::c_void; +use managed; +use managed::raw::BoxHeaderRepr; +use ptr; +use reflect; use reflect::{MovePtr, MovePtrAdaptor, align}; +use repr; +use str; +use sys; +use sys::TypeDesc; +use to_str::ToStr; +use uint; use vec::UnboxedVecRepr; use vec::raw::{VecRepr, SliceRepr}; +use vec; + pub use managed::raw::BoxRepr; -use dvec::DVec; /// Helpers diff --git a/src/libcore/result.rs b/src/libcore/result.rs index e93d186049ecc..9e9886e66ab18 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -15,8 +15,11 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use cmp; use cmp::Eq; +use either; use either::Either; +use vec; /// The result type #[deriving_eq] @@ -378,6 +381,9 @@ pub pure fn unwrap_err(res: Result) -> U { #[allow(non_implicitly_copyable_typarams)] mod tests { #[legacy_exports]; + + use result; + fn op1() -> result::Result { result::Ok(666) } fn op2(i: int) -> result::Result { diff --git a/src/libcore/rt.rs b/src/libcore/rt.rs index 120103bd65683..ebe8746cfcad8 100644 --- a/src/libcore/rt.rs +++ b/src/libcore/rt.rs @@ -15,10 +15,9 @@ #[forbid(deprecated_pattern)]; //! Runtime calls emitted by the compiler. -use libc::c_char; -use libc::c_void; -use libc::size_t; -use libc::uintptr_t; +use libc::{c_char, c_void, size_t, uintptr_t}; +use str; +use sys; use gc::{cleanup_stack_for_failure, gc, Word}; @@ -39,15 +38,14 @@ extern mod rustrt { fn rust_upcall_free(ptr: *c_char); } -// FIXME (#2861): This needs both the attribute, and the name prefixed with -// 'rt_', otherwise the compiler won't find it. To fix this, see -// gather_rust_rtcalls. #[rt(fail_)] +#[lang="fail_"] pub fn rt_fail_(expr: *c_char, file: *c_char, line: size_t) -> ! { sys::begin_unwind_(expr, file, line); } #[rt(fail_bounds_check)] +#[lang="fail_bounds_check"] pub fn rt_fail_bounds_check(file: *c_char, line: size_t, index: size_t, len: size_t) { let msg = fmt!("index out of bounds: the len is %d but the index is %d", @@ -58,6 +56,7 @@ pub fn rt_fail_bounds_check(file: *c_char, line: size_t, } #[rt(exchange_malloc)] +#[lang="exchange_malloc"] pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { return rustrt::rust_upcall_exchange_malloc(td, size); } @@ -66,11 +65,13 @@ pub fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { // inside a landing pad may corrupt the state of the exception handler. If a // problem occurs, call exit instead. #[rt(exchange_free)] +#[lang="exchange_free"] pub fn rt_exchange_free(ptr: *c_char) { rustrt::rust_upcall_exchange_free(ptr); } #[rt(malloc)] +#[lang="malloc"] pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char { return rustrt::rust_upcall_malloc(td, size); } @@ -79,6 +80,7 @@ pub fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char { // inside a landing pad may corrupt the state of the exception handler. If a // problem occurs, call exit instead. #[rt(free)] +#[lang="free"] pub fn rt_free(ptr: *c_char) { rustrt::rust_upcall_free(ptr); } diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 3af854236e1fa..b753c647627ae 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -13,9 +13,18 @@ #[forbid(deprecated_pattern)]; //! Process spawning -use option::{Some, None}; -use libc::{pid_t, c_void, c_int}; +use io; use io::ReaderUtil; +use libc; +use libc::{pid_t, c_void, c_int}; +use oldcomm; +use option::{Some, None}; +use os; +use ptr; +use run; +use str; +use task; +use vec; #[abi = "cdecl"] extern mod rustrt { @@ -409,6 +418,8 @@ pub fn waitpid(pid: pid_t) -> int { #[cfg(test)] mod tests { use io::WriterUtil; + use os; + use run; // Regression test for memory leaks #[ignore(cfg(windows))] // FIXME (#2626) diff --git a/src/libcore/send_map.rs b/src/libcore/send_map.rs index af6b2c163779b..b6f237e14fb0e 100644 --- a/src/libcore/send_map.rs +++ b/src/libcore/send_map.rs @@ -45,6 +45,12 @@ pub trait SendMap { /// Open addressing with linear probing. pub mod linear { + use cmp; + use option; + use rand; + use uint; + use vec; + const INITIAL_CAPACITY: uint = 32u; // 2^5 struct Bucket { @@ -167,6 +173,7 @@ pub mod linear { let mut old_buckets = vec::from_fn(new_capacity, |_i| None); self.buckets <-> old_buckets; + self.size = 0; for uint::range(0, old_capacity) |i| { let mut bucket = None; bucket <-> old_buckets[i]; @@ -452,6 +459,8 @@ pub mod linear { #[test] pub mod test { use send_map::linear::LinearMap; + use send_map::linear; + use uint; #[test] pub fn inserts() { @@ -575,4 +584,22 @@ pub mod test { assert m1 == m2; } + + #[test] + pub fn test_expand() { + let mut m = ~LinearMap(); + + assert m.len() == 0; + assert m.is_empty(); + + let mut i = 0u; + let old_resize_at = m.resize_at; + while old_resize_at == m.resize_at { + m.insert(i, i); + i += 1; + } + + assert m.len() == i; + assert !m.is_empty(); + } } diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs index 1beb1a56efa1b..f45f71104f424 100644 --- a/src/libcore/stackwalk.rs +++ b/src/libcore/stackwalk.rs @@ -99,5 +99,5 @@ extern mod rustrt { #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; - fn frame_address(f: fn(++x: *u8)); + fn frame_address(f: &once fn(++x: *u8)); } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index e68966945caad..a1595e4135ed2 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -20,10 +20,19 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use at_vec; +use cast; +use char; use cmp::{Eq, Ord}; +use libc; use libc::size_t; use io::WriterUtil; +use ptr; +use str; use to_str::ToStr; +use u8; +use uint; +use vec; /* Section: Creating a string @@ -1936,6 +1945,11 @@ pub pure fn escape_unicode(s: &str) -> ~str { /// Unsafe operations pub mod raw { + use cast; + use libc; + use ptr; + use str::raw; + use vec; /// Create a Rust string from a null-terminated *u8 buffer pub unsafe fn from_buf(buf: *u8) -> ~str { @@ -2293,8 +2307,12 @@ impl &str: StrSlice { #[cfg(test)] mod tests { - + use char; use libc::c_char; + use libc; + use ptr; + use str::raw; + use vec; #[test] fn test_eq() { diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 62ced6019517f..d79fa3a86ff75 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -14,8 +14,16 @@ #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use cast; use cmp::{Eq, Ord}; +use gc; +use io; +use libc; use libc::{c_void, c_char, size_t}; +use ptr; +use repr; +use str; +use vec; pub type FreeGlue = fn(*TypeDesc, *c_void); @@ -137,6 +145,7 @@ pub pure fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { #[cfg(test)] pub mod tests { + use cast; #[test] pub fn size_of_basic() { diff --git a/src/libcore/task/local_data.rs b/src/libcore/task/local_data.rs index d321966ac5ea1..0cfceb6358a65 100644 --- a/src/libcore/task/local_data.rs +++ b/src/libcore/task/local_data.rs @@ -26,12 +26,9 @@ magic. */ -use task::local_data_priv::{ - local_pop, - local_get, - local_set, - local_modify -}; +use rt; +use task::local_data_priv::{local_get, local_pop, local_modify, local_set}; +use task; /** * Indexes a task-local data slot. The function's code pointer is used for diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index 634101ea717bf..c6b3cfa6626bb 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -10,6 +10,11 @@ #[doc(hidden)]; // FIXME #3538 +use cast; +use dvec; +use libc; +use option; +use task::rt; use task::local_data::LocalDataKey; #[cfg(notest)] diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 3cd12a5ba66ed..245b955c8711a 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -38,11 +38,22 @@ * ~~~ */ +use cast; +use cmp; use cmp::Eq; +use iter; +use libc; +use oldcomm; +use option; use result::Result; use pipes::{stream, Chan, Port}; +use pipes; +use ptr; +use result; use task::local_data_priv::{local_get, local_set}; use task::rt::{task_id, rust_task}; +use task; +use util; use util::replace; mod local_data_priv; diff --git a/src/libcore/task/rt.rs b/src/libcore/task/rt.rs index be66e9e26b835..e95c6d90eee1b 100644 --- a/src/libcore/task/rt.rs +++ b/src/libcore/task/rt.rs @@ -16,6 +16,8 @@ The task interface to the runtime #[doc(hidden)]; // FIXME #3538 +use libc; + #[allow(non_camel_case_types)] // runtime type pub type sched_id = int; #[allow(non_camel_case_types)] // runtime type diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 77acf3967e8e0..a904cbec3e592 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -73,8 +73,18 @@ #[doc(hidden)]; // FIXME #3538 #[warn(deprecated_mode)]; +use cast; +use oldcomm; +use option; +use pipes; +use private; +use ptr; +use send_map; +use task::rt; use task::rt::rust_task; use task::rt::rust_closure; +use uint; +use util; macro_rules! move_it ( { $x:expr } => ( unsafe { let y = move *ptr::addr_of(&($x)); move y } ) diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs index 900cc97066c5c..edd69219c3fcd 100644 --- a/src/libcore/to_bytes.rs +++ b/src/libcore/to_bytes.rs @@ -18,7 +18,9 @@ The `ToBytes` and `IterBytes` traits #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use io; use io::Writer; +use str; pub type Cb = fn(buf: &[const u8]) -> bool; diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index 55055470f10f1..963901c2c75d8 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -18,49 +18,52 @@ The `ToStr` trait for converting to strings #[forbid(deprecated_mode)]; #[forbid(deprecated_pattern)]; +use str; +use vec; + pub trait ToStr { pub pure fn to_str() -> ~str; } impl int: ToStr { - pure fn to_str() -> ~str { int::str(self) } + pure fn to_str() -> ~str { ::int::str(self) } } impl i8: ToStr { - pure fn to_str() -> ~str { i8::str(self) } + pure fn to_str() -> ~str { ::i8::str(self) } } impl i16: ToStr { - pure fn to_str() -> ~str { i16::str(self) } + pure fn to_str() -> ~str { ::i16::str(self) } } impl i32: ToStr { - pure fn to_str() -> ~str { i32::str(self) } + pure fn to_str() -> ~str { ::i32::str(self) } } impl i64: ToStr { - pure fn to_str() -> ~str { i64::str(self) } + pure fn to_str() -> ~str { ::i64::str(self) } } impl uint: ToStr { - pure fn to_str() -> ~str { uint::str(self) } + pure fn to_str() -> ~str { ::uint::str(self) } } impl u8: ToStr { - pure fn to_str() -> ~str { u8::str(self) } + pure fn to_str() -> ~str { ::u8::str(self) } } impl u16: ToStr { - pure fn to_str() -> ~str { u16::str(self) } + pure fn to_str() -> ~str { ::u16::str(self) } } impl u32: ToStr { - pure fn to_str() -> ~str { u32::str(self) } + pure fn to_str() -> ~str { ::u32::str(self) } } impl u64: ToStr { - pure fn to_str() -> ~str { u64::str(self) } + pure fn to_str() -> ~str { ::u64::str(self) } } impl float: ToStr { - pure fn to_str() -> ~str { float::to_str(self, 4u) } + pure fn to_str() -> ~str { ::float::to_str(self, 4u) } } impl f32: ToStr { - pure 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 { - pure 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 { - pure fn to_str() -> ~str { bool::to_str(self) } + pure fn to_str() -> ~str { ::bool::to_str(self) } } impl (): ToStr { pure fn to_str() -> ~str { ~"()" } @@ -69,10 +72,10 @@ impl ~str: ToStr { pure fn to_str() -> ~str { copy self } } impl &str: ToStr { - pure fn to_str() -> ~str { str::from_slice(self) } + pure fn to_str() -> ~str { ::str::from_slice(self) } } impl @str: ToStr { - pure fn to_str() -> ~str { str::from_slice(self) } + pure fn to_str() -> ~str { ::str::from_slice(self) } } impl (A, B): ToStr { diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 5ab013223c667..c602c19317021 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -15,6 +15,7 @@ //! Operations on tuples use cmp::{Eq, Ord}; +use vec; pub trait CopyableTuple { pure fn first() -> T; diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 80b393a813cf1..ec28056828228 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -14,8 +14,14 @@ use T = self::inst::T; +use char; use cmp::{Eq, Ord}; use from_str::FromStr; +use iter; +use num; +use str; +use uint; +use vec; pub const bits : uint = inst::bits; pub const bytes : uint = (inst::bits / 8); diff --git a/src/libcore/uint-template/uint.rs b/src/libcore/uint-template/uint.rs index b2ae1aa921b72..4d2da7180ef2e 100644 --- a/src/libcore/uint-template/uint.rs +++ b/src/libcore/uint-template/uint.rs @@ -16,6 +16,9 @@ pub use self::inst::{ }; mod inst { + use sys; + use uint; + pub type T = uint; #[cfg(target_arch = "x86")] diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 5071fb903d91d..a128b45c35026 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -14,20 +14,27 @@ #[forbid(deprecated_pattern)]; #[warn(non_camel_case_types)]; +use cast; use cmp::{Eq, Ord}; +use iter; +use libc; +use libc::size_t; use option::{Some, None}; +use ptr; use ptr::addr_of; -use libc::size_t; +use sys; +use uint; +use vec; #[abi = "cdecl"] -extern mod rustrt { +pub extern mod rustrt { fn vec_reserve_shared(++t: *sys::TypeDesc, ++v: **raw::VecRepr, ++n: libc::size_t); } #[abi = "rust-intrinsic"] -extern mod rusti { +pub extern mod rusti { fn move_val_init(dst: &mut T, -src: T); fn init() -> T; } @@ -196,7 +203,7 @@ pub pure fn build(builder: fn(push: pure fn(v: A))) -> ~[A] { #[inline(always)] pub pure fn build_sized_opt(size: Option, builder: fn(push: pure fn(v: A))) -> ~[A] { - build_sized(size.get_default(4), builder) + build_sized(size.get_or_default(4), builder) } /// Produces a mut vector from an immutable vector. @@ -1170,9 +1177,42 @@ pub pure fn reversed(v: &[const T]) -> ~[T] { } /** - * Iterates over a vector, with option to break + * Iterates over a vector, yielding each element to a closure. * - * Return true to continue, false to break. + * # Arguments + * + * * `v` - A vector, to be iterated over + * * `f` - A closure to do the iterating. Within this closure, return true to + * * continue iterating, false to break. + * + * # Examples + * ~~~ + * [1,2,3].each(|&i| { + * io::println(int::str(i)); + * true + * }); + * ~~~ + * + * ~~~ + * [1,2,3,4,5].each(|&i| { + * if i < 4 { + * io::println(int::str(i)); + * true + * } + * else { + * false + * } + * }); + * ~~~ + * + * You probably will want to use each with a `for`/`do` expression, depending + * on your iteration needs: + * + * ~~~ + * for [1,2,3].each |&i| { + * io::println(int::str(i)); + * } + * ~~~ */ #[inline(always)] pub pure fn each(v: &r/[T], f: fn(&r/T) -> bool) { @@ -1799,6 +1839,11 @@ pub struct UnboxedVecRepr { /// Unsafe operations pub mod raw { + use managed; + use option; + use ptr; + use sys; + use vec::rusti; /// The internal representation of a (boxed) vector pub struct VecRepr { @@ -1915,6 +1960,9 @@ pub mod raw { * may overlap. */ pub unsafe fn memcpy(dst: &[mut T], src: &[const T], count: uint) { + assert dst.len() >= count; + assert src.len() >= count; + do as_mut_buf(dst) |p_dst, _len_dst| { do as_const_buf(src) |p_src, _len_src| { ptr::memcpy(p_dst, p_src, count) @@ -1929,6 +1977,9 @@ pub mod raw { * may overlap. */ pub unsafe fn memmove(dst: &[mut T], src: &[const T], count: uint) { + assert dst.len() >= count; + assert src.len() >= count; + do as_mut_buf(dst) |p_dst, _len_dst| { do as_const_buf(src) |p_src, _len_src| { ptr::memmove(p_dst, p_src, count) @@ -1939,6 +1990,10 @@ pub mod raw { /// Operations on `[u8]` pub mod bytes { + use libc; + use uint; + use vec; + use vec::raw; /// Bytewise string comparison pub pure fn cmp(a: &~[u8], b: &~[u8]) -> int { @@ -1986,9 +2041,7 @@ pub mod bytes { * may not overlap. */ pub fn memcpy(dst: &[mut u8], src: &[const u8], count: uint) { - assert dst.len() >= count; - assert src.len() >= count; - + // Bound checks are done at vec::raw::memcpy. unsafe { vec::raw::memcpy(dst, src, count) } } @@ -1999,9 +2052,7 @@ pub mod bytes { * may overlap. */ pub fn memmove(dst: &[mut u8], src: &[const u8], count: uint) { - assert dst.len() >= count; - assert src.len() >= count; - + // Bound checks are done at vec::raw::memmove. unsafe { vec::raw::memmove(dst, src, count) } } } @@ -2229,6 +2280,8 @@ impl @[A] : iter::CopyableNonstrictIter { #[cfg(test)] mod tests { + use option; + use vec::raw; fn square(n: uint) -> uint { return n * n; } @@ -2581,7 +2634,9 @@ mod tests { fn halve(i: &int) -> Option { if *i % 2 == 0 { return option::Some::(*i / 2); - } else { return option::None::; } + } else { + return option::None::; + } } fn halve_for_sure(i: &int) -> int { return *i / 2; } let all_even: ~[int] = ~[0, 2, 8, 6]; @@ -3677,6 +3732,15 @@ mod tests { fail } } + + #[test] + #[should_fail] + fn test_memcpy_oob() unsafe { + let a = [mut 1, 2, 3, 4]; + let b = [1, 2, 3, 4, 5]; + raw::memcpy(a, b, 5); + } + } // Local Variables: diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc index cf242ddd8e219..7d1d112e76f10 100644 --- a/src/libfuzzer/fuzzer.rc +++ b/src/libfuzzer/fuzzer.rc @@ -167,7 +167,7 @@ type stolen_stuff = {exprs: ~[ast::expr], tys: ~[ast::Ty]}; fn steal(crate: ast::crate, tm: test_mode) -> stolen_stuff { let exprs = @mut ~[]; let tys = @mut ~[]; - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_expr: |a| stash_expr_if(safe_to_steal_expr, exprs, a, tm), visit_ty: |a| stash_ty_if(safe_to_steal_ty, tys, a, tm), .. *visit::default_simple_visitor() @@ -216,7 +216,7 @@ fn replace_expr_in_crate(crate: ast::crate, i: uint, fold::noop_fold_expr(original, fld) } } - let afp = @{ + let afp = @fold::AstFoldFns { fold_expr: fold::wrap(|a,b| { fold_expr_rep(j, i, newexpr.node, a, b, tm) }), @@ -241,7 +241,7 @@ fn replace_ty_in_crate(crate: ast::crate, i: uint, newty: ast::Ty, newty_ } else { fold::noop_fold_ty(original, fld) } } - let afp = @{ + let afp = @fold::AstFoldFns { fold_ty: fold::wrap(|a,b| fold_ty_rep(j, i, newty.node, a, b, tm) ), .. *fold::default_ast_fold() }; @@ -485,8 +485,9 @@ fn has_raw_pointers(c: ast::crate) -> bool { } } let v = - visit::mk_simple_visitor(@{visit_ty: |a| visit_ty(has_rp, a), - .. *visit::default_simple_visitor()}); + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_ty: |a| visit_ty(has_rp, a), + .. *visit::default_simple_visitor()}); visit::visit_crate(c, (), v); return *has_rp; } diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 52b94b76fe614..59d9886455aa8 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -8,24 +8,40 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc::{c_int, c_uint, c_char}; + +use back::rpath; use driver::session; -use session::Session; use lib::llvm::llvm; -use syntax::attr; -use middle::ty; +use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False}; +use lib::llvm::{PassManagerRef, FileType}; +use lib; +use metadata::common::link_meta; +use metadata::filesearch; use metadata::{encoder, cstore}; use middle::trans::common::crate_ctxt; -use metadata::common::link_meta; +use middle::ty; +use session::Session; +use session; +use util::ppaux; + +use core::char; +use core::cmp; +use core::hash; +use core::io::{Writer, WriterUtil}; +use core::libc::{c_int, c_uint, c_char}; +use core::os; +use core::ptr; +use core::run; +use core::str; +use core::vec; use std::map::HashMap; use std::sha1::sha1; use syntax::ast; -use syntax::print::pprust; -use lib::llvm::{ModuleRef, mk_pass_manager, mk_target_data, True, False, - PassManagerRef, FileType}; -use metadata::filesearch; use syntax::ast_map::{path, path_mod, path_name}; -use io::{Writer, WriterUtil}; +use syntax::attr; +use syntax::print::pprust; + +use core::os::consts::{macos, freebsd, linux, win32}; enum output_type { output_type_none, @@ -43,11 +59,13 @@ impl output_type : cmp::Eq { pure fn ne(&self, 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)); } + } else { + sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); + } } fn WriteOutputFile(sess: Session, @@ -65,8 +83,16 @@ fn WriteOutputFile(sess: Session, } } -mod jit { +pub mod jit { #[legacy_exports]; + + use lib::llvm::llvm; + use metadata::cstore; + + use core::cast; + use core::ptr; + use core::str; + #[nolink] #[abi = "rust-intrinsic"] extern mod rusti { @@ -126,13 +152,23 @@ mod jit { }; let func: fn(++argv: ~[~str]) = cast::transmute(move closure); - func(~[sess.opts.binary]); + func(~[/*bad*/copy sess.opts.binary]); } } } mod write { #[legacy_exports]; + + use back::link::jit; + use driver::session; + use lib::llvm::llvm; + use lib; + + use core::char; + use core::str; + use core::vec; + fn is_object_or_assembly_or_exe(ot: output_type) -> bool { if ot == output_type_assembly || ot == output_type_object || ot == output_type_exe { @@ -146,7 +182,7 @@ mod write { if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); } let mut pm = mk_pass_manager(); let td = mk_target_data( - sess.targ_cfg.target_strs.data_layout); + /*bad*/copy sess.targ_cfg.target_strs.data_layout); llvm::LLVMAddTargetData(td.lltd, pm.llpm); // FIXME (#2812): run the linter here also, once there are llvm-c // bindings for it. @@ -407,17 +443,19 @@ fn build_link_meta(sess: Session, c: ast::crate, output: &Path, let mut name: Option<~str> = None; let mut vers: Option<~str> = None; let mut cmh_items: ~[@ast::meta_item] = ~[]; - let linkage_metas = attr::find_linkage_metas(c.node.attrs); - attr::require_unique_names(sess.diagnostic(), linkage_metas); + let linkage_metas = + attr::find_linkage_metas(/*bad*/copy c.node.attrs); + // XXX: Bad copy. + attr::require_unique_names(sess.diagnostic(), copy linkage_metas); for linkage_metas.each |meta| { if attr::get_meta_item_name(*meta) == ~"name" { match attr::get_meta_item_value_str(*meta) { - Some(ref v) => { name = Some((*v)); } + Some(ref v) => { name = Some((/*bad*/copy *v)); } None => cmh_items.push(*meta) } } else if attr::get_meta_item_name(*meta) == ~"vers" { match attr::get_meta_item_value_str(*meta) { - Some(ref v) => { vers = Some((*v)); } + Some(ref v) => { vers = Some((/*bad*/copy *v)); } None => cmh_items.push(*meta) } } else { cmh_items.push(*meta); } @@ -438,7 +476,7 @@ fn build_link_meta(sess: Session, c: ast::crate, output: &Path, return len_and_str(pprust::lit_to_str(@l)); } - let cmh_items = attr::sort_meta_items(metas.cmh_items); + let cmh_items = attr::sort_meta_items(/*bad*/copy metas.cmh_items); symbol_hasher.reset(); for cmh_items.each |m| { @@ -473,15 +511,16 @@ fn build_link_meta(sess: Session, c: ast::crate, output: &Path, fn crate_meta_name(sess: Session, _crate: ast::crate, output: &Path, metas: provided_metas) -> ~str { return match metas.name { - Some(ref v) => (*v), + Some(ref v) => (/*bad*/copy *v), None => { let name = match output.filestem() { None => sess.fatal(fmt!("output file name `%s` doesn't\ appear to have a stem", output.to_str())), - Some(ref s) => (*s) + Some(ref s) => (/*bad*/copy *s) }; - warn_missing(sess, ~"name", name); + // XXX: Bad copy. + warn_missing(sess, ~"name", copy name); name } }; @@ -490,10 +529,11 @@ fn build_link_meta(sess: Session, c: ast::crate, output: &Path, fn crate_meta_vers(sess: Session, _crate: ast::crate, metas: provided_metas) -> ~str { return match metas.vers { - Some(ref v) => (*v), + Some(ref v) => (/*bad*/copy *v), None => { let vers = ~"0.0"; - warn_missing(sess, ~"vers", vers); + // Bad copy. + warn_missing(sess, ~"vers", copy vers); vers } }; @@ -534,10 +574,11 @@ fn symbol_hash(tcx: ty::ctxt, symbol_hasher: &hash::State, t: ty::t, fn get_symbol_hash(ccx: @crate_ctxt, t: ty::t) -> ~str { match ccx.type_hashcodes.find(t) { - Some(ref h) => return (*h), + Some(ref h) => return (/*bad*/copy *h), None => { let hash = symbol_hash(ccx.tcx, ccx.symbol_hasher, t, ccx.link_meta); - ccx.type_hashcodes.insert(t, hash); + // XXX: Bad copy. Prefer `@str`? + ccx.type_hashcodes.insert(t, copy hash); return hash; } } @@ -594,22 +635,27 @@ 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))), path_name(sess.ident_of(vers)))); } -fn mangle_exported_name(ccx: @crate_ctxt, path: path, t: ty::t) -> ~str { +fn mangle_exported_name(ccx: @crate_ctxt, +path: path, t: ty::t) -> ~str { let hash = get_symbol_hash(ccx, t); - return exported_name(ccx.sess, path, hash, ccx.link_meta.vers); + return exported_name(ccx.sess, path, + hash, + /*bad*/copy ccx.link_meta.vers); } fn mangle_internal_name_by_type_only(ccx: @crate_ctxt, - t: ty::t, name: ~str) -> - ~str { - let s = util::ppaux::ty_to_short_str(ccx.tcx, t); + t: ty::t, + +name: ~str) -> ~str { + let s = ppaux::ty_to_short_str(ccx.tcx, t); let hash = get_symbol_hash(ccx, t); return mangle(ccx.sess, ~[path_name(ccx.sess.ident_of(name)), @@ -617,20 +663,34 @@ fn mangle_internal_name_by_type_only(ccx: @crate_ctxt, path_name(ccx.sess.ident_of(hash))]); } -fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: path, - flav: ~str) -> ~str { +fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, + +path: path, + +flav: ~str) -> ~str { return mangle(ccx.sess, vec::append_one(path, path_name((ccx.names)(flav)))); } -fn mangle_internal_name_by_path(ccx: @crate_ctxt, path: path) -> ~str { +fn mangle_internal_name_by_path(ccx: @crate_ctxt, +path: path) -> ~str { return mangle(ccx.sess, path); } -fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: ~str) -> ~str { +fn mangle_internal_name_by_seq(ccx: @crate_ctxt, +flav: ~str) -> ~str { return fmt!("%s_%u", flav, (ccx.names)(flav).repr); } + +fn output_dll_filename(os: session::os, lm: &link_meta) -> ~str { + let libname = fmt!("%s-%s-%s", lm.name, lm.extras_hash, lm.vers); + let (dll_prefix, dll_suffix) = match os { + session::os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX), + session::os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX), + session::os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX), + session::os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX), + }; + return str::from_slice(dll_prefix) + libname + + str::from_slice(dll_suffix); +} + // 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, @@ -638,7 +698,7 @@ fn link_binary(sess: Session, out_filename: &Path, lm: link_meta) { // Converts a library file-stem into a cc -l argument - fn unlib(config: @session::config, stem: ~str) -> ~str { + fn unlib(config: @session::config, +stem: ~str) -> ~str { if stem.starts_with("lib") && config.os != session::os_win32 { stem.slice(3, stem.len()) @@ -648,9 +708,7 @@ fn link_binary(sess: Session, } let output = if sess.building_library { - let long_libname = - os::dll_filename(fmt!("%s-%s-%s", - lm.name, lm.extras_hash, lm.vers)); + let long_libname = output_dll_filename(sess.targ_cfg.os, &lm); debug!("link_meta.name: %s", lm.name); debug!("long_libname: %s", long_libname); debug!("out_filename: %s", out_filename.to_str()); @@ -658,7 +716,7 @@ fn link_binary(sess: Session, out_filename.dir_path().push(long_libname) } else { - *out_filename + /*bad*/copy *out_filename }; log(debug, ~"output: " + output.to_str()); @@ -705,7 +763,7 @@ fn link_binary(sess: Session, } let ula = cstore::get_used_link_args(cstore); - for ula.each |arg| { cc_args.push(*arg); } + for ula.each |arg| { cc_args.push(/*bad*/copy *arg); } // # Extern library linking @@ -715,7 +773,7 @@ fn link_binary(sess: Session, // to be found at compile time so it is still entirely up to outside // forces to make sure that library can be found at runtime. - let addl_paths = sess.opts.addl_lib_search_paths; + let addl_paths = /*bad*/copy sess.opts.addl_lib_search_paths; for addl_paths.each |path| { cc_args.push(~"-L" + path.to_str()); } // The names of the extern libraries diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index c12458c3f2805..c6b43ff6ad53a 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -8,12 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map; -use std::map::HashMap; -use metadata::cstore; + use driver::session; +use metadata::cstore; use metadata::filesearch; +use core::os; +use core::uint; +use core::util; +use core::vec; +use std::map::HashMap; +use std::map; + export get_rpath_flags; pure fn not_win32(os: session::os) -> bool { @@ -40,7 +46,7 @@ fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> ~[~str] { // where rustrt is and we know every rust program needs it let libs = vec::append_one(libs, get_sysroot_absolute_rt_lib(sess)); - let target_triple = sess.opts.target_triple; + let target_triple = /*bad*/copy sess.opts.target_triple; let rpaths = get_rpaths(os, &sysroot, output, libs, target_triple); rpaths_to_flags(rpaths) } @@ -109,14 +115,17 @@ fn get_rpaths_relative_to_output(os: session::os, fn get_rpath_relative_to_output(os: session::os, output: &Path, - lib: &Path) -> Path { + lib: &Path) + -> Path { + use core::os; + assert not_win32(os); // Mac doesn't appear to support $ORIGIN let prefix = match os { session::os_linux | session::os_freebsd => "$ORIGIN", session::os_macos => "@executable_path", - session::os_win32 => core::util::unreachable() + session::os_win32 => util::unreachable() }; Path(prefix).push_rel(&get_relative_to(&os::make_absolute(output), @@ -131,8 +140,8 @@ fn get_relative_to(abs1: &Path, abs2: &Path) -> Path { let abs2 = abs2.normalize(); debug!("finding relative path from %s to %s", abs1.to_str(), abs2.to_str()); - let split1 = abs1.components; - let split2 = abs2.components; + let split1 = /*bad*/copy abs1.components; + let split2 = /*bad*/copy abs2.components; let len1 = vec::len(split1); let len2 = vec::len(split2); assert len1 > 0; @@ -182,7 +191,7 @@ fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { for rpaths.each |rpath| { let s = rpath.to_str(); if !set.contains_key(s) { - minimized.push(*rpath); + minimized.push(/*bad*/copy *rpath); set.insert(s, ()); } } @@ -192,6 +201,12 @@ fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] { #[cfg(unix)] mod test { #[legacy_exports]; + + use driver::session; + + use core::os; + use core::str; + #[test] fn test_rpaths_to_flags() { let flags = rpaths_to_flags(~[Path("path1"), diff --git a/src/librustc/back/target_strs.rs b/src/librustc/back/target_strs.rs index 709375dc62f25..490ba574c5325 100644 --- a/src/librustc/back/target_strs.rs +++ b/src/librustc/back/target_strs.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + type t = { module_asm: ~str, meta_sect_name: ~str, diff --git a/src/librustc/back/upcall.rs b/src/librustc/back/upcall.rs index 1d992683faabe..5c9bdcf14eca8 100644 --- a/src/librustc/back/upcall.rs +++ b/src/librustc/back/upcall.rs @@ -36,8 +36,10 @@ fn declare_upcalls(targ_cfg: @session::config, fn nothrow(f: ValueRef) -> ValueRef { base::set_no_unwind(f); f } - let d = |a,b,c| decl(llmod, ~"upcall_", a, b, c); - let dv = |a,b| decl(llmod, ~"upcall_", a, b, T_void()); + let d: &fn(+a: ~str, +b: ~[TypeRef], +c: TypeRef) -> ValueRef = + |a,b,c| decl(llmod, ~"upcall_", a, b, c); + let dv: &fn(+a: ~str, +b: ~[TypeRef]) -> ValueRef = + |a,b| decl(llmod, ~"upcall_", a, b, T_void()); let int_t = T_int(targ_cfg); diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs index 5d8109b9c08db..205867feb3d4b 100644 --- a/src/librustc/back/x86.rs +++ b/src/librustc/back/x86.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use back::target_strs; use driver::session; -use session::sess_os_to_meta_os; use metadata::loader::meta_section_name; +use session::sess_os_to_meta_os; fn get_target_strs(target_os: session::os) -> target_strs::t { return { diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs index ffc598c3a0753..929634e5bd321 100644 --- a/src/librustc/back/x86_64.rs +++ b/src/librustc/back/x86_64.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use back::target_strs; use driver::session; -use session::sess_os_to_meta_os; use metadata::loader::meta_section_name; +use session::sess_os_to_meta_os; fn get_target_strs(target_os: session::os) -> target_strs::t { return { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 91c0d03657724..7eba77ad14327 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -9,27 +9,50 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use back::link; +use back::{x86, x86_64}; +use front; +use lib::llvm::llvm; use metadata::{creader, cstore, filesearch}; -use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive}; -use syntax::parse; -use syntax::{ast, codemap}; -use syntax::attr; +use metadata; use middle::{trans, freevars, kind, ty, typeck, lint}; -use syntax::print::{pp, pprust}; +use middle; +use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive}; +use session; use util::ppaux; -use back::link; -use result::{Ok, Err}; -use std::getopts; -use std::getopts::{opt_present}; -use std::getopts::groups; + +use core::cmp; +use core::int; +use core::io::WriterUtil; +use core::io; +use core::option; +use core::os; +use core::result::{Ok, Err}; +use core::str; +use core::vec; use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts}; -use io::WriterUtil; -use back::{x86, x86_64}; +use std::getopts::groups; +use std::getopts::{opt_present}; +use std::getopts; use std::map::HashMap; -use lib::llvm::llvm; - -enum pp_mode {ppm_normal, ppm_expanded, ppm_typed, ppm_identified, - ppm_expanded_identified } +use std; +use syntax::ast; +use syntax::ast_map; +use syntax::attr; +use syntax::codemap; +use syntax::diagnostic; +use syntax::parse; +use syntax::print::{pp, pprust}; +use syntax; + +enum pp_mode { + ppm_normal, + ppm_expanded, + ppm_typed, + ppm_identified, + ppm_expanded_identified +} /** * The name used for source code that doesn't originate in a file @@ -44,7 +67,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", @@ -63,9 +86,9 @@ fn default_configuration(sess: Session, argv0: ~str, input: input) -> }; return ~[ // Target bindings. - attr::mk_word_item(os::family()), - mk(~"target_os", os::sysname()), - mk(~"target_family", os::family()), + attr::mk_word_item(str::from_slice(os::FAMILY)), + mk(~"target_os", str::from_slice(os::SYSNAME)), + mk(~"target_family", str::from_slice(os::FAMILY)), mk(~"target_arch", arch), mk(~"target_word_size", wordsz), mk(~"target_libc", libc), @@ -74,20 +97,21 @@ fn default_configuration(sess: Session, argv0: ~str, input: input) -> mk(~"build_input", source_name(input))]; } -fn append_configuration(cfg: ast::crate_cfg, name: ~str) -> ast::crate_cfg { - if attr::contains_name(cfg, name) { +fn append_configuration(+cfg: ast::crate_cfg, +name: ~str) -> ast::crate_cfg { + // XXX: Bad copy. + if attr::contains_name(copy cfg, copy name) { return cfg; } else { return vec::append_one(cfg, attr::mk_word_item(name)); } } -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 let default_cfg = default_configuration(sess, argv0, input); - let user_cfg = sess.opts.cfg; + let user_cfg = /*bad*/copy sess.opts.cfg; // If the user wants a test runner, then add the test cfg let user_cfg = append_configuration( user_cfg, @@ -106,7 +130,7 @@ fn parse_cfgspecs(cfgspecs: ~[~str]) -> ast::crate_cfg { // meta_word variant. let mut words = ~[]; for cfgspecs.each |s| { - words.push(attr::mk_word_item(*s)); + words.push(attr::mk_word_item(/*bad*/copy *s)); } return words; } @@ -118,7 +142,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(ref file) => { @@ -127,7 +151,7 @@ fn parse_input(sess: Session, cfg: ast::crate_cfg, input: input) str_input(ref src) => { // FIXME (#2319): Don't really want to box the source string parse::parse_crate_from_source_str( - anon_src(), @(*src), cfg, sess.parse_sess) + anon_src(), @(/*bad*/copy *src), cfg, sess.parse_sess) } } } @@ -251,8 +275,8 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg, time(time_passes, ~"mode computation", || middle::mode::compute_modes(ty_cx, method_map, crate)); - time(time_passes, ~"alt checking", || - middle::check_alt::check_crate(ty_cx, method_map, crate)); + time(time_passes, ~"match checking", || + middle::check_match::check_crate(ty_cx, method_map, crate)); let last_use_map = time(time_passes, ~"liveness checking", || @@ -304,7 +328,7 @@ fn compile_upto(sess: Session, cfg: ast::crate_cfg, return {crate: crate, tcx: None}; } -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 } @@ -314,7 +338,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 { @@ -370,13 +394,16 @@ fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: input, let ann = match ppm { ppm_typed => { - {pre: ann_paren_for_expr, - post: |a| ann_typed_post(tcx.get(), a) } + pprust::pp_ann {pre: ann_paren_for_expr, + post: |a| ann_typed_post(tcx.get(), a) } } ppm_identified | ppm_expanded_identified => { - {pre: ann_paren_for_expr, post: ann_identified_post} + pprust::pp_ann {pre: ann_paren_for_expr, + post: ann_identified_post} + } + ppm_expanded | ppm_normal => { + pprust::no_ann() } - ppm_expanded | ppm_normal => pprust::no_ann() }; let is_expanded = upto != cu_parse; let src = sess.codemap.get_filemap(source_name(input)).src; @@ -460,7 +487,7 @@ fn host_triple() -> ~str { }; } -fn build_session_options(binary: ~str, +fn build_session_options(+binary: ~str, matches: &getopts::Matches, demitter: diagnostic::emitter) -> @session::options { let crate_type = if opt_present(matches, ~"lib") { @@ -505,7 +532,7 @@ fn build_session_options(binary: ~str, for debug_flags.each |debug_flag| { let mut this_bit = 0u; for debug_map.each |pair| { - let (name, _, bit) = *pair; + let (name, _, bit) = /*bad*/copy *pair; if name == *debug_flag { this_bit = bit; break; } } if this_bit == 0u { @@ -566,7 +593,7 @@ fn build_session_options(binary: ~str, let target = match target_opt { None => host_triple(), - Some(ref s) => (*s) + Some(ref s) => (/*bad*/copy *s) }; let addl_lib_search_paths = @@ -619,7 +646,7 @@ fn build_session_(sopts: @session::options, let filesearch = filesearch::mk_filesearch( sopts.maybe_sysroot, sopts.target_triple, - sopts.addl_lib_search_paths); + /*bad*/copy sopts.addl_lib_search_paths); let lint_settings = lint::mk_lint_settings(); Session_(@{targ_cfg: target_cfg, opts: sopts, @@ -746,7 +773,7 @@ fn build_output_filenames(input: input, // have to make up a name // We want to toss everything after the final '.' let dirpath = match *odir { - Some(ref d) => (*d), + Some(ref d) => (/*bad*/copy *d), None => match input { str_input(_) => os::getcwd(), file_input(ref ifile) => (*ifile).dir_path() @@ -768,9 +795,9 @@ fn build_output_filenames(input: input, } Some(ref out_file) => { - out_path = (*out_file); + out_path = (/*bad*/copy *out_file); obj_path = if stop_after_codegen { - (*out_file) + (/*bad*/copy *out_file) } else { (*out_file).with_filetype(obj_suffix) }; @@ -806,6 +833,11 @@ fn list_metadata(sess: Session, path: &Path, out: io::Writer) { mod test { #[legacy_exports]; + use core::vec; + use std::getopts; + use syntax::attr; + use syntax::diagnostic; + // When the user supplies --test we should implicitly supply --cfg test #[test] fn test_switch_implies_cfg_test() { diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index b2cb6da78ddc2..d60ad7606fdec 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -11,15 +11,22 @@ use back::link; use back::target_strs; +use back; +use driver; +use driver::session; use metadata::filesearch; +use metadata; use middle::lint; +use core::cmp; +use core::option; use syntax::ast::node_id; use syntax::ast::{int_ty, uint_ty, float_ty}; use syntax::codemap::span; +use syntax::diagnostic; use syntax::parse::parse_sess; use syntax::{ast, codemap}; - +use syntax; enum os { os_win32, os_macos, os_linux, os_freebsd, } @@ -201,8 +208,7 @@ impl Session { fn unimpl(msg: ~str) -> ! { self.span_diagnostic.handler().unimpl(msg) } - fn span_lint_level(level: lint::level, - sp: span, msg: ~str) { + fn span_lint_level(level: lint::level, sp: span, +msg: ~str) { match level { lint::allow => { }, lint::warn => self.span_warn(sp, msg), @@ -212,8 +218,10 @@ impl Session { } } fn span_lint(lint_mode: lint::lint, - expr_id: ast::node_id, item_id: ast::node_id, - span: span, msg: ~str) { + expr_id: ast::node_id, + item_id: ast::node_id, + span: span, + +msg: ~str) { let level = lint::get_lint_settings_level( self.lint_settings, lint_mode, expr_id, item_id); self.span_lint_level(level, span, msg); @@ -251,9 +259,9 @@ impl Session { } fn str_of(id: ast::ident) -> ~str { - *self.parse_sess.interner.get(id) + /*bad*/copy *self.parse_sess.interner.get(id) } - fn ident_of(st: ~str) -> ast::ident { + fn ident_of(+st: ~str) -> ast::ident { self.parse_sess.interner.intern(@st) } fn intr() -> @syntax::parse::token::ident_interner { @@ -325,9 +333,10 @@ fn sess_os_to_meta_os(os: os) -> metadata::loader::os { #[cfg(test)] mod test { #[legacy_exports]; + use syntax::ast; use syntax::ast_util; - fn make_crate_type_attr(t: ~str) -> ast::attribute { + fn make_crate_type_attr(+t: ~str) -> ast::attribute { ast_util::respan(ast_util::dummy_sp(), { style: ast::attr_outer, value: ast_util::respan(ast_util::dummy_sp(), diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index 22054b6a8d27d..c8b980218c1ed 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use syntax::{ast, fold, attr}; +use core::option; +use core::vec; + export strip_unconfigured_items; export metas_in_cfg; export strip_items; -type in_cfg_pred = fn@(~[ast::attribute]) -> bool; +type in_cfg_pred = fn@(+attrs: ~[ast::attribute]) -> bool; type ctxt = @{ in_cfg: in_cfg_pred @@ -24,7 +28,7 @@ type ctxt = @{ // any items that do not belong in the current configuration fn strip_unconfigured_items(crate: @ast::crate) -> @ast::crate { do strip_items(crate) |attrs| { - in_cfg(crate.node.config, attrs) + in_cfg(/*bad*/copy crate.node.config, attrs) } } @@ -33,11 +37,14 @@ fn strip_items(crate: @ast::crate, in_cfg: in_cfg_pred) let ctxt = @{in_cfg: in_cfg}; - let precursor = - @{fold_mod: |a,b| fold_mod(ctxt, a, b), + let precursor = @fold::AstFoldFns { + fold_mod: |a,b| fold_mod(ctxt, a, b), fold_block: fold::wrap(|a,b| fold_block(ctxt, a, b) ), fold_foreign_mod: |a,b| fold_foreign_mod(ctxt, a, b), - fold_item_underscore: |a,b| fold_item_underscore(ctxt, a, b), + fold_item_underscore: |a,b| { + // Bad copy. + fold_item_underscore(ctxt, copy a, b) + }, .. *fold::default_ast_fold()}; let fold = fold::make_fold(precursor); @@ -91,18 +98,18 @@ fn fold_foreign_mod(cx: ctxt, nm: ast::foreign_mod, }; } -fn fold_item_underscore(cx: ctxt, item: ast::item_, +fn fold_item_underscore(cx: ctxt, +item: ast::item_, fld: fold::ast_fold) -> ast::item_ { let item = match item { ast::item_impl(a, b, c, methods) => { let methods = methods.filter(|m| method_in_cfg(cx, *m) ); ast::item_impl(a, b, c, methods) } - ast::item_trait(a, b, ref methods) => { + ast::item_trait(ref a, ref b, ref methods) => { let methods = methods.filter(|m| trait_method_in_cfg(cx, m) ); - ast::item_trait(a, b, methods) + ast::item_trait(/*bad*/copy *a, /*bad*/copy *b, methods) } - _ => item + item => item }; fold::noop_fold_item_underscore(item, fld) @@ -128,7 +135,7 @@ fn filter_stmt(cx: ctxt, &&stmt: @ast::stmt) -> fn fold_block(cx: ctxt, b: ast::blk_, fld: fold::ast_fold) -> ast::blk_ { let filtered_stmts = vec::filter_map(b.stmts, |a| filter_stmt(cx, *a)); - return {view_items: b.view_items, + return {view_items: /*bad*/copy b.view_items, stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)), expr: option::map(&b.expr, |x| fld.fold_expr(*x)), id: b.id, @@ -136,36 +143,35 @@ fn fold_block(cx: ctxt, b: ast::blk_, fld: fold::ast_fold) -> } fn item_in_cfg(cx: ctxt, item: @ast::item) -> bool { - return (cx.in_cfg)(item.attrs); + return (cx.in_cfg)(/*bad*/copy item.attrs); } fn foreign_item_in_cfg(cx: ctxt, item: @ast::foreign_item) -> bool { - return (cx.in_cfg)(item.attrs); + return (cx.in_cfg)(/*bad*/copy item.attrs); } fn view_item_in_cfg(cx: ctxt, item: @ast::view_item) -> bool { - return (cx.in_cfg)(item.attrs); + return (cx.in_cfg)(/*bad*/copy item.attrs); } fn method_in_cfg(cx: ctxt, meth: @ast::method) -> bool { - return (cx.in_cfg)(meth.attrs); + return (cx.in_cfg)(/*bad*/copy meth.attrs); } fn trait_method_in_cfg(cx: ctxt, meth: &ast::trait_method) -> bool { match *meth { - ast::required(ref meth) => (cx.in_cfg)(meth.attrs), - ast::provided(@ref meth) => (cx.in_cfg)(meth.attrs) + ast::required(ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs), + ast::provided(@ref meth) => (cx.in_cfg)(/*bad*/copy meth.attrs) } } // Determine if an item should be translated in the current crate // configuration based on the item's attributes -fn in_cfg(cfg: ast::crate_cfg, attrs: ~[ast::attribute]) -> bool { +fn in_cfg(+cfg: ast::crate_cfg, +attrs: ~[ast::attribute]) -> bool { metas_in_cfg(cfg, attr::attr_metas(attrs)) } -fn metas_in_cfg(cfg: ast::crate_cfg, metas: ~[@ast::meta_item]) -> bool { - +fn metas_in_cfg(cfg: ast::crate_cfg, +metas: ~[@ast::meta_item]) -> bool { // The "cfg" attributes on the item let cfg_metas = attr::find_meta_items_by_name(metas, ~"cfg"); @@ -179,7 +185,7 @@ fn metas_in_cfg(cfg: ast::crate_cfg, metas: ~[@ast::meta_item]) -> bool { if !has_cfg_metas { return true; } for cfg_metas.each |cfg_mi| { - if attr::contains(cfg, *cfg_mi) { return true; } + if attr::contains(/*bad*/copy cfg, *cfg_mi) { return true; } } return false; diff --git a/src/librustc/front/core_inject.rs b/src/librustc/front/core_inject.rs index 0d01bdbd33654..e0b63314e3e22 100644 --- a/src/librustc/front/core_inject.rs +++ b/src/librustc/front/core_inject.rs @@ -8,14 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use driver::session::Session; -use syntax::codemap; + +use core::vec; use syntax::ast; use syntax::ast_util::*; use syntax::attr; +use syntax::codemap; +use syntax::fold; export maybe_inject_libcore_ref; +const CORE_VERSION: &static/str = "0.6"; + fn maybe_inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { if use_core(crate) { @@ -31,29 +37,62 @@ fn use_core(crate: @ast::crate) -> bool { fn inject_libcore_ref(sess: Session, crate: @ast::crate) -> @ast::crate { - - fn spanned(x: T) -> @ast::spanned { - return @{node: x, - span: dummy_sp()}; + fn spanned(x: T) -> ast::spanned { + return {node: x, span: dummy_sp()}; } - let n1 = sess.next_node_id(); - let n2 = sess.next_node_id(); - - let vi1 = @{node: ast::view_item_use(sess.ident_of(~"core"), ~[], n1), - attrs: ~[], - vis: ast::private, - span: dummy_sp()}; - let vp = spanned(ast::view_path_glob( - ident_to_path(dummy_sp(), sess.ident_of(~"core")), - n2)); - let vi2 = @{node: ast::view_item_import(~[vp]), - attrs: ~[], - vis: ast::private, - span: dummy_sp()}; - - let vis = vec::append(~[vi1, vi2], crate.node.module.view_items); - - return @{node: {module: { view_items: vis,.. crate.node.module }, - .. crate.node},.. *crate } + let precursor = @fold::AstFoldFns { + fold_crate: |crate, span, fld| { + let n1 = sess.next_node_id(); + let vi1 = @{node: ast::view_item_use(sess.ident_of(~"core"), + ~[], + n1), + attrs: ~[ + spanned({ + style: ast::attr_inner, + value: spanned(ast::meta_name_value( + ~"vers", + spanned(ast::lit_str( + @CORE_VERSION.to_str())) + )), + is_sugared_doc: false + }) + ], + vis: ast::private, + span: dummy_sp()}; + + let vis = vec::append(~[vi1], crate.module.view_items); + let mut new_module = { + view_items: vis, + ../*bad*/copy crate.module + }; + new_module = fld.fold_mod(new_module); + + // XXX: Bad copy. + let new_crate = { module: new_module, ..copy crate }; + (new_crate, span) + }, + fold_mod: |module, fld| { + let n2 = sess.next_node_id(); + + let vp = @spanned( + ast::view_path_glob(ident_to_path(dummy_sp(), + sess.ident_of(~"core")), + n2)); + let vi2 = @{node: ast::view_item_import(~[vp]), + attrs: ~[], + vis: ast::private, + span: dummy_sp()}; + + let vis = vec::append(~[vi2], module.view_items); + + // XXX: Bad copy. + let new_module = { view_items: vis, ..copy module }; + fold::noop_fold_mod(new_module, fld) + }, + ..*fold::default_ast_fold() + }; + + let fold = fold::make_fold(precursor); + @fold.fold_crate(*crate) } diff --git a/src/librustc/front/intrinsic_inject.rs b/src/librustc/front/intrinsic_inject.rs index f8a94fff67820..08b61557fdd74 100644 --- a/src/librustc/front/intrinsic_inject.rs +++ b/src/librustc/front/intrinsic_inject.rs @@ -8,20 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use driver::session::Session; use syntax::parse; use syntax::ast; -export inject_intrinsic; +use core::vec; -fn inject_intrinsic(sess: Session, - crate: @ast::crate) -> @ast::crate { +export inject_intrinsic; +fn inject_intrinsic(sess: Session, crate: @ast::crate) -> @ast::crate { let intrinsic_module = @(include_str!("intrinsic.rs").to_owned()); let item = parse::parse_item_from_source_str(~"", intrinsic_module, - sess.opts.cfg, + /*bad*/copy sess.opts.cfg, ~[], sess.parse_sess); let item = @@ -34,6 +35,6 @@ fn inject_intrinsic(sess: Session, let items = vec::append(~[item], crate.node.module.items); - return @{node: {module: { items: items ,.. crate.node.module } - ,.. crate.node} ,.. *crate } + return @{node: {module: { items: items ,.. /*bad*/copy crate.node.module } + ,.. /*bad*/copy crate.node} ,.. /*bad*/copy *crate } } diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 27e9e35b7ec47..d675c6f078a77 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -10,16 +10,20 @@ // Code that generates a test runner to run all the tests in a crate -use syntax::{ast, ast_util}; -use syntax::ast_util::*; -//import syntax::ast_util::dummy_sp; -use syntax::fold; -use syntax::print::pprust; -use syntax::codemap::span; + use driver::session; +use front::config; use session::Session; + +use core::dvec::DVec; +use core::option; +use core::vec; +use syntax::ast_util::*; use syntax::attr; -use dvec::DVec; +use syntax::codemap::span; +use syntax::fold; +use syntax::print::pprust; +use syntax::{ast, ast_util}; export modify_for_testing; @@ -42,7 +46,7 @@ fn modify_for_testing(sess: session::Session, // We generate the test harness when building in the 'test' // configuration, either with the '--test' or '--cfg test' // command line options. - let should_test = attr::contains(crate.node.config, + let should_test = attr::contains(/*bad*/copy crate.node.config, attr::mk_word_item(~"test")); if should_test { @@ -60,10 +64,10 @@ fn generate_test_harness(sess: session::Session, mut path: ~[], testfns: DVec()}; - let precursor = - @{fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ), - fold_item: |a,b| fold_item(cx, a, b), - fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()}; + let precursor = @fold::AstFoldFns { + fold_crate: fold::wrap(|a,b| fold_crate(cx, a, b) ), + fold_item: |a,b| fold_item(cx, a, b), + fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()}; let fold = fold::make_fold(precursor); let res = @fold.fold_crate(*crate); @@ -98,7 +102,7 @@ fn fold_mod(cx: test_ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod { } let mod_nomain = - {view_items: m.view_items, + {view_items: /*bad*/copy m.view_items, items: vec::filter_map(m.items, |i| nomain(cx, *i))}; return fold::noop_fold_mod(mod_nomain, fld); } @@ -109,7 +113,7 @@ fn fold_crate(cx: test_ctxt, c: ast::crate_, fld: fold::ast_fold) -> // Add a special __test module to the crate that will contain code // generated for the test harness - return {module: add_test_module(cx, folded.module),.. folded}; + return {module: add_test_module(cx, /*bad*/copy folded.module),.. folded}; } @@ -130,7 +134,7 @@ fn fold_item(cx: test_ctxt, &&i: @ast::item, fld: fold::ast_fold) -> _ => { debug!("this is a test function"); let test = {span: i.span, - path: cx.path, ignore: is_ignored(cx, i), + path: /*bad*/copy cx.path, ignore: is_ignored(cx, i), should_fail: should_fail(i)}; cx.testfns.push(test); debug!("have %u test functions", cx.testfns.len()); @@ -148,7 +152,7 @@ fn is_test_fn(i: @ast::item) -> bool { vec::len(attr::find_attrs_by_name(i.attrs, ~"test")) > 0u; fn has_test_signature(i: @ast::item) -> bool { - match i.node { + match /*bad*/copy i.node { ast::item_fn(decl, _, tps, _) => { let input_cnt = vec::len(decl.inputs); let no_output = match decl.output.node { @@ -166,12 +170,13 @@ fn is_test_fn(i: @ast::item) -> bool { } fn is_ignored(cx: test_ctxt, i: @ast::item) -> bool { - let ignoreattrs = attr::find_attrs_by_name(i.attrs, ~"ignore"); + let ignoreattrs = attr::find_attrs_by_name(/*bad*/copy i.attrs, + ~"ignore"); let ignoreitems = attr::attr_metas(ignoreattrs); let cfg_metas = vec::concat(vec::filter_map(ignoreitems, |i| attr::get_meta_item_list(*i))); return if vec::is_not_empty(ignoreitems) { - config::metas_in_cfg(cx.crate.node.config, cfg_metas) + config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas) } else { false } @@ -181,9 +186,9 @@ fn should_fail(i: @ast::item) -> bool { vec::len(attr::find_attrs_by_name(i.attrs, ~"should_fail")) > 0u } -fn add_test_module(cx: test_ctxt, m: ast::_mod) -> ast::_mod { +fn add_test_module(cx: test_ctxt, +m: ast::_mod) -> ast::_mod { let testmod = mk_test_module(cx); - return {items: vec::append_one(m.items, testmod),.. m}; + return {items: vec::append_one(/*bad*/copy m.items, testmod),.. m}; } /* @@ -205,13 +210,18 @@ mod __test { */ fn mk_test_module(cx: test_ctxt) -> @ast::item { + // Link to std + let std = mk_std(cx); + let view_items = if is_std(cx) { ~[] } else { ~[std] }; // A function that generates a vector of test descriptors to feed to the // test runner let testsfn = mk_tests(cx); // The synthesized main function which will call the console test runner // with our list of tests let mainfn = mk_main(cx); - let testmod: ast::_mod = {view_items: ~[], items: ~[mainfn, testsfn]}; + let testmod: ast::_mod = { + view_items: view_items, items: ~[mainfn, testsfn] + }; let item_ = ast::item_mod(testmod); // This attribute tells resolve to let us call unexported functions let resolve_unexported_attr = @@ -225,7 +235,7 @@ fn mk_test_module(cx: test_ctxt) -> @ast::item { span: dummy_sp()}; debug!("Synthetic test module:\n%s\n", - pprust::item_to_str(@item, cx.sess.intr())); + pprust::item_to_str(@copy item, cx.sess.intr())); return @item; } @@ -234,10 +244,32 @@ fn nospan(t: T) -> ast::spanned { return {node: t, span: dummy_sp()}; } -fn path_node(ids: ~[ast::ident]) -> @ast::path { +fn path_node(+ids: ~[ast::ident]) -> @ast::path { @{span: dummy_sp(), global: false, idents: ids, rp: None, types: ~[]} } +fn path_node_global(+ids: ~[ast::ident]) -> @ast::path { + @{span: dummy_sp(), global: true, idents: ids, rp: None, types: ~[]} +} + +fn mk_std(cx: test_ctxt) -> @ast::view_item { + let vers = ast::lit_str(@~"0.6"); + let vers = nospan(vers); + let mi = ast::meta_name_value(~"vers", vers); + let mi = nospan(mi); + let vi = ast::view_item_use(cx.sess.ident_of(~"std"), + ~[@mi], + cx.sess.next_node_id()); + let vi = { + node: vi, + attrs: ~[], + vis: ast::private, + span: dummy_sp() + }; + + return @vi; +} + fn mk_tests(cx: test_ctxt) -> @ast::item { let ret_ty = mk_test_desc_vec_ty(cx); @@ -264,25 +296,34 @@ fn mk_tests(cx: test_ctxt) -> @ast::item { return @item; } -fn mk_path(cx: test_ctxt, path: ~[ast::ident]) -> ~[ast::ident] { - // For tests that are inside of std we don't want to prefix - // the paths with std:: +fn is_std(cx: test_ctxt) -> bool { let is_std = { - let items = attr::find_linkage_metas(cx.crate.node.attrs); + let items = attr::find_linkage_metas(/*bad*/copy cx.crate.node.attrs); match attr::last_meta_item_value_str_by_name(items, ~"name") { Some(~"std") => true, _ => false } }; - if is_std { path } - else { vec::append(~[cx.sess.ident_of(~"std")], path) } + return is_std; +} + +fn mk_path(cx: test_ctxt, +path: ~[ast::ident]) -> @ast::path { + // For tests that are inside of std we don't want to prefix + // the paths with std:: + if is_std(cx) { path_node_global(path) } + else { + path_node( + ~[cx.sess.ident_of(~"self"), + 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 { let test_desc_ty_path = - path_node(mk_path(cx, ~[cx.sess.ident_of(~"test"), - cx.sess.ident_of(~"TestDesc")])); + mk_path(cx, ~[cx.sess.ident_of(~"test"), + cx.sess.ident_of(~"TestDesc")]); let test_desc_ty: ast::Ty = {id: cx.sess.next_node_id(), @@ -318,14 +359,15 @@ fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr { fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { let span = test.span; - let path = test.path; + let path = /*bad*/copy test.path; debug!("encoding %s", ast_util::path_name_i(path, cx.sess.parse_sess.interner)); + // XXX: Bad copy of `path`. let name_lit: ast::lit = - nospan(ast::lit_str(@ast_util::path_name_i(path, cx.sess.parse_sess - .interner))); + nospan(ast::lit_str(@ast_util::path_name_i( + copy path, cx.sess.parse_sess.interner))); let name_expr_inner: @ast::expr = @{id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), @@ -342,7 +384,7 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { nospan({mutbl: ast::m_imm, ident: cx.sess.ident_of(~"name"), expr: @name_expr}); - let fn_path = path_node(path); + let fn_path = path_node_global(path); let fn_expr: ast::expr = {id: cx.sess.next_node_id(), @@ -381,8 +423,14 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { ident: cx.sess.ident_of(~"should_fail"), expr: @fail_expr}); + let test_desc_path = + mk_path(cx, ~[cx.sess.ident_of(~"test"), + cx.sess.ident_of(~"TestDesc")]); + let desc_rec_: ast::expr_ = - ast::expr_rec(~[name_field, fn_field, ignore_field, fail_field], + ast::expr_struct( + test_desc_path, + ~[name_field, fn_field, ignore_field, fail_field], option::None); let desc_rec: ast::expr = {id: cx.sess.next_node_id(), callee_id: cx.sess.next_node_id(), @@ -394,7 +442,7 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr { // FIXME (#1281): This can go away once fn is the type of bare function. fn mk_test_wrapper(cx: test_ctxt, - fn_path_expr: ast::expr, + +fn_path_expr: ast::expr, span: span) -> @ast::expr { let call_expr: ast::expr = { id: cx.sess.next_node_id(), @@ -461,7 +509,7 @@ fn mk_main(cx: test_ctxt) -> @ast::item { fn mk_test_main_call(cx: test_ctxt) -> @ast::expr { // Call os::args to generate the vector of test_descs - let args_path = path_node(~[ + let args_path = path_node_global(~[ cx.sess.ident_of(~"os"), cx.sess.ident_of(~"args") ]); @@ -494,9 +542,9 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr { node: test_call_expr_, span: dummy_sp()}; // Call std::test::test_main - let test_main_path = path_node( + let test_main_path = mk_path(cx, ~[cx.sess.ident_of(~"test"), - cx.sess.ident_of(~"test_main")])); + cx.sess.ident_of(~"test_main")]); let test_main_path_expr_: ast::expr_ = ast::expr_path(test_main_path); diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 3f24d28043799..629563411895f 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -8,12 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map::HashMap; -use libc::{c_char, c_int, c_uint, c_longlong, c_ulonglong}; +use core::cast; +use core::cmp; +use core::int; +use core::io; +use core::libc::{c_char, c_int, c_uint, c_longlong, c_ulonglong}; +use core::option; +use core::ptr; +use core::str; +use core::uint; +use core::vec; +use std::map::HashMap; type Opcode = u32; type Bool = c_uint; + const True: Bool = 1 as Bool; const False: Bool = 0 as Bool; @@ -1058,11 +1068,12 @@ fn SetLinkage(Global: ValueRef, Link: Linkage) { /* Memory-managed object interface to type handles. */ -type type_names = @{type_names: std::map::HashMap, - named_types: std::map::HashMap<~str, TypeRef>}; +type type_names = @{type_names: HashMap, + named_types: HashMap<~str, TypeRef>}; -fn associate_type(tn: type_names, s: ~str, t: TypeRef) { - assert tn.type_names.insert(t, s); +fn associate_type(tn: type_names, +s: ~str, t: TypeRef) { + // XXX: Bad copy, use @str instead? + assert tn.type_names.insert(t, copy s); assert tn.named_types.insert(s, t); } @@ -1070,27 +1081,28 @@ fn type_has_name(tn: type_names, t: TypeRef) -> Option<~str> { return tn.type_names.find(t); } -fn name_has_type(tn: type_names, s: ~str) -> Option { +fn name_has_type(tn: type_names, +s: ~str) -> Option { return tn.named_types.find(s); } fn mk_type_names() -> type_names { - @{type_names: std::map::HashMap(), - named_types: std::map::HashMap()} + @{type_names: HashMap(), + named_types: HashMap()} } fn type_to_str(names: type_names, ty: TypeRef) -> ~str { return type_to_str_inner(names, ~[], ty); } -fn type_to_str_inner(names: type_names, outer0: ~[TypeRef], ty: TypeRef) -> +fn type_to_str_inner(names: type_names, +outer0: ~[TypeRef], ty: TypeRef) -> ~str { match type_has_name(names, ty) { - option::Some(ref n) => return (*n), + option::Some(ref n) => return (/*bad*/copy *n), _ => {} } - let outer = vec::append_one(outer0, ty); + // XXX: Bad copy. + let outer = vec::append_one(copy outer0, ty); let kind = llvm::LLVMGetTypeKind(ty); diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 69dcdc389d62a..e6a367ac1a863 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // EBML enum definitions and utils shared by the encoder and decoder const tag_items: uint = 0x02u; @@ -139,5 +140,17 @@ const tag_item_trait_method_sort: uint = 0x70; const tag_item_impl_type_basename: uint = 0x71; +// Language items are a top-level directory (for speed). Hierarchy: +// +// tag_lang_items +// - tag_lang_items_item +// - tag_lang_items_item_id: u32 +// - tag_lang_items_item_node_id: u32 + +const tag_lang_items: uint = 0x72; +const tag_lang_items_item: uint = 0x73; +const tag_lang_items_item_id: uint = 0x74; +const tag_lang_items_item_node_id: uint = 0x75; + type link_meta = {name: ~str, vers: ~str, extras_hash: ~str}; diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index e9b820d30db08..5ba1f4e86b7c9 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -8,27 +8,39 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + //! Validates all used crates and extern libraries and loads their metadata -use syntax::diagnostic::span_handler; -use syntax::{ast, ast_util}; +use metadata::cstore; +use metadata::common::*; +use metadata::decoder; +use metadata::filesearch::FileSearch; +use metadata::loader; + +use core::dvec::DVec; +use core::either; +use core::option; +use core::vec; use syntax::attr; -use syntax::visit; use syntax::codemap::span; -use std::map::HashMap; -use syntax::print::pprust; -use metadata::filesearch::FileSearch; -use metadata::common::*; -use dvec::DVec; +use syntax::diagnostic::span_handler; use syntax::parse::token::ident_interner; +use syntax::print::pprust; +use syntax::visit; +use syntax::{ast, ast_util}; +use std::map::HashMap; 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, - os: loader::os, static: bool, intr: @ident_interner) { +fn read_crates(diag: span_handler, + crate: ast::crate, + cstore: cstore::CStore, + filesearch: FileSearch, + os: loader::os, + static: bool, + intr: @ident_interner) { let e = @{diag: diag, filesearch: filesearch, cstore: cstore, @@ -38,10 +50,10 @@ fn read_crates(diag: span_handler, crate: ast::crate, mut next_crate_num: 1, intr: intr}; let v = - visit::mk_simple_visitor(@{visit_view_item: - |a| visit_view_item(e, a), - visit_item: |a| visit_item(e, a) - ,.. *visit::default_simple_visitor()}); + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_view_item: |a| visit_view_item(e, a), + visit_item: |a| visit_item(e, a), + .. *visit::default_simple_visitor()}); visit::visit_crate(crate, (), v); dump_crates(e.crate_cache); warn_if_multiple_versions(e, diag, e.crate_cache.get()); @@ -68,7 +80,8 @@ fn warn_if_multiple_versions(e: env, diag: span_handler, use either::*; if crate_cache.len() != 0u { - let name = loader::crate_name_from_metas(*crate_cache.last().metas); + let name = loader::crate_name_from_metas( + /*bad*/copy *crate_cache.last().metas); let (matches, non_matches) = partition(crate_cache.map_to_vec(|&entry| { let othername = loader::crate_name_from_metas(*entry.metas); @@ -87,7 +100,8 @@ fn warn_if_multiple_versions(e: env, diag: span_handler, for matches.each |match_| { diag.span_note(match_.span, ~"used here"); let attrs = ~[ - attr::mk_attr(attr::mk_list_item(~"link", *match_.metas)) + attr::mk_attr(attr::mk_list_item( + ~"link", /*bad*/copy *match_.metas)) ]; loader::note_linkage_attrs(e.intr, diag, attrs); } @@ -107,7 +121,7 @@ type env = @{diag: span_handler, intr: @ident_interner}; fn visit_view_item(e: env, i: @ast::view_item) { - match i.node { + match /*bad*/copy i.node { ast::view_item_use(ident, meta_items, id) => { debug!("resolving use stmt. ident: %?, meta: %?", ident, meta_items); let cnum = resolve_crate(e, ident, meta_items, ~"", i.span); @@ -118,7 +132,7 @@ fn visit_view_item(e: env, i: @ast::view_item) { } fn visit_item(e: env, i: @ast::item) { - match i.node { + match /*bad*/copy i.node { ast::item_foreign_mod(fm) => { match attr::foreign_abi(i.attrs) { either::Right(abi) => { @@ -130,7 +144,8 @@ fn visit_item(e: env, i: @ast::item) { let cstore = e.cstore; let mut already_added = false; - let link_args = attr::find_attrs_by_name(i.attrs, ~"link_args"); + let link_args = attr::find_attrs_by_name(/*bad*/copy i.attrs, + ~"link_args"); match fm.sort { ast::named => { @@ -143,9 +158,9 @@ fn visit_item(e: env, i: @ast::item) { i.span, ~"empty #[link_name] not allowed; use #[nolink]."); } - (*nn) + (/*bad*/copy *nn) } - None => *e.intr.get(i.ident) + None => /*bad*/copy *e.intr.get(i.ident) }; if attr::find_attrs_by_name(i.attrs, ~"nolink").is_empty() { already_added = !cstore::add_used_library(cstore, @@ -162,7 +177,7 @@ fn visit_item(e: env, i: @ast::item) { for link_args.each |a| { match attr::get_meta_item_value_str(attr::attr_meta(*a)) { Some(ref linkarg) => { - cstore::add_used_link_args(cstore, (*linkarg)); + cstore::add_used_link_args(cstore, (/*bad*/copy *linkarg)); } None => {/* fallthrough */ } } @@ -172,9 +187,10 @@ fn visit_item(e: env, i: @ast::item) { } } -fn metas_with(ident: ~str, key: ~str, metas: ~[@ast::meta_item]) +fn metas_with(+ident: ~str, +key: ~str, +metas: ~[@ast::meta_item]) -> ~[@ast::meta_item] { - let name_items = attr::find_meta_items_by_name(metas, key); + // XXX: Bad copies. + let name_items = attr::find_meta_items_by_name(copy metas, copy key); if name_items.is_empty() { vec::append_one(metas, attr::mk_name_value_item_str(key, ident)) } else { @@ -182,7 +198,7 @@ fn metas_with(ident: ~str, key: ~str, metas: ~[@ast::meta_item]) } } -fn metas_with_ident(ident: ~str, metas: ~[@ast::meta_item]) +fn metas_with_ident(+ident: ~str, +metas: ~[@ast::meta_item]) -> ~[@ast::meta_item] { metas_with(ident, ~"name", metas) } @@ -199,9 +215,9 @@ fn existing_match(e: env, metas: ~[@ast::meta_item], hash: ~str) -> return None; } -fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item], - hash: ~str, span: span) -> ast::crate_num { - let metas = metas_with_ident(*e.intr.get(ident), metas); +fn resolve_crate(e: env, ident: ast::ident, +metas: ~[@ast::meta_item], + +hash: ~str, span: span) -> ast::crate_num { + let metas = metas_with_ident(/*bad*/copy *e.intr.get(ident), metas); match existing_match(e, metas, hash) { None => { @@ -210,7 +226,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item], filesearch: e.filesearch, span: span, ident: ident, - metas: metas, + metas: copy metas, // XXX: Bad copy. hash: hash, os: e.os, static: e.static, @@ -236,8 +252,8 @@ fn resolve_crate(e: env, ident: ast::ident, metas: ~[@ast::meta_item], let cname = match attr::last_meta_item_value_str_by_name(metas, ~"name") { - option::Some(ref v) => (*v), - option::None => *e.intr.get(ident) + option::Some(ref v) => (/*bad*/copy *v), + option::None => /*bad*/copy *e.intr.get(ident) }; let cmeta = @{name: cname, data: cdata, cnum_map: cnum_map, cnum: cnum}; @@ -262,7 +278,7 @@ fn resolve_crate_deps(e: env, cdata: @~[u8]) -> cstore::cnum_map { for decoder::get_crate_deps(e.intr, cdata).each |dep| { let extrn_cnum = dep.cnum; let cname = dep.name; - let cmetas = metas_with(dep.vers, ~"vers", ~[]); + let cmetas = metas_with(/*bad*/copy dep.vers, ~"vers", ~[]); debug!("resolving dep crate %s ver: %s hash: %s", *e.intr.get(dep.name), dep.vers, dep.hash); match existing_match(e, metas_with_ident(*e.intr.get(cname), cmetas), @@ -278,8 +294,8 @@ fn resolve_crate_deps(e: env, cdata: @~[u8]) -> cstore::cnum_map { // FIXME (#2404): Need better error reporting than just a bogus // span. let fake_span = ast_util::dummy_sp(); - let local_cnum = resolve_crate(e, cname, cmetas, dep.hash, - fake_span); + let local_cnum = resolve_crate(e, cname, cmetas, + /*bad*/copy dep.hash, fake_span); cnum_map.insert(extrn_cnum, local_cnum); } } diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index ae56cf45dbcf2..2dfe5bad27a22 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -8,13 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // Searching for information from the cstore use metadata::common::*; +use metadata::cstore; +use metadata::decoder; +use metadata; use middle::ty; use core::dvec::DVec; -use core::option::{Some, None}; +use core::vec; use reader = std::ebml::reader; use std::ebml; use std::map::HashMap; @@ -40,11 +44,13 @@ export get_method_names_if_trait; export get_type_name_if_impl; export get_static_methods_if_impl; export get_item_attrs; +export each_lang_item; export each_path; export get_type; export get_impl_traits; export get_impl_method; export get_item_path; +export get_lang_items; export maybe_get_item_ast, found_ast, found, found_parent, not_found; export ProvidedTraitMethodInfo; export StaticMethodInfo; @@ -70,6 +76,14 @@ fn get_type_param_count(cstore: cstore::CStore, def: ast::def_id) -> uint { return decoder::get_type_param_count(cdata, def.node); } +/// Iterates over all the language items in the given crate. +fn each_lang_item(cstore: cstore::CStore, + cnum: ast::crate_num, + f: &fn(ast::node_id, uint) -> bool) { + let crate_data = cstore::get_crate_data(cstore, cnum); + decoder::each_lang_item(crate_data, f) +} + /// Iterates over all the paths in the given crate. fn each_path(cstore: cstore::CStore, cnum: ast::crate_num, f: fn(decoder::path_entry) -> bool) { @@ -87,7 +101,8 @@ fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path { // FIXME #1920: This path is not always correct if the crate is not linked // into the root namespace. - vec::append(~[ast_map::path_mod(tcx.sess.ident_of(cdata.name))], path) + vec::append(~[ast_map::path_mod(tcx.sess.ident_of( + /*bad*/copy cdata.name))], path) } enum found_ast { diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 4f5046e40083c..b09f2d87b6c6b 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -8,11 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // The crate store - a central repo for information collected about external // crates and libraries -use std::map; +use metadata::creader; +use metadata::cstore; +use metadata::decoder; + +use core::option; +use core::str; +use core::vec; use std::map::HashMap; +use std::map; +use std; use syntax::{ast, attr}; use syntax::parse::token::ident_interner; @@ -35,7 +44,6 @@ export get_used_link_args; export add_use_stmt_cnum; export find_use_stmt_cnum; export get_dep_hashes; -export get_path; // A map from external crate numbers (as decoded from some crate file) to @@ -44,11 +52,6 @@ export get_path; // own crate numbers. type cnum_map = map::HashMap; -// Multiple items may have the same def_id in crate metadata. They may be -// renamed imports or reexports. This map keeps the "real" module path -// and def_id. -type mod_path_map = map::HashMap; - type crate_metadata = @{name: ~str, data: @~[u8], cnum_map: cnum_map, @@ -64,7 +67,6 @@ enum CStore { private(cstore_private), } type cstore_private = @{metas: map::HashMap, use_crate_map: use_crate_map, - mod_path_map: mod_path_map, mut used_crate_files: ~[Path], mut used_libraries: ~[~str], mut used_link_args: ~[~str], @@ -81,10 +83,8 @@ pure fn p(cstore: CStore) -> cstore_private { fn mk_cstore(intr: @ident_interner) -> CStore { let meta_cache = map::HashMap(); let crate_map = map::HashMap(); - let mod_path_map = HashMap(); return private(@{metas: meta_cache, use_crate_map: crate_map, - mod_path_map: mod_path_map, mut used_crate_files: ~[], mut used_libraries: ~[], mut used_link_args: ~[], @@ -105,18 +105,10 @@ fn get_crate_vers(cstore: CStore, cnum: ast::crate_num) -> ~str { 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); - let get_crate_data: decoder::GetCrateDataCb = |cnum| { - cstore::get_crate_data(cstore, cnum) - }; - for vec::each(decoder::get_crate_module_paths(cstore.intr, data, - get_crate_data)) |dp| { - let (did, path) = *dp; - let d = {crate: cnum, node: did.node}; - p(cstore).mod_path_map.insert(d, @path); - } } fn have_crate_data(cstore: CStore, cnum: ast::crate_num) -> bool { @@ -134,10 +126,10 @@ fn add_used_crate_file(cstore: CStore, lib: &Path) { } fn get_used_crate_files(cstore: CStore) -> ~[Path] { - return p(cstore).used_crate_files; + return /*bad*/copy 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; } @@ -146,7 +138,7 @@ fn add_used_library(cstore: CStore, lib: ~str) -> bool { } fn get_used_libraries(cstore: CStore) -> ~[~str] { - return p(cstore).used_libraries; + return /*bad*/copy p(cstore).used_libraries; } fn add_used_link_args(cstore: CStore, args: ~str) { @@ -154,7 +146,7 @@ fn add_used_link_args(cstore: CStore, args: ~str) { } fn get_used_link_args(cstore: CStore) -> ~[~str] { - return p(cstore).used_link_args; + return /*bad*/copy p(cstore).used_link_args; } fn add_use_stmt_cnum(cstore: CStore, use_id: ast::node_id, @@ -177,7 +169,7 @@ fn get_dep_hashes(cstore: CStore) -> ~[~str] { let cdata = cstore::get_crate_data(cstore, cnum); let hash = decoder::get_crate_hash(cdata.data); debug!("Add hash[%s]: %s", cdata.name, hash); - result.push({name: cdata.name, hash: hash}); + result.push({name: /*bad*/copy cdata.name, hash: hash}); }; pure fn lteq(a: &crate_hash, b: &crate_hash) -> bool {a.name <= b.name} let sorted = std::sort::merge_sort(result, lteq); @@ -185,14 +177,10 @@ fn get_dep_hashes(cstore: CStore) -> ~[~str] { for sorted.each |x| { debug!(" hash[%s]: %s", x.name, x.hash); } - fn mapper(ch: &crate_hash) -> ~str { return ch.hash; } + fn mapper(ch: &crate_hash) -> ~str { return /*bad*/copy ch.hash; } return vec::map(sorted, mapper); } -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, ~"::")) -} // Local Variables: // mode: rust // fill-column: 78; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 726bc5f95902f..d4cebea66cde8 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // Decoding metadata from a single crate's metadata use cmd = metadata::cstore::crate_metadata; @@ -16,12 +17,22 @@ use hash::{Hash, HashUtil}; use io::WriterUtil; use metadata::common::*; use metadata::csearch::{ProvidedTraitMethodInfo, StaticMethodInfo}; +use metadata::csearch; +use metadata::cstore; +use metadata::decoder; use metadata::tydecode::{parse_ty_data, parse_def_id, parse_bounds_data}; use metadata::tydecode::{parse_ident}; use middle::ty; use util::ppaux::ty_to_str; -use reader = std::ebml::reader; +use core::cmp; +use core::dvec; +use core::int; +use core::io; +use core::option; +use core::str; +use core::vec; +use std::ebml::reader; use std::ebml; use std::map::HashMap; use std::map; @@ -58,12 +69,12 @@ export get_supertraits; export get_method_names_if_trait; export get_type_name_if_impl; export get_item_attrs; -export get_crate_module_paths; export def_like; export dl_def; export dl_impl; export dl_field; export path_entry; +export each_lang_item; export each_path; export get_item_path; export maybe_find_item; // sketchy @@ -462,13 +473,30 @@ struct path_entry { def_like: def_like, } -fn path_entry(path_string: ~str, def_like: def_like) -> path_entry { +fn path_entry(+path_string: ~str, def_like: def_like) -> path_entry { path_entry { path_string: path_string, def_like: def_like } } +/// Iterates over the language items in the given crate. +fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) { + let root = reader::Doc(cdata.data); + let lang_items = reader::get_doc(root, tag_lang_items); + for reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| { + let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id); + let id = reader::doc_as_u32(id_doc) as uint; + let node_id_doc = reader::get_doc(item_doc, + tag_lang_items_item_node_id); + let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id; + + if !f(node_id, id) { + break; + } + } +} + /// Iterates over all the paths in the given crate. fn each_path(intr: @ident_interner, cdata: cmd, get_crate_data: GetCrateDataCb, @@ -493,7 +521,8 @@ fn each_path(intr: @ident_interner, cdata: cmd, let def_like = item_to_def_like(item_doc, def_id, cdata.cnum); // Hand the information off to the iteratee. - let this_path_entry = path_entry(path, def_like); + // XXX: Bad copy. + let this_path_entry = path_entry(copy path, def_like); if !f(this_path_entry) { broken = true; // XXX: This is awful. } @@ -581,7 +610,7 @@ fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, let item_doc = lookup_item(id, cdata.data); let path = vec::init(item_path(intr, item_doc)); match decode_inlined_item(cdata, tcx, path, item_doc) { - Some(ref ii) => csearch::found((*ii)), + Some(ref ii) => csearch::found((/*bad*/copy *ii)), None => { match item_parent_item(item_doc) { Some(did) => { @@ -589,7 +618,7 @@ fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt, let parent_item = lookup_item(did.node, cdata.data); match decode_inlined_item(cdata, tcx, path, parent_item) { - Some(ref ii) => csearch::found_parent(did, (*ii)), + Some(ref ii) => csearch::found_parent(did, (/*bad*/copy *ii)), None => csearch::not_found } } @@ -728,7 +757,7 @@ fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id, 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(ref f) => (*f), + ty::ty_fn(ref f) => (/*bad*/copy *f), _ => { tcx.diag.handler().bug( ~"get_trait_methods: id has non-function type"); @@ -759,7 +788,7 @@ fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd, let fty; match ty::get(ty).sty { - ty::ty_fn(ref f) => fty = (*f), + ty::ty_fn(ref f) => fty = (/*bad*/copy *f), _ => { tcx.diag.handler().bug(~"get_provided_trait_methods(): id \ has non-function type"); @@ -1000,7 +1029,7 @@ fn get_attributes(md: ebml::Doc) -> ~[ast::attribute] { assert (vec::len(meta_items) == 1u); let meta_item = meta_items[0]; attrs.push( - {node: {style: ast::attr_outer, value: *meta_item, + {node: {style: ast::attr_outer, value: /*bad*/copy *meta_item, is_sugared_doc: false}, span: ast_util::dummy_sp()}); }; @@ -1075,52 +1104,25 @@ fn get_crate_vers(data: @~[u8]) -> ~str { let attrs = decoder::get_crate_attributes(data); return match attr::last_meta_item_value_str_by_name( attr::find_linkage_metas(attrs), ~"vers") { - Some(ref ver) => (*ver), + Some(ref ver) => (/*bad*/copy *ver), None => ~"0.0" }; } fn iter_crate_items(intr: @ident_interner, cdata: cmd, get_crate_data: GetCrateDataCb, - proc: fn(~str, ast::def_id)) { + proc: fn(+path: ~str, ast::def_id)) { for each_path(intr, cdata, get_crate_data) |path_entry| { match path_entry.def_like { dl_impl(*) | dl_field => {} dl_def(def) => { - proc(path_entry.path_string, ast_util::def_id_of_def(def)) + proc(/*bad*/copy path_entry.path_string, + ast_util::def_id_of_def(def)) } } } } -fn get_crate_module_paths(intr: @ident_interner, cdata: cmd, - get_crate_data: GetCrateDataCb) - -> ~[(ast::def_id, ~str)] { - fn mod_of_path(p: ~str) -> ~str { - str::connect(vec::init(str::split_str(p, ~"::")), ~"::") - } - - // find all module (path, def_ids), which are not - // fowarded path due to renamed import or reexport - let mut res = ~[]; - let mods = map::HashMap(); - do iter_crate_items(intr, cdata, get_crate_data) |path, did| { - let m = mod_of_path(path); - if str::is_not_empty(m) { - // if m has a sub-item, it must be a module - mods.insert(m, true); - } - // Collect everything by now. There might be multiple - // paths pointing to the same did. Those will be - // unified later by using the mods map - res.push((did, path)); - } - return do vec::filter(res) |x| { - let (_, xp) = *x; - mods.contains_key(xp) - } -} - fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8], out: io::Writer) { let hash = get_crate_hash(bytes); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index ab6992c1283bc..541913be2616d 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -8,30 +8,45 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // Metadata encoding +use metadata::common::*; +use metadata::csearch; +use metadata::cstore; +use metadata::decoder; +use metadata::tyencode; +use middle::resolve; +use middle::ty::node_id_to_type; +use middle::ty; +use middle; use util::ppaux::ty_to_str; -use std::{ebml, map}; +use core::dvec; +use core::flate; +use core::float; +use core::hash::{Hash, HashUtil}; +use core::int; +use core::io::WriterUtil; +use core::io; +use core::str::to_bytes; +use core::str; +use core::to_bytes::IterBytes; +use core::uint; +use core::vec; use std::map::HashMap; -use io::WriterUtil; -use writer = std::ebml::writer; +use std::{ebml, map}; +use std; use syntax::ast::*; -use syntax::print::pprust; -use syntax::{ast_util, visit}; -use syntax::ast_util::*; -use metadata::common::*; -use middle::ty; -use middle::ty::node_id_to_type; -use middle::resolve; +use syntax::ast; use syntax::ast_map; +use syntax::ast_util::*; use syntax::attr; -use str::to_bytes; -use syntax::ast; use syntax::diagnostic::span_handler; - -use hash::{Hash, HashUtil}; -use to_bytes::IterBytes; +use syntax::print::pprust; +use syntax::{ast_util, visit}; +use syntax; +use writer = std::ebml::writer; export encode_parms; export encode_metadata; @@ -70,6 +85,7 @@ type stats = { mut inline_bytes: uint, mut attr_bytes: uint, mut dep_bytes: uint, + mut lang_item_bytes: uint, mut item_bytes: uint, mut index_bytes: uint, mut zero_bytes: uint, @@ -162,11 +178,12 @@ fn def_to_str(did: def_id) -> ~str { fmt!("%d:%d", did.crate, did.node) } fn encode_ty_type_param_bounds(ebml_w: writer::Encoder, ecx: @encode_ctxt, params: @~[ty::param_bounds]) { - let ty_str_ctxt = @{diag: ecx.diag, - ds: def_to_str, - tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; for params.each |param| { ebml_w.start_tag(tag_items_data_item_ty_param_bounds); tyencode::enc_bounds(ebml_w.writer, ty_str_ctxt, *param); @@ -189,23 +206,23 @@ fn encode_variant_id(ebml_w: writer::Encoder, vid: def_id) { } fn write_type(ecx: @encode_ctxt, ebml_w: writer::Encoder, typ: ty::t) { - let ty_str_ctxt = - @{diag: ecx.diag, - ds: def_to_str, - tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ); } fn write_vstore(ecx: @encode_ctxt, ebml_w: writer::Encoder, vstore: ty::vstore) { - let ty_str_ctxt = - @{diag: ecx.diag, - ds: def_to_str, - tcx: ecx.tcx, - reachable: |a| reachable(ecx, a), - abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; + let ty_str_ctxt = @tyencode::ctxt { + diag: ecx.diag, + ds: def_to_str, + tcx: ecx.tcx, + reachable: |a| reachable(ecx, a), + abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)}; tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore); } @@ -218,7 +235,7 @@ fn encode_type(ecx: @encode_ctxt, ebml_w: writer::Encoder, typ: ty::t) { fn encode_symbol(ecx: @encode_ctxt, ebml_w: writer::Encoder, id: node_id) { ebml_w.start_tag(tag_items_data_item_symbol); let sym = match ecx.item_symbols.find(id) { - Some(ref x) => (*x), + Some(ref x) => (/*bad*/copy *x), None => { ecx.diag.handler().bug( fmt!("encode_symbol: id not found %d", id)); @@ -265,7 +282,7 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, variant.node.id)); match variant.node.kind { - ast::tuple_variant_kind(args) + ast::tuple_variant_kind(ref args) if args.len() > 0 && ty_params.len() == 0 => { encode_symbol(ecx, ebml_w, variant.node.id); } @@ -277,8 +294,9 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_disr_val(ecx, ebml_w, vi[i].disr_val); disr_val = vi[i].disr_val; } - encode_type_param_bounds(ebml_w, ecx, ty_params); - encode_path(ecx, ebml_w, path, ast_map::path_name(variant.node.name)); + encode_type_param_bounds(ebml_w, ecx, /*bad*/copy ty_params); + encode_path(ecx, ebml_w, /*bad*/copy path, + ast_map::path_name(variant.node.name)); ebml_w.end_tag(); disr_val += 1; i += 1; @@ -307,7 +325,7 @@ fn encode_path(ecx: @encode_ctxt, ebml_w: writer::Encoder, } fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: writer::Encoder, - md: _mod, id: node_id, path: ast_map::path, + 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)); @@ -434,7 +452,8 @@ fn encode_info_for_struct(ecx: @encode_ctxt, ebml_w: writer::Encoder, tcx.sess.str_of(nm), id); encode_visibility(ebml_w, vis); encode_name(ecx, ebml_w, nm); - encode_path(ecx, ebml_w, path, ast_map::path_name(nm)); + encode_path(ecx, ebml_w, /*bad*/copy path, + ast_map::path_name(nm)); encode_type(ecx, ebml_w, node_id_to_type(tcx, id)); encode_mutability(ebml_w, mt); encode_def_id(ebml_w, local_def(id)); @@ -443,13 +462,13 @@ fn encode_info_for_struct(ecx: @encode_ctxt, ebml_w: writer::Encoder, unnamed_field => {} } } - *index + /*bad*/copy *index } // This is for encoding info for ctors and dtors fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: writer::Encoder, - id: node_id, ident: ident, path: ast_map::path, - item: Option, tps: ~[ty_param]) { + id: node_id, ident: ident, +path: ast_map::path, + item: Option, +tps: ~[ty_param]) { ebml_w.start_tag(tag_items_data_item); encode_name(ecx, ebml_w, ident); encode_def_id(ebml_w, local_def(id)); @@ -458,9 +477,10 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: writer::Encoder, let its_ty = node_id_to_type(ecx.tcx, id); debug!("fn name = %s ty = %s its node id = %d", ecx.tcx.sess.str_of(ident), - util::ppaux::ty_to_str(ecx.tcx, its_ty), id); + ty_to_str(ecx.tcx, its_ty), id); encode_type(ecx, ebml_w, its_ty); - encode_path(ecx, ebml_w, path, ast_map::path_name(ident)); + // XXX: Bad copy. + encode_path(ecx, ebml_w, copy path, ast_map::path_name(ident)); match item { Some(ref it) => { (ecx.encode_inlined_item)(ecx, ebml_w, path, (*it)); @@ -472,10 +492,13 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: writer::Encoder, ebml_w.end_tag(); } -fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: writer::Encoder, - impl_path: ast_map::path, should_inline: bool, +fn encode_info_for_method(ecx: @encode_ctxt, + ebml_w: writer::Encoder, + +impl_path: ast_map::path, + should_inline: bool, parent_id: node_id, - m: @method, all_tps: ~[ty_param]) { + m: @method, + +all_tps: ~[ty_param]) { debug!("encode_info_for_method: %d %s %u", m.id, ecx.tcx.sess.str_of(m.ident), all_tps.len()); ebml_w.start_tag(tag_items_data_item); @@ -486,12 +509,14 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: writer::Encoder, } _ => encode_family(ebml_w, purity_fn_family(m.purity)) } + let len = all_tps.len(); 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); - encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident)); + // XXX: Bad copy. + encode_path(ecx, ebml_w, copy impl_path, ast_map::path_name(m.ident)); encode_self_type(ebml_w, m.self_ty.node); - if all_tps.len() > 0u || should_inline { + if len > 0u || should_inline { (ecx.encode_inlined_item)( ecx, ebml_w, impl_path, ii_method(local_def(parent_id), m)); @@ -529,7 +554,7 @@ fn should_inline(attrs: ~[attribute]) -> bool { fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, item: @item, index: @mut ~[entry], - path: ast_map::path) { + +path: ast_map::path) { let tcx = ecx.tcx; let must_write = @@ -549,7 +574,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, debug!("encoding info for item at %s", ecx.tcx.sess.codemap.span_to_str(item.span)); - match item.node { + match /*bad*/copy item.node { item_const(_, _) => { add_to_index(); ebml_w.start_tag(tag_items_data_item); @@ -565,11 +590,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, purity_fn_family(purity)); + let tps_len = tps.len(); encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); - encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); - encode_attributes(ebml_w, item.attrs); - if tps.len() > 0u || should_inline(item.attrs) { + // XXX: Bad copy. + encode_path(ecx, ebml_w, copy path, ast_map::path_name(item.ident)); + encode_attributes(ebml_w, /*bad*/copy item.attrs); + if tps_len > 0u || should_inline(item.attrs) { (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); } else { encode_symbol(ecx, ebml_w, item.id); @@ -601,36 +628,39 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_region_param(ecx, ebml_w, item); ebml_w.end_tag(); } - item_enum(ref enum_definition, tps) => { + item_enum(ref enum_definition, ref tps) => { add_to_index(); do ebml_w.wr_tag(tag_items_data_item) { encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, 't'); - encode_type_param_bounds(ebml_w, ecx, tps); + encode_type_param_bounds(ebml_w, ecx, /*bad*/copy *tps); encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id)); encode_name(ecx, ebml_w, item.ident); for (*enum_definition).variants.each |v| { encode_variant_id(ebml_w, local_def(v.node.id)); } - (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); - encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); + (ecx.encode_inlined_item)(ecx, ebml_w, /*bad*/copy path, + ii_item(item)); + encode_path(ecx, ebml_w, /*bad*/copy path, + ast_map::path_name(item.ident)); encode_region_param(ecx, ebml_w, item); } encode_enum_variant_info(ecx, ebml_w, item.id, - (*enum_definition).variants, + /*bad*/copy (*enum_definition).variants, path, index, - tps); + /*bad*/copy *tps); } item_struct(struct_def, tps) => { /* First, encode the fields These come first because we need to write them to make the index, and the index needs to be in the item for the class itself */ - let idx = encode_info_for_struct(ecx, ebml_w, path, - struct_def.fields, index); + // XXX: Bad copy of `path`. + let idx = encode_info_for_struct(ecx, ebml_w, copy path, + /*bad*/copy struct_def.fields, index); /* Encode the dtor */ do struct_def.dtor.iter |dtor| { index.push({val: dtor.node.id, pos: ebml_w.writer.tell()}); @@ -638,10 +668,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, ecx.tcx.sess.ident_of( ecx.tcx.sess.str_of(item.ident) + ~"_dtor"), - path, if tps.len() > 0u { + /*bad*/copy path, if tps.len() > 0u { Some(ii_dtor(*dtor, item.ident, tps, local_def(item.id))) } - else { None }, tps); + else { None }, /*bad*/copy tps); } /* Index the class*/ @@ -690,10 +720,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, 'i'); encode_region_param(ecx, ebml_w, item); - encode_type_param_bounds(ebml_w, ecx, tps); + // XXX: Bad copy. + encode_type_param_bounds(ebml_w, ecx, copy tps); 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); + encode_attributes(ebml_w, /*bad*/copy item.attrs); match ty.node { ast::ty_path(path, _) if path.idents.len() == 1 => { encode_impl_type_basename(ecx, ebml_w, @@ -710,19 +741,21 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, do opt_trait.iter() |associated_trait| { encode_trait_ref(ebml_w, ecx, *associated_trait); } - encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); + // XXX: Bad copy. + encode_path(ecx, ebml_w, copy path, ast_map::path_name(item.ident)); ebml_w.end_tag(); let impl_path = vec::append_one(path, ast_map::path_name(item.ident)); for methods.each |m| { index.push({val: m.id, pos: ebml_w.writer.tell()}); - encode_info_for_method(ecx, ebml_w, impl_path, - should_inline(m.attrs), item.id, *m, - vec::append(tps, m.tps)); + encode_info_for_method(ecx, ebml_w, /*bad*/copy impl_path, + should_inline(/*bad*/copy m.attrs), + item.id, *m, + vec::append(/*bad*/copy tps, m.tps)); } } - item_trait(tps, traits, ref ms) => { + item_trait(ref tps, ref traits, ref ms) => { let provided_methods = dvec::DVec(); add_to_index(); @@ -730,10 +763,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_def_id(ebml_w, local_def(item.id)); encode_family(ebml_w, 'I'); encode_region_param(ecx, ebml_w, item); - encode_type_param_bounds(ebml_w, ecx, tps); + encode_type_param_bounds(ebml_w, ecx, /*bad*/copy *tps); 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); + encode_attributes(ebml_w, /*bad*/copy item.attrs); let mut i = 0u; for vec::each(*ty::trait_methods(tcx, local_def(item.id))) |mty| { match (*ms)[i] { @@ -741,8 +774,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, ebml_w.start_tag(tag_item_trait_method); encode_def_id(ebml_w, local_def((*ty_m).id)); encode_name(ecx, ebml_w, mty.ident); - encode_type_param_bounds(ebml_w, ecx, (*ty_m).tps); - encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty)); + encode_type_param_bounds(ebml_w, ecx, + /*bad*/copy (*ty_m).tps); + encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy 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'); @@ -754,8 +788,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, 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_type_param_bounds(ebml_w, ecx, /*bad*/copy m.tps); + encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy 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'); @@ -764,7 +798,8 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, } i += 1u; } - encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident)); + // XXX: Bad copy. + encode_path(ecx, ebml_w, copy path, ast_map::path_name(item.ident)); for traits.each |associated_trait| { encode_trait_ref(ebml_w, ecx, *associated_trait) } @@ -790,7 +825,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, let polyty = ecx.tcx.tcache.get(local_def(ty_m.id)); encode_ty_type_param_bounds(ebml_w, ecx, polyty.bounds); encode_type(ecx, ebml_w, polyty.ty); - let m_path = vec::append_one(path, + let m_path = vec::append_one(/*bad*/copy path, ast_map::path_name(item.ident)); encode_path(ecx, ebml_w, m_path, ast_map::path_name(ty_m.ident)); ebml_w.end_tag(); @@ -799,30 +834,33 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, // 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); + encode_info_for_method(ecx, ebml_w, /*bad*/copy path, + true, item.id, *m, /*bad*/copy m.tps); } } item_mac(*) => fail ~"item macros unimplemented" } } -fn encode_info_for_foreign_item(ecx: @encode_ctxt, ebml_w: writer::Encoder, +fn encode_info_for_foreign_item(ecx: @encode_ctxt, + ebml_w: writer::Encoder, nitem: @foreign_item, index: @mut ~[entry], - path: ast_map::path, abi: foreign_abi) { + +path: ast_map::path, + abi: foreign_abi) { if !reachable(ecx, nitem.id) { return; } index.push({val: nitem.id, pos: ebml_w.writer.tell()}); ebml_w.start_tag(tag_items_data_item); - match nitem.node { + match /*bad*/copy nitem.node { foreign_item_fn(_, purity, tps) => { encode_def_id(ebml_w, local_def(nitem.id)); encode_family(ebml_w, purity_fn_family(purity)); encode_type_param_bounds(ebml_w, ecx, tps); encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id)); if abi == foreign_abi_rust_intrinsic { - (ecx.encode_inlined_item)(ecx, ebml_w, path, + // XXX: Bad copy of `path`. + (ecx.encode_inlined_item)(ecx, ebml_w, copy path, ii_foreign(nitem)); } else { encode_symbol(ecx, ebml_w, nitem.id); @@ -848,13 +886,13 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: writer::Encoder, encode_info_for_mod(ecx, ebml_w, crate.node.module, crate_node_id, ~[], syntax::parse::token::special_idents::invalid); - visit::visit_crate(*crate, (), visit::mk_vt(@{ + visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |_e, _cx, _v| { }, visit_item: |i, cx, v, copy ebml_w| { visit::visit_item(i, cx, v); match ecx.tcx.items.get(i.id) { ast_map::node_item(_, pt) => { - encode_info_for_item(ecx, ebml_w, i, index, *pt); + encode_info_for_item(ecx, ebml_w, i, index, /*bad*/copy *pt); } _ => fail ~"bad item" } @@ -864,7 +902,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: writer::Encoder, match ecx.tcx.items.get(ni.id) { ast_map::node_foreign_item(_, abi, pt) => { encode_info_for_foreign_item(ecx, ebml_w, ni, - index, *pt, abi); + index, /*bad*/copy *pt, abi); } // case for separate item and foreign-item tables _ => fail ~"bad foreign item" @@ -873,7 +911,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: writer::Encoder, ,.. *visit::default_visitor() })); ebml_w.end_tag(); - return *index; + return /*bad*/copy *index; } @@ -890,7 +928,7 @@ fn create_index(index: ~[entry]) -> let mut buckets_frozen = ~[]; for buckets.each |bucket| { - buckets_frozen.push(@**bucket); + buckets_frozen.push(@/*bad*/copy **bucket); } return buckets_frozen; } @@ -954,7 +992,7 @@ fn encode_meta_item(ebml_w: writer::Encoder, mi: meta_item) { _ => {/* FIXME (#623): encode other variants */ } } } - meta_list(ref name, items) => { + meta_list(ref name, ref items) => { ebml_w.start_tag(tag_meta_item_list); ebml_w.start_tag(tag_meta_item_name); ebml_w.writer.write(str::to_bytes((*name))); @@ -983,16 +1021,18 @@ fn encode_attributes(ebml_w: writer::Encoder, attrs: ~[attribute]) { // them in anyway with default values. fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] { - fn synthesize_link_attr(ecx: @encode_ctxt, items: ~[@meta_item]) -> + fn synthesize_link_attr(ecx: @encode_ctxt, +items: ~[@meta_item]) -> attribute { assert (ecx.link_meta.name != ~""); assert (ecx.link_meta.vers != ~""); let name_item = - attr::mk_name_value_item_str(~"name", ecx.link_meta.name); + attr::mk_name_value_item_str(~"name", + /*bad*/copy ecx.link_meta.name); let vers_item = - attr::mk_name_value_item_str(~"vers", ecx.link_meta.vers); + attr::mk_name_value_item_str(~"vers", + /*bad*/copy ecx.link_meta.vers); let other_items = { @@ -1011,14 +1051,14 @@ fn synthesize_crate_attrs(ecx: @encode_ctxt, crate: @crate) -> ~[attribute] { for crate.node.attrs.each |attr| { attrs.push( if attr::get_attr_name(*attr) != ~"link" { - *attr + /*bad*/copy *attr } else { - match attr.node.value.node { + match /*bad*/copy attr.node.value.node { meta_list(_, l) => { found_link_attr = true;; synthesize_link_attr(ecx, l) } - _ => *attr + _ => /*bad*/copy *attr } }); } @@ -1040,7 +1080,8 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: writer::Encoder, // Pull the cnums and name,vers,hash out of cstore let mut deps: ~[numdep] = ~[]; do cstore::iter_crate_data(cstore) |key, val| { - let dep = {cnum: key, name: ecx.tcx.sess.ident_of(val.name), + let dep = {cnum: key, + name: ecx.tcx.sess.ident_of(/*bad*/copy val.name), vers: decoder::get_crate_vers(val.data), hash: decoder::get_crate_hash(val.data)}; deps.push(dep); @@ -1074,6 +1115,30 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: writer::Encoder, ebml_w.end_tag(); } +fn encode_lang_items(ecx: @encode_ctxt, ebml_w: writer::Encoder) { + ebml_w.start_tag(tag_lang_items); + + for ecx.tcx.lang_items.each_item |def_id, i| { + if def_id.crate != local_crate { + loop; + } + + ebml_w.start_tag(tag_lang_items_item); + + ebml_w.start_tag(tag_lang_items_item_id); + ebml_w.writer.write_be_u32(i as u32); + ebml_w.end_tag(); // tag_lang_items_item_id + + ebml_w.start_tag(tag_lang_items_item_node_id); + ebml_w.writer.write_be_u32(def_id.node as u32); + ebml_w.end_tag(); // tag_lang_items_item_node_id + + ebml_w.end_tag(); // tag_lang_items_item + } + + ebml_w.end_tag(); // tag_lang_items +} + fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: writer::Encoder, dep: decoder::crate_dep) { ebml_w.start_tag(tag_crate_dep); @@ -1108,6 +1173,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { {mut inline_bytes: 0, mut attr_bytes: 0, mut dep_bytes: 0, + mut lang_item_bytes: 0, mut item_bytes: 0, mut index_bytes: 0, mut zero_bytes: 0, @@ -1121,7 +1187,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { reexports2: parms.reexports2, item_symbols: parms.item_symbols, discrim_symbols: parms.discrim_symbols, - link_meta: parms.link_meta, + link_meta: /*bad*/copy parms.link_meta, cstore: parms.cstore, encode_inlined_item: parms.encode_inlined_item, type_abbrevs: ty::new_ty_hash() @@ -1129,7 +1195,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { let ebml_w = writer::Encoder(wr as io::Writer); - encode_hash(ebml_w, ecx.link_meta.extras_hash); + encode_hash(ebml_w, /*bad*/copy ecx.link_meta.extras_hash); let mut i = wr.pos; let crate_attrs = synthesize_crate_attrs(ecx, crate); @@ -1140,6 +1206,11 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { encode_crate_deps(ecx, ebml_w, ecx.cstore); ecx.stats.dep_bytes = wr.pos - i; + // Encode the language items. + i = wr.pos; + encode_lang_items(ecx, ebml_w); + ecx.stats.lang_item_bytes = wr.pos - i; + // Encode and index the items. ebml_w.start_tag(tag_items); i = wr.pos; @@ -1169,6 +1240,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes)); io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes)); io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes)); + io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes)); io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes)); io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes)); io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes)); @@ -1194,11 +1266,12 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] { // Get the encoded string for a type fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str { - let cx = @{diag: tcx.diag, - ds: def_to_str, - tcx: tcx, - reachable: |_id| false, - abbrevs: tyencode::ac_no_abbrevs}; + let cx = @tyencode::ctxt { + diag: tcx.diag, + ds: def_to_str, + tcx: tcx, + reachable: |_id| false, + abbrevs: tyencode::ac_no_abbrevs}; do io::with_str_writer |wr| { tyencode::enc_ty(wr, cx, t); } diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index be4968636f158..0401d8fcb6ca6 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // A module for searching for libraries // FIXME (#2658): I'm not happy how this module turned out. Should // probably just be folded into cstore. -use result::Result; +use core::option; +use core::os; +use core::result::Result; +use core::result; +use core::str; + export FileSearch; export mk_filesearch; export pick; @@ -40,24 +46,24 @@ 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 { - fn sysroot() -> Path { self.sysroot } + fn sysroot() -> Path { /*bad*/copy self.sysroot } fn lib_search_paths() -> ~[Path] { - let mut paths = self.addl_lib_search_paths; + let mut paths = /*bad*/copy self.addl_lib_search_paths; paths.push( make_target_lib_path(&self.sysroot, self.target_triple)); match get_cargo_lib_path_nearest() { - result::Ok(ref p) => paths.push((*p)), + result::Ok(ref p) => paths.push((/*bad*/copy *p)), result::Err(_) => () } match get_cargo_lib_path() { - result::Ok(ref p) => paths.push((*p)), + result::Ok(ref p) => paths.push((/*bad*/copy *p)), result::Err(_) => () } paths @@ -108,7 +114,7 @@ fn make_target_lib_path(sysroot: &Path, sysroot.push_rel(&relative_target_lib_path(target_triple)) } -fn get_default_sysroot() -> Path { +fn get_or_default_sysroot() -> Path { match os::self_exe_path() { option::Some(ref p) => (*p).pop(), option::None => fail ~"can't determine value for sysroot" @@ -117,13 +123,13 @@ fn get_default_sysroot() -> Path { fn get_sysroot(maybe_sysroot: Option) -> Path { match maybe_sysroot { - option::Some(ref sr) => (*sr), - option::None => get_default_sysroot() + option::Some(ref sr) => (/*bad*/copy *sr), + option::None => get_or_default_sysroot() } } fn get_cargo_sysroot() -> Result { - result::Ok(get_default_sysroot().push_many([libdir(), ~"cargo"])) + result::Ok(get_or_default_sysroot().push_many([libdir(), ~"cargo"])) } fn get_cargo_root() -> Result { @@ -141,7 +147,7 @@ fn get_cargo_root_nearest() -> Result { let cwd = os::getcwd(); let cwd_cargo = cwd.push(".cargo"); let mut par_cargo = cwd.pop().push(".cargo"); - let mut rslt = result::Ok(cwd_cargo); + let mut rslt = result::Ok(copy cwd_cargo); // XXX: Bad copy. if !os::path_is_dir(&cwd_cargo) && cwd_cargo != p { while par_cargo != p { diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 5901e58aeb190..fa858f9e9a33e 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -8,16 +8,31 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + //! Finds crate binaries and loads their metadata -use syntax::diagnostic::span_handler; -use syntax::{ast, attr}; -use syntax::print::pprust; -use syntax::codemap::span; use lib::llvm::{False, llvm, mk_object_file, mk_section_iter}; +use metadata::decoder; +use metadata::encoder; use metadata::filesearch::FileSearch; -use io::WriterUtil; +use metadata::filesearch; +use syntax::codemap::span; +use syntax::diagnostic::span_handler; use syntax::parse::token::ident_interner; +use syntax::print::pprust; +use syntax::{ast, attr}; + +use core::cast; +use core::flate; +use core::io::WriterUtil; +use core::io; +use core::option; +use core::ptr; +use core::str; +use core::uint; +use core::vec; + +use core::os::consts::{macos, freebsd, linux, win32}; export os; export os_macos, os_win32, os_linux, os_freebsd; @@ -50,7 +65,7 @@ type ctxt = { fn load_library_crate(cx: ctxt) -> {ident: ~str, data: @~[u8]} { match find_library_crate(cx) { - Some(ref t) => return (*t), + Some(ref t) => return (/*bad*/copy *t), None => { cx.diag.span_fatal( cx.span, fmt!("can't find crate for `%s`", @@ -60,17 +75,21 @@ fn load_library_crate(cx: ctxt) -> {ident: ~str, data: @~[u8]} { } fn find_library_crate(cx: ctxt) -> Option<{ident: ~str, data: @~[u8]}> { - attr::require_unique_names(cx.diag, cx.metas); + attr::require_unique_names(cx.diag, /*bad*/copy cx.metas); find_library_crate_aux(cx, libname(cx), cx.filesearch) } fn libname(cx: ctxt) -> {prefix: ~str, suffix: ~str} { if cx.static { return {prefix: ~"lib", suffix: ~".rlib"}; } - match cx.os { - os_win32 => return {prefix: ~"", suffix: ~".dll"}, - os_macos => return {prefix: ~"lib", suffix: ~".dylib"}, - os_linux => return {prefix: ~"lib", suffix: ~".so"}, - os_freebsd => return {prefix: ~"lib", suffix: ~".so"} + let (dll_prefix, dll_suffix) = match cx.os { + os_win32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX), + os_macos => (macos::DLL_PREFIX, macos::DLL_SUFFIX), + os_linux => (linux::DLL_PREFIX, linux::DLL_SUFFIX), + os_freebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX), + }; + return { + prefix: str::from_slice(dll_prefix), + suffix: str::from_slice(dll_suffix) } } @@ -78,9 +97,9 @@ fn find_library_crate_aux(cx: ctxt, nn: {prefix: ~str, suffix: ~str}, filesearch: filesearch::FileSearch) -> Option<{ident: ~str, data: @~[u8]}> { - let crate_name = crate_name_from_metas(cx.metas); + let crate_name = crate_name_from_metas(/*bad*/copy cx.metas); let prefix: ~str = nn.prefix + crate_name + ~"-"; - let suffix: ~str = nn.suffix; + let suffix: ~str = /*bad*/copy nn.suffix; let mut matches = ~[]; filesearch::search(filesearch, |path| { @@ -115,7 +134,7 @@ fn find_library_crate_aux(cx: ctxt, if matches.is_empty() { None } else if matches.len() == 1u { - Some(matches[0]) + Some(/*bad*/copy matches[0]) } else { cx.diag.span_err( cx.span, fmt!("multiple matching crates for `%s`", crate_name)); @@ -130,12 +149,12 @@ fn find_library_crate_aux(cx: ctxt, } } -fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> ~str { +fn crate_name_from_metas(+metas: ~[@ast::meta_item]) -> ~str { let name_items = attr::find_meta_items_by_name(metas, ~"name"); match vec::last_opt(name_items) { Some(i) => { match attr::get_meta_item_value_str(i) { - Some(ref n) => (*n), + Some(ref n) => (/*bad*/copy *n), // FIXME (#2406): Probably want a warning here since the user // is using the wrong type of meta item. _ => fail @@ -153,7 +172,7 @@ fn note_linkage_attrs(intr: @ident_interner, diag: span_handler, } } -fn crate_matches(crate_data: @~[u8], metas: ~[@ast::meta_item], +fn crate_matches(crate_data: @~[u8], +metas: ~[@ast::meta_item], hash: ~str) -> bool { let attrs = decoder::get_crate_attributes(crate_data); let linkage_metas = attr::find_linkage_metas(attrs); diff --git a/src/librustc/metadata/mod.rs b/src/librustc/metadata/mod.rs index 4ba6abb038310..25a73b009a94f 100644 --- a/src/librustc/metadata/mod.rs +++ b/src/librustc/metadata/mod.rs @@ -9,6 +9,7 @@ // except according to those terms. #[legacy_exports]; + export encoder; export creader; export cstore; diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index c7ee052147f9a..089e528c0c2e4 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // Type decoding // tjc note: Would be great to have a `match check` macro equivalent @@ -16,6 +17,10 @@ use middle::ty; use middle::ty::{FnTyBase, FnMeta, FnSig}; +use core::io; +use core::str; +use core::uint; +use core::vec; use syntax::ast; use syntax::ast::*; use syntax::ast_util; @@ -85,13 +90,6 @@ fn parse_arg_data(data: @~[u8], crate_num: int, pos: uint, tcx: ty::ctxt, parse_arg(st, conv) } -fn parse_ret_ty(st: @pstate, conv: conv_did) -> (ast::ret_style, ty::t) { - match peek(st) { - '!' => { next(st); (ast::noreturn, ty::mk_bot(st.tcx)) } - _ => (ast::return_val, parse_ty(st, conv)) - } -} - fn parse_path(st: @pstate) -> @ast::path { let mut idents: ~[ast::ident] = ~[]; fn is_last(c: char) -> bool { return c == '(' || c == ':'; } @@ -432,14 +430,13 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy { inputs.push({mode: mode, ty: parse_ty(st, conv)}); } st.pos += 1u; // eat the ']' - let (ret_style, ret_ty) = parse_ret_ty(st, conv); + let ret_ty = parse_ty(st, conv); return FnTyBase { meta: FnMeta {purity: purity, proto: proto, onceness: onceness, bounds: bounds, - region: region, - ret_style: ret_style}, + region: region}, sig: FnSig {inputs: inputs, output: ret_ty} }; diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 6ceb592f6c9dd..9ae47425fa78a 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -8,15 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // Type encoding -use io::WriterUtil; +use middle::ty; +use middle::ty::Vid; + +use core::io::WriterUtil; +use core::io; +use core::uint; +use core::vec; use std::map::HashMap; use syntax::ast::*; use syntax::diagnostic::span_handler; -use middle::ty; -use middle::ty::vid; use syntax::print::pprust::*; +use middle::ty::Vid; export ctxt; export ty_abbrev; @@ -28,7 +34,7 @@ export enc_mode; export enc_arg; export enc_vstore; -type ctxt = { +struct ctxt { diag: span_handler, // Def -> str Callback: ds: fn@(def_id) -> ~str, @@ -36,7 +42,7 @@ type ctxt = { tcx: ty::ctxt, reachable: fn@(node_id) -> bool, abbrevs: abbrev_ctxt -}; +} // Compact string representation for ty.t values. API ty_str & parse_from_str. // Extra parameters are for converting to/from def_ids in the string rep. @@ -56,12 +62,12 @@ fn enc_ty(w: io::Writer, cx: @ctxt, t: ty::t) { match cx.abbrevs { ac_no_abbrevs => { let result_str = match cx.tcx.short_names_cache.find(t) { - Some(s) => *s, + Some(s) => /*bad*/copy *s, None => { let s = do io::with_str_writer |wr| { - enc_sty(wr, cx, ty::get(t).sty); + enc_sty(wr, cx, /*bad*/copy ty::get(t).sty); }; - cx.tcx.short_names_cache.insert(t, @s); + cx.tcx.short_names_cache.insert(t, @copy s); s } }; @@ -85,7 +91,7 @@ fn enc_ty(w: io::Writer, cx: @ctxt, t: ty::t) { } _ => {} } - enc_sty(w, cx, ty::get(t).sty); + enc_sty(w, cx, /*bad*/copy ty::get(t).sty); let end = w.tell(); let len = end - pos; fn estimate_sz(u: uint) -> uint { @@ -183,6 +189,9 @@ fn enc_bound_region(w: io::Writer, cx: @ctxt, br: ty::bound_region) { w.write_char('|'); enc_bound_region(w, cx, *br); } + ty::br_fresh(id) => { + w.write_uint(id); + } } } @@ -206,7 +215,7 @@ fn enc_vstore(w: io::Writer, cx: @ctxt, v: ty::vstore) { } } -fn enc_sty(w: io::Writer, cx: @ctxt, st: ty::sty) { +fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) { match st { ty::ty_nil => w.write_char('n'), ty::ty_bot => w.write_char('z'), @@ -383,10 +392,7 @@ fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) { enc_arg(w, cx, *arg); } w.write_char(']'); - match ft.meta.ret_style { - noreturn => w.write_char('!'), - _ => enc_ty(w, cx, ft.sig.output) - } + enc_ty(w, cx, ft.sig.output); } fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) { diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 40d4bd61668b0..3ab8d39d49dae 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use c = metadata::common; use cstore = metadata::cstore; use driver::session::Session; @@ -20,13 +21,16 @@ use middle::freevars::freevar_entry; use middle::typeck::{method_origin, method_map_entry, vtable_res}; use middle::typeck::{vtable_origin}; use middle::{ty, typeck}; +use middle; use util::ppaux::ty_to_str; -use reader = std::ebml::reader; +use core::{dvec, io, option, vec}; use std::ebml::reader::get_doc; +use std::ebml::reader; use std::ebml::writer::Encoder; use std::ebml; use std::map::HashMap; +use std::prettyprint; use std::serialize; use std::serialize::{Encodable, EncoderHelpers, DecoderHelpers}; use std::serialize::Decodable; @@ -41,6 +45,7 @@ use syntax::fold; use syntax::parse; use syntax::print::pprust; use syntax::visit; +use syntax; use writer = std::ebml::writer; export maps; @@ -109,7 +114,7 @@ fn encode_inlined_item(ecx: @e::encode_ctxt, fn decode_inlined_item(cdata: cstore::crate_metadata, tcx: ty::ctxt, maps: maps, - path: ast_map::path, + +path: ast_map::path, par_doc: ebml::Doc) -> Option { let dcx = @{cdata: cdata, tcx: tcx, maps: maps}; match par_doc.opt_child(c::tag_ast) { @@ -125,8 +130,9 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, to_id_range: to_id_range}); let raw_ii = decode_ast(ast_doc); let ii = renumber_ast(xcx, raw_ii); + // XXX: Bad copy of `path`. ast_map::map_decoded_item(tcx.sess.diagnostic(), - dcx.tcx.items, path, ii); + dcx.tcx.items, copy path, ii); debug!("Fn named: %s", tcx.sess.str_of(ii.ident())); decode_side_tables(xcx, ast_doc); debug!("< Decoded inlined fn: %s::%s", @@ -257,11 +263,12 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::stmt_mac(*) => fail ~"unexpanded macro in astencode" } }; - let blk_sans_items = { stmts: stmts_sans_items,.. blk }; + // XXX: Bad copy. + let blk_sans_items = { stmts: stmts_sans_items,.. copy blk }; fold::noop_fold_block(blk_sans_items, fld) } - let fld = fold::make_fold(@{ + let fld = fold::make_fold(@fold::AstFoldFns { fold_block: fold::wrap(drop_nested_items), .. *fold::default_ast_fold() }); @@ -276,11 +283,11 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item { ast::ii_foreign(i) => { ast::ii_foreign(fld.fold_foreign_item(i)) } - ast::ii_dtor(ref dtor, nm, tps, parent_id) => { + ast::ii_dtor(ref dtor, nm, ref tps, parent_id) => { let dtor_body = fld.fold_block((*dtor).node.body); ast::ii_dtor({node: {body: dtor_body, - .. (*dtor).node}, - .. (*dtor)}, nm, tps, parent_id) + .. /*bad*/copy (*dtor).node}, + .. (/*bad*/copy *dtor)}, nm, /*bad*/copy *tps, parent_id) } } } @@ -293,7 +300,7 @@ fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item { fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item) -> ast::inlined_item { - let fld = fold::make_fold(@{ + let fld = fold::make_fold(@fold::AstFoldFns{ new_id: |a| xcx.tr_id(a), new_span: |a| xcx.tr_span(a), .. *fold::default_ast_fold() @@ -309,16 +316,16 @@ 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_dtor(ref dtor, nm, tps, parent_id) => { + ast::ii_dtor(ref dtor, nm, ref tps, parent_id) => { let dtor_body = fld.fold_block((*dtor).node.body); - let dtor_attrs = fld.fold_attributes((*dtor).node.attrs); - let new_params = fold::fold_ty_params(tps, fld); + let dtor_attrs = fld.fold_attributes(/*bad*/copy (*dtor).node.attrs); + let new_params = fold::fold_ty_params(/*bad*/copy *tps, fld); let dtor_id = fld.new_id((*dtor).node.id); let new_parent = xcx.tr_def_id(parent_id); let new_self = fld.new_id((*dtor).node.self_id); ast::ii_dtor({node: {id: dtor_id, attrs: dtor_attrs, self_id: new_self, body: dtor_body}, - .. (*dtor)}, + .. (/*bad*/copy *dtor)}, nm, new_params, new_parent) } } @@ -411,7 +418,8 @@ impl ty::Region: tr { impl ty::bound_region: tr { fn tr(xcx: extended_decode_ctxt) -> ty::bound_region { match self { - ty::br_anon(_) | ty::br_named(_) | ty::br_self => self, + ty::br_anon(_) | ty::br_named(_) | ty::br_self | + ty::br_fresh(_) => self, ty::br_cap_avoid(id, br) => ty::br_cap_avoid(xcx.tr_id(id), @br.tr(xcx)) } @@ -516,7 +524,7 @@ fn encode_vtable_res(ecx: @e::encode_ctxt, // ty::t doesn't work, and there is no way (atm) to have // hand-written encoding routines combine with auto-generated // ones. perhaps we should fix this. - do ebml_w.emit_from_vec(*dr) |vtable_origin| { + do ebml_w.emit_from_vec(/*bad*/copy *dr) |vtable_origin| { encode_vtable_origin(ecx, ebml_w, *vtable_origin) } } @@ -525,14 +533,14 @@ fn encode_vtable_origin(ecx: @e::encode_ctxt, ebml_w: writer::Encoder, vtable_origin: typeck::vtable_origin) { do ebml_w.emit_enum(~"vtable_origin") { - match vtable_origin { + match /*bad*/copy vtable_origin { typeck::vtable_static(def_id, tys, vtable_res) => { do ebml_w.emit_enum_variant(~"vtable_static", 0u, 3u) { do ebml_w.emit_enum_variant_arg(0u) { ebml_w.emit_def_id(def_id) } do ebml_w.emit_enum_variant_arg(1u) { - ebml_w.emit_tys(ecx, tys); + ebml_w.emit_tys(ecx, /*bad*/copy tys); } do ebml_w.emit_enum_variant_arg(2u) { encode_vtable_res(ecx, ebml_w, vtable_res); @@ -555,7 +563,7 @@ fn encode_vtable_origin(ecx: @e::encode_ctxt, ebml_w.emit_def_id(def_id) } do ebml_w.emit_enum_variant_arg(1u) { - ebml_w.emit_tys(ecx, tys); + ebml_w.emit_tys(ecx, /*bad*/copy tys); } } } @@ -629,11 +637,11 @@ trait get_ty_str_ctxt { impl @e::encode_ctxt: get_ty_str_ctxt { fn ty_str_ctxt() -> @tyencode::ctxt { - @{diag: self.tcx.sess.diagnostic(), - ds: e::def_to_str, - tcx: self.tcx, - reachable: |a| encoder::reachable(self, a), - abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)} + @tyencode::ctxt {diag: self.tcx.sess.diagnostic(), + ds: e::def_to_str, + tcx: self.tcx, + reachable: |a| encoder::reachable(self, a), + abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)} } } @@ -666,7 +674,8 @@ impl writer::Encoder: ebml_writer_helpers { } fn emit_tys(ecx: @e::encode_ctxt, tys: ~[ty::t]) { - do self.emit_from_vec(tys) |ty| { + // XXX: Bad copy. + do self.emit_from_vec(copy tys) |ty| { self.emit_ty(ecx, *ty) } } @@ -680,7 +689,7 @@ impl writer::Encoder: ebml_writer_helpers { fn emit_tpbt(ecx: @e::encode_ctxt, tpbt: ty::ty_param_bounds_and_ty) { do self.emit_rec { do self.emit_field(~"bounds", 0u) { - do self.emit_from_vec(*tpbt.bounds) |bs| { + do self.emit_from_vec(/*bad*/copy *tpbt.bounds) |bs| { self.emit_bounds(ecx, *bs); } } @@ -754,7 +763,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, do ebml_w.tag(c::tag_table_node_type_subst) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - ebml_w.emit_tys(ecx, *tys) + ebml_w.emit_tys(ecx, /*bad*/copy *tys) } } } @@ -763,7 +772,7 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt, do ebml_w.tag(c::tag_table_freevars) { ebml_w.id(id); do ebml_w.tag(c::tag_table_val) { - do ebml_w.emit_from_vec(**fv) |fv_entry| { + do ebml_w.emit_from_vec(/*bad*/copy **fv) |fv_entry| { encode_freevar_entry(ebml_w, *fv_entry) } } @@ -1030,7 +1039,7 @@ trait fake_ext_ctxt { fn cfg() -> ast::crate_cfg; fn parse_sess() -> parse::parse_sess; fn call_site() -> span; - fn ident_of(st: ~str) -> ast::ident; + fn ident_of(+st: ~str) -> ast::ident; } #[cfg(test)] @@ -1047,7 +1056,7 @@ impl fake_session: fake_ext_ctxt { expn_info: None } } - fn ident_of(st: ~str) -> ast::ident { + fn ident_of(+st: ~str) -> ast::ident { self.interner.intern(@st) } } @@ -1068,10 +1077,10 @@ fn roundtrip(in_item: Option<@ast::item>) { let out_item = decode_item_ast(ebml_doc); let exp_str = do io::with_str_writer |w| { - in_item.encode(&std::prettyprint::Encoder(w)) + in_item.encode(&prettyprint::Serializer(w)) }; let out_str = do io::with_str_writer |w| { - out_item.encode(&std::prettyprint::Encoder(w)) + out_item.encode(&prettyprint::Serializer(w)) }; debug!("expected string: %s", exp_str); diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 858cfb06d5120..9f3ca5a6cfff1 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -17,9 +17,18 @@ // 3. assignments do not affect things loaned out as immutable // 4. moves to dnot affect things loaned out in any way + use middle::ty::{CopyValue, MoveValue, ReadValue}; +use middle::ty; -use dvec::DVec; +use core::cmp; +use core::dvec::DVec; +use core::uint; +use core::vec; +use syntax::ast; +use syntax::ast_util; +use syntax::print::pprust; +use syntax::visit; export check_loans; @@ -72,11 +81,11 @@ fn check_loans(bccx: borrowck_ctxt, reported: HashMap(), mut declared_purity: ast::impure_fn, mut fn_args: @~[]}); - let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr, - visit_local: check_loans_in_local, - visit_block: check_loans_in_block, - visit_fn: check_loans_in_fn, - .. *visit::default_visitor()}); + let vt = visit::mk_vt(@visit::Visitor {visit_expr: check_loans_in_expr, + visit_local: check_loans_in_local, + visit_block: check_loans_in_block, + visit_fn: check_loans_in_fn, + .. *visit::default_visitor()}); visit::visit_crate(*crate, clcx, vt); } @@ -227,13 +236,13 @@ impl check_loan_ctxt { let callee_ty = ty::node_id_to_type(tcx, callee_id); match ty::get(callee_ty).sty { ty::ty_fn(ref fn_ty) => { - match (*fn_ty).meta.purity { + match fn_ty.meta.purity { ast::pure_fn => return, // case (c) above ast::impure_fn | ast::unsafe_fn | ast::extern_fn => { self.report_purity_error( pc, callee_span, fmt!("access to %s function", - pprust::purity_to_str((*fn_ty).meta.purity))); + fn_ty.meta.purity.to_str())); } } } @@ -623,7 +632,7 @@ fn check_loans_in_expr(expr: @ast::expr, Some(ReadValue) | Some(CopyValue) | None => {} } - match expr.node { + match /*bad*/copy expr.node { ast::expr_path(*) if self.bccx.last_use_map.contains_key(expr.id) => { self.check_last_use(expr); } diff --git a/src/librustc/middle/borrowck/gather_loans.rs b/src/librustc/middle/borrowck/gather_loans.rs index d5809a7389e81..8cb40f3c3f581 100644 --- a/src/librustc/middle/borrowck/gather_loans.rs +++ b/src/librustc/middle/borrowck/gather_loans.rs @@ -16,11 +16,19 @@ // their associated scopes. In phase two, checking loans, we will then make // sure that all of these loans are honored. -use middle::mem_categorization::{mem_categorization_ctxt, opt_deref_kind}; + use middle::borrowck::preserve::{preserve_condition, pc_ok, pc_if_pure}; +use middle::mem_categorization::{mem_categorization_ctxt, opt_deref_kind}; +use middle::pat_util; use middle::ty::{ty_region}; +use middle::ty; +use core::dvec; use core::send_map::linear::LinearMap; +use core::vec; +use syntax::ast; +use syntax::print::pprust; +use syntax::visit; export gather_loans; @@ -65,9 +73,9 @@ fn gather_loans(bccx: borrowck_ctxt, crate: @ast::crate) -> req_maps { mut item_ub: 0, mut root_ub: 0, mut ignore_adjustments: LinearMap()}); - let v = visit::mk_vt(@{visit_expr: req_loans_in_expr, - visit_fn: req_loans_in_fn, - .. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor {visit_expr: req_loans_in_expr, + visit_fn: req_loans_in_fn, + .. *visit::default_visitor()}); visit::visit_crate(*crate, glcx, v); return glcx.req_maps; } @@ -115,7 +123,7 @@ fn req_loans_in_expr(ex: @ast::expr, } // Special checks for various kinds of expressions: - match ex.node { + match /*bad*/copy ex.node { ast::expr_addr_of(mutbl, base) => { let base_cmt = self.bccx.cat_expr(base); @@ -498,7 +506,7 @@ impl gather_loan_ctxt { discr_cmt: cmt, root_pat: @ast::pat, arm_id: ast::node_id, - alt_id: ast::node_id) { + match_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_binding(pat) => { @@ -506,11 +514,11 @@ impl gather_loan_ctxt { ast::bind_by_value | ast::bind_by_move => { // copying does not borrow anything, so no check // is required - // as for move, check::alt ensures it's from an rvalue. + // as for move, check::_match ensures it's from an rvalue. } ast::bind_by_ref(mutbl) => { // ref x or ref x @ p --- creates a ptr which must - // remain valid for the scope of the alt + // remain valid for the scope of the match // find the region of the resulting pointer (note that // the type of such a pattern will *always* be a @@ -523,7 +531,7 @@ impl gather_loan_ctxt { // of the function of this node in method preserve(): let arm_scope = ty::re_scope(arm_id); if self.bccx.is_subregion_of(scope_r, arm_scope) { - let cmt_discr = self.bccx.cat_discr(cmt, alt_id); + let cmt_discr = self.bccx.cat_discr(cmt, match_id); self.guarantee_valid(cmt_discr, mutbl, scope_r); } else { self.guarantee_valid(cmt, mutbl, scope_r); diff --git a/src/librustc/middle/borrowck/loan.rs b/src/librustc/middle/borrowck/loan.rs index 7dc68fa0b4b13..6539cb0c6c3cc 100644 --- a/src/librustc/middle/borrowck/loan.rs +++ b/src/librustc/middle/borrowck/loan.rs @@ -12,8 +12,13 @@ // Loan(Ex, M, S) = Ls holds if ToAddr(Ex) will remain valid for the entirety // of the scope S, presuming that the returned set of loans `Ls` are honored. + +use middle::ty; + +use core::result::{Result, Ok, Err}; +use syntax::ast; + export public_methods; -use result::{Result, Ok, Err}; impl borrowck_ctxt { fn loan(cmt: cmt, diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 90de32814470e..7994ef314cc67 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -226,13 +226,17 @@ Borrowck results in two maps. #[legacy_exports]; +use middle::liveness; use middle::mem_categorization::*; -use middle::ty::to_str; +use middle::region; +use middle::ty; use util::common::indenter; use util::ppaux::{expr_repr, note_and_explain_region}; use util::ppaux::{ty_to_str, region_to_str, explain_region}; +use core::cmp; use core::dvec::DVec; +use core::io; use core::result::{Result, Ok, Err}; use std::list::{List, Cons, Nil}; use std::list; @@ -333,7 +337,7 @@ type root_map_key = {id: ast::node_id, derefs: uint}; // set of ids of local vars / formal arguments that are modified / moved. // this is used in trans for optimization purposes. -type mutbl_map = std::map::HashMap; +type mutbl_map = HashMap; // Errors that can occur"] enum bckerr_code { @@ -489,8 +493,8 @@ impl borrowck_ctxt { cat_variant(self.tcx, self.method_map, arg, enum_did, cmt) } - fn cat_discr(cmt: cmt, alt_id: ast::node_id) -> cmt { - return @{cat:cat_discr(cmt, alt_id),.. *cmt}; + fn cat_discr(cmt: cmt, match_id: ast::node_id) -> cmt { + return @{cat:cat_discr(cmt, match_id),.. *cmt}; } fn cat_pattern(cmt: cmt, pat: @ast::pat, op: fn(cmt, @ast::pat)) { @@ -514,11 +518,11 @@ impl borrowck_ctxt { self.note_and_explain_bckerr(err); } - fn span_err(s: span, m: ~str) { + fn span_err(s: span, +m: ~str) { self.tcx.sess.span_err(s, m); } - fn span_note(s: span, m: ~str) { + fn span_note(s: span, +m: ~str) { self.tcx.sess.span_note(s, m); } diff --git a/src/librustc/middle/borrowck/preserve.rs b/src/librustc/middle/borrowck/preserve.rs index b1a34bbe2569b..e6d311fd04fc7 100644 --- a/src/librustc/middle/borrowck/preserve.rs +++ b/src/librustc/middle/borrowck/preserve.rs @@ -13,6 +13,11 @@ // the scope S. // + +use middle::ty; + +use syntax::ast; + export public_methods, preserve_condition, pc_ok, pc_if_pure; enum preserve_condition { @@ -190,15 +195,15 @@ priv impl &preserve_ctxt { self.attempt_root(cmt, base, derefs) } } - cat_discr(base, alt_id) => { - // Subtle: in an alt, we must ensure that each binding + cat_discr(base, match_id) => { + // Subtle: in a match, we must ensure that each binding // variable remains valid for the duration of the arm in // which it appears, presuming that this arm is taken. // But it is inconvenient in trans to root something just // for one arm. Therefore, we insert a cat_discr(), // basically a special kind of category that says "if this // value must be dynamically rooted, root it for the scope - // `alt_id`. + // `match_id`. // // As an example, consider this scenario: // @@ -208,7 +213,7 @@ priv impl &preserve_ctxt { // Technically, the value `x` need only be rooted // in the `some` arm. However, we evaluate `x` in trans // before we know what arm will be taken, so we just - // always root it for the duration of the alt. + // always root it for the duration of the match. // // As a second example, consider *this* scenario: // @@ -220,7 +225,7 @@ priv impl &preserve_ctxt { // found only when checking which pattern matches: but // this check is done before entering the arm. Therefore, // even in this case we just choose to keep the value - // rooted for the entire alt. This means the value will be + // rooted for the entire match. This means the value will be // rooted even if the none arm is taken. Oh well. // // At first, I tried to optimize the second case to only @@ -242,12 +247,12 @@ priv impl &preserve_ctxt { // Nonetheless, if you decide to optimize this case in the // future, you need only adjust where the cat_discr() // node appears to draw the line between what will be rooted - // in the *arm* vs the *alt*. + // in the *arm* vs the *match*. - let alt_rooting_ctxt = - preserve_ctxt({scope_region: ty::re_scope(alt_id), + let match_rooting_ctxt = + preserve_ctxt({scope_region: ty::re_scope(match_id), .. **self}); - (&alt_rooting_ctxt).preserve(base) + (&match_rooting_ctxt).preserve(base) } } } diff --git a/src/librustc/middle/capture.rs b/src/librustc/middle/capture.rs index f9a7459c67176..86d9151ae9b50 100644 --- a/src/librustc/middle/capture.rs +++ b/src/librustc/middle/capture.rs @@ -8,10 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::{ast, ast_util}; -use syntax::codemap::span; -use std::map; + +use middle::freevars; +use middle::ty; + +use core::option; +use core::vec; use std::map::HashMap; +use std::map; +use syntax::codemap::span; +use syntax::{ast, ast_util}; export capture_mode; export capture_var; diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 06dd18b3bf3f4..df175a83a31bf 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -8,16 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::*; -use syntax::{visit, ast_util, ast_map}; + use driver::session::Session; +use middle::resolve; +use middle::ty; +use middle::typeck; +use util::ppaux; + +use core::dvec::DVec; +use core::option; use std::map::HashMap; -use dvec::DVec; +use syntax::ast::*; +use syntax::{visit, ast_util, ast_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(@{ + visit::visit_crate(*crate, false, visit::mk_vt(@visit::Visitor { visit_item: |a,b,c| check_item(sess, ast_map, def_map, a, b, c), visit_pat: check_pat, visit_expr: |a,b,c| @@ -88,7 +95,7 @@ fn check_expr(sess: Session, def_map: resolve::DefMap, let ety = ty::expr_ty(tcx, e); if !ty::type_is_numeric(ety) { sess.span_err(e.span, ~"can not cast to `" + - util::ppaux::ty_to_str(tcx, ety) + + ppaux::ty_to_str(tcx, ety) + ~"` in a constant expression"); } } @@ -202,7 +209,7 @@ fn check_item_recursion(sess: Session, ast_map: ast_map::map, idstack: @DVec() }; - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_item: visit_item, visit_expr: visit_expr, .. *visit::default_visitor() diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 5ff186126fb0c..0e260c54fe26b 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::ty; + use syntax::ast::*; use syntax::visit; @@ -16,7 +19,7 @@ type ctx = {in_loop: bool, can_ret: bool}; fn check_crate(tcx: ty::ctxt, crate: @crate) { visit::visit_crate(*crate, {in_loop: false, can_ret: true}, - visit::mk_vt(@{ + visit::mk_vt(@visit::Visitor { visit_item: |i, _cx, v| { visit::visit_item(i, {in_loop: false, can_ret: true}, v); }, diff --git a/src/librustc/middle/check_alt.rs b/src/librustc/middle/check_match.rs similarity index 91% rename from src/librustc/middle/check_alt.rs rename to src/librustc/middle/check_match.rs index ef192a0fda730..aaf4656cae892 100644 --- a/src/librustc/middle/check_alt.rs +++ b/src/librustc/middle/check_match.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use middle::const_eval::{compare_const_vals, lookup_const_by_id}; use middle::const_eval::{eval_const_expr, const_val, const_int, const_bool}; use middle::pat_util::*; @@ -16,22 +17,27 @@ use middle::ty; use middle::typeck::method_map; use util::ppaux::ty_to_str; +use core::cmp; +use core::option; +use core::uint; +use core::vec; use std::map::HashMap; +use std::sort; use syntax::ast::*; use syntax::ast_util::{variant_def_ids, dummy_sp, unguarded_pat, walk_pat}; +use syntax::ast_util; use syntax::codemap::span; use syntax::print::pprust::pat_to_str; use syntax::visit; -use std::sort; -struct AltCheckCtxt { +struct MatchCheckCtxt { tcx: ty::ctxt, method_map: method_map, } fn check_crate(tcx: ty::ctxt, method_map: method_map, crate: @crate) { - let cx = @AltCheckCtxt { tcx: tcx, method_map: method_map }; - visit::visit_crate(*crate, (), visit::mk_vt(@{ + let cx = @MatchCheckCtxt { tcx: tcx, method_map: method_map }; + visit::visit_crate(*crate, (), visit::mk_vt(@visit::Visitor { visit_expr: |a,b,c| check_expr(cx, a, b, c), visit_local: |a,b,c| check_local(cx, a, b, c), visit_fn: |kind, decl, body, sp, id, e, v| @@ -41,7 +47,7 @@ fn check_crate(tcx: ty::ctxt, method_map: method_map, crate: @crate) { tcx.sess.abort_if_errors(); } -fn expr_is_non_moving_lvalue(cx: @AltCheckCtxt, expr: @expr) -> bool { +fn expr_is_non_moving_lvalue(cx: @MatchCheckCtxt, expr: @expr) -> bool { if !ty::expr_is_lval(cx.tcx, cx.method_map, expr) { return false; } @@ -55,7 +61,7 @@ fn expr_is_non_moving_lvalue(cx: @AltCheckCtxt, expr: @expr) -> bool { } } -fn check_expr(cx: @AltCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) { +fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) { visit::visit_expr(ex, s, v); match ex.node { expr_match(scrut, ref arms) => { @@ -68,7 +74,7 @@ fn check_expr(cx: @AltCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) { arm.pats); } - check_arms(cx, (*arms)); + check_arms(cx, (/*bad*/copy *arms)); /* Check for exhaustiveness */ // Check for empty enum, because is_useful only works on inhabited // types. @@ -101,7 +107,7 @@ fn check_expr(cx: @AltCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) { } // Check for unreachable patterns -fn check_arms(cx: @AltCheckCtxt, arms: ~[arm]) { +fn check_arms(cx: @MatchCheckCtxt, arms: ~[arm]) { let mut seen = ~[]; for arms.each |arm| { for arm.pats.each |pat| { @@ -124,7 +130,7 @@ fn raw_pat(p: @pat) -> @pat { } } -fn check_exhaustive(cx: @AltCheckCtxt, sp: span, pats: ~[@pat]) { +fn check_exhaustive(cx: @MatchCheckCtxt, sp: span, pats: ~[@pat]) { assert(pats.is_not_empty()); let ext = match is_useful(cx, vec::map(pats, |p| ~[*p]), ~[wild()]) { not_useful => return, // This is good, wildcard pattern isn't reachable @@ -210,7 +216,7 @@ impl ctor : cmp::Eq { // Note: is_useful doesn't work on empty types, as the paper notes. // So it assumes that v is non-empty. -fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful { +fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: ~[@pat]) -> useful { if m.len() == 0u { return useful_; } if m[0].len() == 0u { return not_useful; } let real_pat = match vec::find(m, |r| r[0].id != 0) { @@ -233,7 +239,7 @@ fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful { val(const_bool(false)), 0u, left_ty) } - ref u => (*u) + ref u => (/*bad*/copy *u) } } ty::ty_enum(eid, _) => { @@ -241,14 +247,14 @@ fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful { match is_useful_specialized(cx, m, v, variant(va.id), va.args.len(), left_ty) { not_useful => (), - ref u => return (*u) + ref u => return (/*bad*/copy *u) } } not_useful } ty::ty_unboxed_vec(*) | ty::ty_evec(*) => { let max_len = do m.foldr(0) |r, max_len| { - match r[0].node { + match /*bad*/copy r[0].node { pat_vec(elems, _) => uint::max(elems.len(), max_len), _ => max_len } @@ -256,7 +262,7 @@ fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful { for uint::range(0, max_len + 1) |n| { match is_useful_specialized(cx, m, v, vec(n), n, left_ty) { not_useful => (), - ref u => return (*u) + ref u => return (/*bad*/copy *u) } } not_useful @@ -270,33 +276,33 @@ fn is_useful(cx: @AltCheckCtxt, m: matrix, v: ~[@pat]) -> useful { Some(ref ctor) => { match is_useful(cx, vec::filter_map(m, |r| default(cx, *r)), vec::tail(v)) { - useful_ => useful(left_ty, (*ctor)), - ref u => (*u) + useful_ => useful(left_ty, (/*bad*/copy *ctor)), + ref u => (/*bad*/copy *u) } } } } Some(ref v0_ctor) => { let arity = ctor_arity(cx, (*v0_ctor), left_ty); - is_useful_specialized(cx, m, v, (*v0_ctor), arity, left_ty) + is_useful_specialized(cx, m, v, /*bad*/copy *v0_ctor, arity, left_ty) } } } -fn is_useful_specialized(cx: @AltCheckCtxt, m: matrix, v: ~[@pat], ctor: ctor, - arity: uint, lty: ty::t) -> useful { +fn is_useful_specialized(cx: @MatchCheckCtxt, m: matrix, +v: ~[@pat], + +ctor: ctor, arity: uint, lty: ty::t) -> useful { let ms = vec::filter_map(m, |r| specialize(cx, *r, ctor, arity, lty)); let could_be_useful = is_useful( cx, ms, specialize(cx, v, ctor, arity, lty).get()); match could_be_useful { useful_ => useful(lty, ctor), - ref u => (*u) + ref u => (/*bad*/copy *u) } } -fn pat_ctor_id(cx: @AltCheckCtxt, p: @pat) -> Option { +fn pat_ctor_id(cx: @MatchCheckCtxt, p: @pat) -> Option { let pat = raw_pat(p); - match pat.node { + match /*bad*/copy pat.node { pat_wild => { None } pat_ident(_, _, _) | pat_enum(_, _) => { match cx.tcx.def_map.find(pat.id) { @@ -331,7 +337,7 @@ fn pat_ctor_id(cx: @AltCheckCtxt, p: @pat) -> Option { } } -fn is_wild(cx: @AltCheckCtxt, p: @pat) -> bool { +fn is_wild(cx: @MatchCheckCtxt, p: @pat) -> bool { let pat = raw_pat(p); match pat.node { pat_wild => { true } @@ -345,7 +351,7 @@ fn is_wild(cx: @AltCheckCtxt, p: @pat) -> bool { } } -fn missing_ctor(cx: @AltCheckCtxt, +fn missing_ctor(cx: @MatchCheckCtxt, m: matrix, left_ty: ty::t) -> Option { @@ -362,7 +368,7 @@ fn missing_ctor(cx: @AltCheckCtxt, for m.each |r| { do option::iter(&pat_ctor_id(cx, r[0])) |id| { if !vec::contains(found, id) { - found.push(*id); + found.push(/*bad*/copy *id); } } } @@ -395,7 +401,7 @@ fn missing_ctor(cx: @AltCheckCtxt, // Find the lengths and tails of all vector patterns. let vec_pat_lens = do m.filter_map |r| { - match r[0].node { + match /*bad*/copy r[0].node { pat_vec(elems, tail) => { Some((elems.len(), tail.is_some())) } @@ -445,8 +451,8 @@ fn missing_ctor(cx: @AltCheckCtxt, } } -fn ctor_arity(cx: @AltCheckCtxt, ctor: ctor, ty: ty::t) -> uint { - match ty::get(ty).sty { +fn ctor_arity(cx: @MatchCheckCtxt, ctor: ctor, ty: ty::t) -> uint { + match /*bad*/copy ty::get(ty).sty { ty::ty_tup(fs) => fs.len(), ty::ty_rec(fs) => fs.len(), ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(*) => 1u, @@ -470,13 +476,13 @@ fn ctor_arity(cx: @AltCheckCtxt, ctor: ctor, ty: ty::t) -> uint { } fn wild() -> @pat { - @{id: 0, node: pat_wild, span: syntax::ast_util::dummy_sp()} + @{id: 0, node: pat_wild, span: ast_util::dummy_sp()} } -fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint, +fn specialize(cx: @MatchCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint, left_ty: ty::t) -> Option<~[@pat]> { let r0 = raw_pat(r[0]); - match r0.node { + match /*bad*/copy r0.node { pat_wild => Some(vec::append(vec::from_elem(arity, wild()), vec::tail(r))), pat_ident(_, _, _) => { @@ -525,7 +531,7 @@ fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint, } } pat_rec(flds, _) => { - let ty_flds = match ty::get(left_ty).sty { + let ty_flds = match /*bad*/copy ty::get(left_ty).sty { ty::ty_rec(flds) => flds, _ => fail ~"bad type for pat_rec" }; @@ -597,8 +603,8 @@ fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint, } pat_range(lo, hi) => { let (c_lo, c_hi) = match ctor_id { - val(ref v) => ((*v), (*v)), - range(ref lo, ref hi) => ((*lo), (*hi)), + val(ref v) => ((/*bad*/copy *v), (/*bad*/copy *v)), + range(ref lo, ref hi) => ((/*bad*/copy *lo), (/*bad*/copy *hi)), single => return Some(vec::tail(r)), _ => fail ~"type error" }; @@ -612,8 +618,9 @@ fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint, match ctor_id { vec(_) => { if elems.len() < arity && tail.is_some() { + // XXX: Bad copy. Some(vec::append( - vec::append(elems, vec::from_elem( + vec::append(copy elems, vec::from_elem( arity - elems.len(), wild() )), vec::tail(r) @@ -630,12 +637,12 @@ fn specialize(cx: @AltCheckCtxt, r: ~[@pat], ctor_id: ctor, arity: uint, } } -fn default(cx: @AltCheckCtxt, r: ~[@pat]) -> Option<~[@pat]> { +fn default(cx: @MatchCheckCtxt, r: ~[@pat]) -> Option<~[@pat]> { if is_wild(cx, r[0]) { Some(vec::tail(r)) } else { None } } -fn check_local(cx: @AltCheckCtxt, loc: @local, &&s: (), v: visit::vt<()>) { +fn check_local(cx: @MatchCheckCtxt, loc: @local, &&s: (), v: visit::vt<()>) { visit::visit_local(loc, s, v); if is_refutable(cx, loc.node.pat) { cx.tcx.sess.span_err(loc.node.pat.span, @@ -650,7 +657,7 @@ fn check_local(cx: @AltCheckCtxt, loc: @local, &&s: (), v: visit::vt<()>) { check_legality_of_move_bindings(cx, is_lvalue, false, [ loc.node.pat ]); } -fn check_fn(cx: @AltCheckCtxt, +fn check_fn(cx: @MatchCheckCtxt, kind: visit::fn_kind, decl: fn_decl, body: blk, @@ -667,7 +674,7 @@ fn check_fn(cx: @AltCheckCtxt, } } -fn is_refutable(cx: @AltCheckCtxt, pat: &pat) -> bool { +fn is_refutable(cx: @MatchCheckCtxt, pat: &pat) -> bool { match cx.tcx.def_map.find(pat.id) { Some(def_variant(enum_id, _)) => { if vec::len(*ty::enum_variants(cx.tcx, enum_id)) != 1u { @@ -678,7 +685,7 @@ fn is_refutable(cx: @AltCheckCtxt, pat: &pat) -> bool { _ => () } - match pat.node { + match /*bad*/copy pat.node { pat_box(sub) | pat_uniq(sub) | pat_region(sub) | pat_ident(_, _, Some(sub)) => { is_refutable(cx, sub) @@ -705,7 +712,7 @@ fn is_refutable(cx: @AltCheckCtxt, pat: &pat) -> bool { // Legality of move bindings checking -fn check_legality_of_move_bindings(cx: @AltCheckCtxt, +fn check_legality_of_move_bindings(cx: @MatchCheckCtxt, is_lvalue: bool, has_guard: bool, pats: &[@pat]) { @@ -786,7 +793,7 @@ fn check_legality_of_move_bindings(cx: @AltCheckCtxt, // Now check to ensure that any move binding is not behind an @ or &. // This is always illegal. - let vt = visit::mk_vt(@{ + let vt = visit::mk_vt(@visit::Visitor { visit_pat: |pat, behind_bad_pointer, v| { let error_out = || { cx.tcx.sess.span_err(pat.span, ~"by-move pattern \ diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index a51885b1fc7eb..3781239ad22a9 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -8,6 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::resolve; +use middle::ty; +use middle; + +use core::cmp; +use core::float; +use core::vec; use syntax::{ast, ast_map, ast_util, visit}; use syntax::ast::*; @@ -38,7 +46,7 @@ use syntax::ast::*; // & and * pointers // copies of general constants // -// (in theory, probably not at first: if/alt on integer-const +// (in theory, probably not at first: if/match on integer-const // conditions / descriminants) // // - Non-constants: everything else. @@ -72,7 +80,7 @@ fn classify(e: @expr, Some(x) => x, None => { let cn = - match e.node { + match /*bad*/copy e.node { ast::expr_lit(lit) => { match lit.node { ast::lit_str(*) | @@ -198,7 +206,7 @@ fn lookup_constness(tcx: ty::ctxt, e: @expr) -> constness { fn process_crate(crate: @ast::crate, def_map: resolve::DefMap, tcx: ty::ctxt) { - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_expr_post: |e| { classify(e, def_map, tcx); }, .. *visit::default_simple_visitor() }); @@ -234,8 +242,8 @@ impl const_val : cmp::Eq { fn eval_const_expr(tcx: middle::ty::ctxt, e: @expr) -> const_val { match eval_const_expr_partial(tcx, e) { - Ok(ref r) => (*r), - Err(ref s) => fail (*s) + Ok(ref r) => (/*bad*/copy *r), + Err(ref s) => fail (/*bad*/copy *s) } } @@ -251,7 +259,7 @@ fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) Ok(const_uint(i)) => Ok(const_uint(-i)), Ok(const_str(_)) => Err(~"Negate on string"), Ok(const_bool(_)) => Err(~"Negate on boolean"), - ref err => (*err) + ref err => (/*bad*/copy *err) } } expr_unary(not, inner) => { @@ -398,7 +406,7 @@ fn eval_const_expr_partial(tcx: middle::ty::ctxt, e: @expr) fn lit_to_const(lit: @lit) -> const_val { match lit.node { - lit_str(s) => const_str(*s), + lit_str(s) => const_str(/*bad*/copy *s), lit_int(n, _) => const_int(n), lit_uint(n, _) => const_uint(n), lit_int_unsuffixed(n) => const_int(n), diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 38ec7dd5eb071..3c1f261c1f8af 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -8,14 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // A pass that annotates for each loops and functions with the free // variables that they contain. -use syntax::print::pprust::path_to_str; +use middle::resolve; +use middle::ty; + +use core::int; +use core::option::*; +use core::vec; use std::map::*; -use option::*; -use syntax::{ast, ast_util, visit}; use syntax::codemap::span; +use syntax::print::pprust::path_to_str; +use syntax::{ast, ast_util, visit}; export annotate_freevars; export freevar_map; @@ -84,10 +90,11 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::blk) } }; - let v = visit::mk_vt(@{visit_item: ignore_item, visit_expr: walk_expr, - .. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor {visit_item: ignore_item, + visit_expr: walk_expr, + .. *visit::default_visitor()}); (v.visit_block)(blk, 1, v); - return @*refs; + return @/*bad*/copy *refs; } // Build a map from every function and for-each body to a set of the @@ -106,8 +113,9 @@ fn annotate_freevars(def_map: resolve::DefMap, crate: @ast::crate) -> }; let visitor = - visit::mk_simple_visitor(@{visit_fn: walk_fn, - .. *visit::default_simple_visitor()}); + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_fn: walk_fn, + .. *visit::default_simple_visitor()}); visit::visit_crate(*crate, (), visitor); return freevars; diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index e35377c5cdd93..90b067d2d588b 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -8,12 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use middle::freevars::freevar_entry; +use middle::freevars; use middle::lint::{non_implicitly_copyable_typarams, implicit_copies}; +use middle::liveness; +use middle::pat_util; use middle::ty::{CopyValue, MoveValue, ReadValue}; use middle::ty::{Kind, kind_copyable, kind_noncopyable, kind_const}; +use middle::ty; +use middle::typeck; +use middle; use util::ppaux::{ty_to_str, tys_to_str}; +use core::option; +use core::str; +use core::vec; use std::map::HashMap; use syntax::ast::*; use syntax::codemap::span; @@ -71,7 +81,7 @@ fn kind_to_str(k: Kind) -> ~str { str::connect(kinds, ~" ") } -type rval_map = std::map::HashMap; +type rval_map = HashMap; type ctx = {tcx: ty::ctxt, method_map: typeck::method_map, @@ -86,7 +96,7 @@ fn check_crate(tcx: ty::ctxt, method_map: method_map, last_use_map: last_use_map, current_item: -1}; - let visit = visit::mk_vt(@{ + let visit = visit::mk_vt(@visit::Visitor { visit_arm: check_arm, visit_expr: check_expr, visit_stmt: check_stmt, @@ -287,7 +297,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { } } - match e.node { + match /*bad*/copy e.node { expr_assign(_, ex) | expr_unary(box(_), ex) | expr_unary(uniq(_), ex) | expr_ret(Some(ex)) => { @@ -320,7 +330,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { Some(ex) => { // All noncopyable fields must be overridden let t = ty::expr_ty(cx.tcx, ex); - let ty_fields = match ty::get(t).sty { + let ty_fields = match /*bad*/copy ty::get(t).sty { ty::ty_rec(f) => f, ty::ty_struct(did, ref substs) => ty::struct_fields(cx.tcx, did, &(*substs)), @@ -398,7 +408,7 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt) { fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt) { match stmt.node { - stmt_decl(@{node: decl_local(locals), _}, _) => { + stmt_decl(@{node: decl_local(ref locals), _}, _) => { for locals.each |local| { match local.node.init { Some(expr) => @@ -605,7 +615,7 @@ fn check_cast_for_escaping_regions( // worries. let target_ty = ty::expr_ty(cx.tcx, target); let target_substs = match ty::get(target_ty).sty { - ty::ty_trait(_, ref substs, _) => {(*substs)} + ty::ty_trait(_, ref substs, _) => {(/*bad*/copy *substs)} _ => { return; /* not a cast to a trait */ } }; diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 1f65ee8ae8324..b57dbffc2d360 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // Detecting language items. // // Language items are items that represent concepts intrinsic to the language @@ -20,116 +21,247 @@ // * Functions called by the compiler itself. use driver::session::Session; -use metadata::csearch::{each_path, get_item_attrs}; +use metadata::csearch::{each_lang_item, get_item_attrs}; use metadata::cstore::{iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use syntax::ast::{crate, def_fn, def_id, def_ty, lit_str, meta_item}; use syntax::ast::{meta_list, meta_name_value, meta_word}; use syntax::ast_util::{local_def}; -use syntax::visit::{default_simple_visitor, mk_simple_visitor}; +use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor}; use syntax::visit::{visit_crate, visit_item}; +use core::ptr; use std::map::HashMap; use str_eq = str::eq; +pub enum LangItem { + ConstTraitLangItem, // 0 + CopyTraitLangItem, // 1 + OwnedTraitLangItem, // 2 + DurableTraitLangItem, // 3 + + DropTraitLangItem, // 4 + + AddTraitLangItem, // 5 + SubTraitLangItem, // 6 + MulTraitLangItem, // 7 + DivTraitLangItem, // 8 + ModuloTraitLangItem, // 9 + NegTraitLangItem, // 10 + BitXorTraitLangItem, // 11 + BitAndTraitLangItem, // 12 + BitOrTraitLangItem, // 13 + ShlTraitLangItem, // 14 + ShrTraitLangItem, // 15 + IndexTraitLangItem, // 16 + + EqTraitLangItem, // 17 + OrdTraitLangItem, // 18 + + StrEqFnLangItem, // 19 + UniqStrEqFnLangItem, // 20 + AnnihilateFnLangItem, // 21 + LogTypeFnLangItem, // 22 + FailFnLangItem, // 23 + FailBoundsCheckFnLangItem, // 24 + ExchangeMallocFnLangItem, // 25 + ExchangeFreeFnLangItem, // 26 + MallocFnLangItem, // 27 + FreeFnLangItem, // 28 +} + struct LanguageItems { - mut const_trait: Option, - mut copy_trait: Option, - mut owned_trait: Option, - mut durable_trait: Option, - - mut drop_trait: Option, - - mut add_trait: Option, - mut sub_trait: Option, - mut mul_trait: Option, - mut div_trait: Option, - mut modulo_trait: Option, - mut neg_trait: Option, - mut bitxor_trait: Option, - mut bitand_trait: Option, - mut bitor_trait: Option, - mut shl_trait: Option, - mut shr_trait: Option, - mut index_trait: Option, - - mut eq_trait: Option, - mut ord_trait: Option, - - mut str_eq_fn: Option, - mut uniq_str_eq_fn: Option, - mut annihilate_fn: Option, - mut log_type_fn: Option + items: [ Option * 29 ] } -mod language_items { - #[legacy_exports]; - fn make() -> LanguageItems { +impl LanguageItems { + static pub fn new() -> LanguageItems { LanguageItems { - const_trait: None, - copy_trait: None, - owned_trait: None, - durable_trait: None, - - drop_trait: None, - - add_trait: None, - sub_trait: None, - mul_trait: None, - div_trait: None, - modulo_trait: None, - neg_trait: None, - bitxor_trait: None, - bitand_trait: None, - bitor_trait: None, - shl_trait: None, - shr_trait: None, - index_trait: None, - - eq_trait: None, - ord_trait: None, - - str_eq_fn: None, - uniq_str_eq_fn: None, - annihilate_fn: None, - log_type_fn: None + items: [ None, ..29 ] } } -} -fn LanguageItemCollector(crate: @crate, session: Session, - items: &r/LanguageItems) - -> LanguageItemCollector/&r { + fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) { + for self.items.eachi |i, &item| { + if !f(item.get(), i) { + break; + } + } + } + + static pub fn item_name(index: uint) -> &static/str { + match index { + 0 => "const", + 1 => "copy", + 2 => "owned", + 3 => "durable", + + 4 => "drop", + + 5 => "add", + 6 => "sub", + 7 => "mul", + 8 => "div", + 9 => "modulo", + 10 => "neg", + 11 => "bitxor", + 12 => "bitand", + 13 => "bitor", + 14 => "shl", + 15 => "shr", + 16 => "index", + 17 => "eq", + 18 => "ord", + + 19 => "str_eq", + 20 => "uniq_str_eq", + 21 => "annihilate", + 22 => "log_type", + 23 => "fail_", + 24 => "fail_bounds_check", + 25 => "exchange_malloc", + 26 => "exchange_free", + 27 => "malloc", + 28 => "free", + + _ => "???" + } + } + + // XXX: Method macros sure would be nice here. + + pub fn const_trait(&const self) -> def_id { + self.items[ConstTraitLangItem as uint].get() + } + pub fn copy_trait(&const self) -> def_id { + self.items[CopyTraitLangItem as uint].get() + } + pub fn owned_trait(&const self) -> def_id { + self.items[OwnedTraitLangItem as uint].get() + } + pub fn durable_trait(&const self) -> def_id { + self.items[DurableTraitLangItem as uint].get() + } + + pub fn drop_trait(&const self) -> def_id { + self.items[DropTraitLangItem as uint].get() + } + + pub fn add_trait(&const self) -> def_id { + self.items[AddTraitLangItem as uint].get() + } + pub fn sub_trait(&const self) -> def_id { + self.items[SubTraitLangItem as uint].get() + } + pub fn mul_trait(&const self) -> def_id { + self.items[MulTraitLangItem as uint].get() + } + pub fn div_trait(&const self) -> def_id { + self.items[DivTraitLangItem as uint].get() + } + pub fn modulo_trait(&const self) -> def_id { + self.items[ModuloTraitLangItem as uint].get() + } + pub fn neg_trait(&const self) -> def_id { + self.items[NegTraitLangItem as uint].get() + } + pub fn bitxor_trait(&const self) -> def_id { + self.items[BitXorTraitLangItem as uint].get() + } + pub fn bitand_trait(&const self) -> def_id { + self.items[BitAndTraitLangItem as uint].get() + } + pub fn bitor_trait(&const self) -> def_id { + self.items[BitOrTraitLangItem as uint].get() + } + pub fn shl_trait(&const self) -> def_id { + self.items[ShlTraitLangItem as uint].get() + } + pub fn shr_trait(&const self) -> def_id { + self.items[ShrTraitLangItem as uint].get() + } + pub fn index_trait(&const self) -> def_id { + self.items[IndexTraitLangItem as uint].get() + } + pub fn eq_trait(&const self) -> def_id { + self.items[EqTraitLangItem as uint].get() + } + pub fn ord_trait(&const self) -> def_id { + self.items[OrdTraitLangItem as uint].get() + } + + pub fn str_eq_fn(&const self) -> def_id { + self.items[StrEqFnLangItem as uint].get() + } + pub fn uniq_str_eq_fn(&const self) -> def_id { + self.items[UniqStrEqFnLangItem as uint].get() + } + pub fn annihilate_fn(&const self) -> def_id { + self.items[AnnihilateFnLangItem as uint].get() + } + pub fn log_type_fn(&const self) -> def_id { + self.items[LogTypeFnLangItem as uint].get() + } + pub fn fail_fn(&const self) -> def_id { + self.items[FailFnLangItem as uint].get() + } + pub fn fail_bounds_check_fn(&const self) -> def_id { + self.items[FailBoundsCheckFnLangItem as uint].get() + } + pub fn exchange_malloc_fn(&const self) -> def_id { + self.items[ExchangeMallocFnLangItem as uint].get() + } + pub fn exchange_free_fn(&const self) -> def_id { + self.items[ExchangeFreeFnLangItem as uint].get() + } + pub fn malloc_fn(&const self) -> def_id { + self.items[MallocFnLangItem as uint].get() + } + pub fn free_fn(&const self) -> def_id { + self.items[FreeFnLangItem as uint].get() + } +} + +fn LanguageItemCollector(crate: @crate, + session: Session, + items: &r/mut LanguageItems) + -> LanguageItemCollector/&r { let item_refs = HashMap(); - item_refs.insert(~"const", &mut items.const_trait); - item_refs.insert(~"copy", &mut items.copy_trait); - item_refs.insert(~"owned", &mut items.owned_trait); - item_refs.insert(~"durable", &mut items.durable_trait); - - item_refs.insert(~"drop", &mut items.drop_trait); - - item_refs.insert(~"add", &mut items.add_trait); - item_refs.insert(~"sub", &mut items.sub_trait); - item_refs.insert(~"mul", &mut items.mul_trait); - item_refs.insert(~"div", &mut items.div_trait); - item_refs.insert(~"modulo", &mut items.modulo_trait); - item_refs.insert(~"neg", &mut items.neg_trait); - item_refs.insert(~"bitxor", &mut items.bitxor_trait); - item_refs.insert(~"bitand", &mut items.bitand_trait); - item_refs.insert(~"bitor", &mut items.bitor_trait); - item_refs.insert(~"shl", &mut items.shl_trait); - item_refs.insert(~"shr", &mut items.shr_trait); - item_refs.insert(~"index", &mut items.index_trait); - - item_refs.insert(~"eq", &mut items.eq_trait); - item_refs.insert(~"ord", &mut items.ord_trait); - - item_refs.insert(~"str_eq", &mut items.str_eq_fn); - item_refs.insert(~"uniq_str_eq", &mut items.uniq_str_eq_fn); - item_refs.insert(~"annihilate", &mut items.annihilate_fn); - item_refs.insert(~"log_type", &mut items.log_type_fn); + item_refs.insert(~"const", ConstTraitLangItem as uint); + item_refs.insert(~"copy", CopyTraitLangItem as uint); + item_refs.insert(~"owned", OwnedTraitLangItem as uint); + item_refs.insert(~"durable", DurableTraitLangItem as uint); + + item_refs.insert(~"drop", DropTraitLangItem as uint); + + item_refs.insert(~"add", AddTraitLangItem as uint); + item_refs.insert(~"sub", SubTraitLangItem as uint); + item_refs.insert(~"mul", MulTraitLangItem as uint); + item_refs.insert(~"div", DivTraitLangItem as uint); + item_refs.insert(~"modulo", ModuloTraitLangItem as uint); + item_refs.insert(~"neg", NegTraitLangItem as uint); + item_refs.insert(~"bitxor", BitXorTraitLangItem as uint); + item_refs.insert(~"bitand", BitAndTraitLangItem as uint); + item_refs.insert(~"bitor", BitOrTraitLangItem as uint); + item_refs.insert(~"shl", ShlTraitLangItem as uint); + item_refs.insert(~"shr", ShrTraitLangItem as uint); + item_refs.insert(~"index", IndexTraitLangItem as uint); + + item_refs.insert(~"eq", EqTraitLangItem as uint); + item_refs.insert(~"ord", OrdTraitLangItem as uint); + + item_refs.insert(~"str_eq", StrEqFnLangItem as uint); + item_refs.insert(~"uniq_str_eq", UniqStrEqFnLangItem as uint); + item_refs.insert(~"annihilate", AnnihilateFnLangItem as uint); + item_refs.insert(~"log_type", LogTypeFnLangItem as uint); + item_refs.insert(~"fail_", FailFnLangItem as uint); + item_refs.insert(~"fail_bounds_check", FailBoundsCheckFnLangItem as uint); + item_refs.insert(~"exchange_malloc", ExchangeMallocFnLangItem as uint); + item_refs.insert(~"exchange_free", ExchangeFreeFnLangItem as uint); + item_refs.insert(~"malloc", MallocFnLangItem as uint); + item_refs.insert(~"free", FreeFnLangItem as uint); LanguageItemCollector { crate: crate, @@ -140,16 +272,15 @@ fn LanguageItemCollector(crate: @crate, session: Session, } struct LanguageItemCollector { - items: &LanguageItems, + items: &mut LanguageItems, crate: @crate, session: Session, - item_refs: HashMap<~str,&mut Option>, + item_refs: HashMap<~str,uint>, } impl LanguageItemCollector { - fn match_and_collect_meta_item(item_def_id: def_id, meta_item: meta_item) { match meta_item.node { @@ -157,8 +288,8 @@ impl LanguageItemCollector { match literal.node { lit_str(value) => { self.match_and_collect_item(item_def_id, - (*key), - *value); + (/*bad*/copy *key), + /*bad*/copy *value); } _ => {} // Skip. } @@ -167,6 +298,22 @@ impl LanguageItemCollector { } } + fn collect_item(item_index: uint, item_def_id: def_id) { + // Check for duplicates. + match self.items.items[item_index] { + Some(original_def_id) if original_def_id != item_def_id => { + self.session.err(fmt!("duplicate entry for `%s`", + LanguageItems::item_name(item_index))); + } + Some(_) | None => { + // OK. + } + } + + // Matched. + self.items.items[item_index] = Some(item_def_id); + } + fn match_and_collect_item(item_def_id: def_id, key: ~str, value: ~str) { if key != ~"lang" { return; // Didn't match. @@ -176,29 +323,15 @@ impl LanguageItemCollector { None => { // Didn't match. } - Some(item_ref) => { - // Check for duplicates. - match copy *item_ref { - Some(original_def_id) - if original_def_id != item_def_id => { - - self.session.err(fmt!("duplicate entry for `%s`", - value)); - } - Some(_) | None => { - // OK. - } - } - - // Matched. - *item_ref = Some(item_def_id); + Some(item_index) => { + self.collect_item(item_index, item_def_id) } } } fn collect_local_language_items() { let this = unsafe { ptr::addr_of(&self) }; - visit_crate(*self.crate, (), mk_simple_visitor(@{ + visit_crate(*self.crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { for item.attrs.each |attribute| { unsafe { @@ -216,30 +349,17 @@ impl LanguageItemCollector { fn collect_external_language_items() { let crate_store = self.session.cstore; do iter_crate_data(crate_store) |crate_number, _crate_metadata| { - for each_path(crate_store, crate_number) |path_entry| { - let def_id; - match path_entry.def_like { - dl_def(def_ty(did)) | dl_def(def_fn(did, _)) => { - def_id = did; - } - dl_def(_) | dl_impl(_) | dl_field => { - // Skip this. - loop; - } - } - - do get_item_attrs(crate_store, def_id) |meta_items| { - for meta_items.each |meta_item| { - self.match_and_collect_meta_item(def_id, **meta_item); - } - } + for each_lang_item(crate_store, crate_number) + |node_id, item_index| { + let def_id = { crate: crate_number, node: node_id }; + self.collect_item(item_index, def_id); } } } fn check_completeness() { for self.item_refs.each |key, item_ref| { - match *item_ref { + match self.items.items[item_ref] { None => { self.session.err(fmt!("no item found for `%s`", key)); } @@ -258,8 +378,8 @@ impl LanguageItemCollector { } fn collect_language_items(crate: @crate, session: Session) -> LanguageItems { - let items = language_items::make(); - let collector = LanguageItemCollector(crate, session, &items); + let mut items = LanguageItems::new(); + let collector = LanguageItemCollector(crate, session, &mut items); collector.collect(); copy items } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index f2ab93478c4b7..fa31201ac49eb 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -8,19 +8,39 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use driver::session; + use driver::session::Session; +use driver::session; +use middle::pat_util::{pat_bindings}; use middle::ty; -use syntax::{ast, ast_util, visit}; -use syntax::attr; -use syntax::codemap::span; -use std::map::{Map,HashMap}; -use std::smallintmap::{Map,SmallIntMap}; -use io::WriterUtil; use util::ppaux::{ty_to_str}; -use middle::pat_util::{pat_bindings}; + +use core::char; +use core::cmp; +use core::either; +use core::i8; +use core::i16; +use core::i32; +use core::i64; +use core::int; +use core::io::WriterUtil; +use core::str; +use core::u8; +use core::u16; +use core::u32; +use core::u64; +use core::uint; +use core::vec; +use std::map::{Map, HashMap}; +use std::map; +use std::smallintmap::{Map, SmallIntMap}; +use std::smallintmap; use syntax::ast_util::{path_to_ident}; +use syntax::attr; +use syntax::codemap::span; use syntax::print::pprust::{expr_to_str, mode_to_str, pat_to_str}; +use syntax::{ast, ast_util, visit}; + export lint, ctypes, unused_imports, while_true, path_statement, old_vecs; export unrecognized_lint, non_implicitly_copyable_typarams; export vecs_implicitly_copyable, implicit_copies, legacy_modes; @@ -86,12 +106,12 @@ impl lint : cmp::Eq { pure fn ne(&self, other: &lint) -> bool { !(*self).eq(other) } } -fn level_to_str(lv: level) -> ~str { +fn level_to_str(lv: level) -> &static/str { match lv { - allow => ~"allow", - warn => ~"warn", - deny => ~"deny", - forbid => ~"forbid" + allow => "allow", + warn => "warn", + deny => "deny", + forbid => "forbid" } } @@ -107,7 +127,7 @@ impl level : cmp::Eq { } type lint_spec = @{lint: lint, - desc: ~str, + desc: &static/str, default: level}; type lint_dict = HashMap<~str,lint_spec>; @@ -120,113 +140,113 @@ fn get_lint_dict() -> lint_dict { let v = ~[ (~"ctypes", @{lint: ctypes, - desc: ~"proper use of core::libc types in foreign modules", + desc: "proper use of core::libc types in foreign modules", default: warn}), (~"unused_imports", @{lint: unused_imports, - desc: ~"imports that are never used", + desc: "imports that are never used", default: allow}), (~"while_true", @{lint: while_true, - desc: ~"suggest using loop { } instead of while(true) { }", + desc: "suggest using loop { } instead of while(true) { }", default: warn}), (~"path_statement", @{lint: path_statement, - desc: ~"path statements with no effect", + desc: "path statements with no effect", default: warn}), (~"unrecognized_lint", @{lint: unrecognized_lint, - desc: ~"unrecognized lint attribute", + desc: "unrecognized lint attribute", default: warn}), (~"non_implicitly_copyable_typarams", @{lint: non_implicitly_copyable_typarams, - desc: ~"passing non implicitly copyable types as copy type params", + desc: "passing non implicitly copyable types as copy type params", default: warn}), (~"vecs_implicitly_copyable", @{lint: vecs_implicitly_copyable, - desc: ~"make vecs and strs not implicitly copyable \ + desc: "make vecs and strs not implicitly copyable \ (only checked at top level)", default: warn}), (~"implicit_copies", @{lint: implicit_copies, - desc: ~"implicit copies of non implicitly copyable data", + desc: "implicit copies of non implicitly copyable data", default: warn}), (~"deprecated_mode", @{lint: deprecated_mode, - desc: ~"warn about deprecated uses of modes", + desc: "warn about deprecated uses of modes", default: warn}), (~"deprecated_pattern", @{lint: deprecated_pattern, - desc: ~"warn about deprecated uses of pattern bindings", + desc: "warn about deprecated uses of pattern bindings", default: allow}), (~"non_camel_case_types", @{lint: non_camel_case_types, - desc: ~"types, variants and traits should have camel case names", + desc: "types, variants and traits should have camel case names", default: allow}), (~"managed_heap_memory", @{lint: managed_heap_memory, - desc: ~"use of managed (@ type) heap memory", + desc: "use of managed (@ type) heap memory", default: allow}), (~"owned_heap_memory", @{lint: owned_heap_memory, - desc: ~"use of owned (~ type) heap memory", + desc: "use of owned (~ type) heap memory", default: allow}), (~"heap_memory", @{lint: heap_memory, - desc: ~"use of any (~ type or @ type) heap memory", + desc: "use of any (~ type or @ type) heap memory", default: allow}), (~"structural_records", @{lint: structural_records, - desc: ~"use of any structural records", + desc: "use of any structural records", default: allow}), (~"legacy modes", @{lint: legacy_modes, - desc: ~"allow legacy modes", + desc: "allow legacy modes", default: forbid}), (~"type_limits", @{lint: type_limits, - desc: ~"comparisons made useless by limits of the types involved", + desc: "comparisons made useless by limits of the types involved", default: warn}), (~"default_methods", @{lint: default_methods, - desc: ~"allow default methods", + desc: "allow default methods", default: deny}), (~"deprecated_self", @{lint: deprecated_self, - desc: ~"warn about deprecated uses of `self`", + desc: "warn about deprecated uses of `self`", default: allow}), /* FIXME(#3266)--make liveness warnings lintable (~"unused_variable", @{lint: unused_variable, - desc: ~"detect variables which are not used in any way", + desc: "detect variables which are not used in any way", default: warn}), (~"dead_assignment", @{lint: dead_assignment, - desc: ~"detect assignments that will never be read", + desc: "detect assignments that will never be read", default: warn}), */ ]; - std::map::hash_from_vec(v) + map::hash_from_vec(v) } // This is a highly not-optimal set of data structure decisions. @@ -242,7 +262,7 @@ type lint_settings = { }; fn mk_lint_settings() -> lint_settings { - {default_settings: std::smallintmap::mk(), + {default_settings: smallintmap::mk(), settings_map: HashMap()} } @@ -266,7 +286,7 @@ fn get_lint_settings_level(settings: lint_settings, // This is kind of unfortunate. It should be somewhere else, or we should use // a persistent data structure... fn clone_lint_modes(modes: lint_modes) -> lint_modes { - std::smallintmap::SmallIntMap_(@{v: copy modes.v}) + smallintmap::SmallIntMap_(@{v: copy modes.v}) } type ctxt_ = {dict: lint_dict, @@ -291,7 +311,7 @@ impl ctxt { } } - fn span_lint(level: level, span: span, msg: ~str) { + fn span_lint(level: level, span: span, +msg: ~str) { self.sess.span_lint_level(level, span, msg); } @@ -308,15 +328,17 @@ impl ctxt { for [allow, warn, deny, forbid].each |level| { let level_name = level_to_str(*level); let metas = - attr::attr_metas(attr::find_attrs_by_name(attrs, + attr::attr_metas(attr::find_attrs_by_name(/*bad*/copy attrs, level_name)); for metas.each |meta| { - match meta.node { + match /*bad*/copy meta.node { ast::meta_list(_, metas) => { for metas.each |meta| { match meta.node { ast::meta_word(ref lintname) => { - triples.push((*meta, *level, *lintname)); + triples.push((*meta, + *level, + /*bad*/copy *lintname)); } _ => { self.sess.span_err( @@ -335,7 +357,7 @@ impl ctxt { } for triples.each |pair| { - let (meta, level, lintname) = *pair; + let (meta, level, lintname) = /*bad*/copy *pair; match self.dict.find(lintname) { None => { self.span_lint( @@ -375,7 +397,7 @@ impl ctxt { fn build_settings_item(i: @ast::item, &&cx: ctxt, v: visit::vt) { - do cx.with_lint_attrs(i.attrs) |cx| { + do cx.with_lint_attrs(/*bad*/copy i.attrs) |cx| { if !cx.is_default { cx.sess.lint_settings.settings_map.insert(i.id, cx.curr); } @@ -386,7 +408,7 @@ fn build_settings_item(i: @ast::item, &&cx: ctxt, v: visit::vt) { fn build_settings_crate(sess: session::Session, crate: @ast::crate) { let cx = ctxt_({dict: get_lint_dict(), - curr: std::smallintmap::mk(), + curr: smallintmap::mk(), is_default: true, sess: sess}); @@ -399,7 +421,7 @@ fn build_settings_crate(sess: session::Session, crate: @ast::crate) { cx.set_level(lint, level); } - do cx.with_lint_attrs(crate.node.attrs) |cx| { + do cx.with_lint_attrs(/*bad*/copy crate.node.attrs) |cx| { // Copy out the default settings for cx.curr.each |k, v| { sess.lint_settings.default_settings.insert(k, v); @@ -407,7 +429,7 @@ fn build_settings_crate(sess: session::Session, crate: @ast::crate) { let cx = ctxt_({is_default: true,.. *cx}); - let visit = visit::mk_vt(@{ + let visit = visit::mk_vt(@visit::Visitor { visit_item: build_settings_item, .. *visit::default_visitor() }); @@ -435,29 +457,31 @@ fn check_item(i: @ast::item, cx: ty::ctxt) { // not traverse into subitems, since that is handled by the outer // lint visitor. fn item_stopping_visitor(v: visit::vt) -> visit::vt { - visit::mk_vt(@{visit_item: |_i, _e, _v| { },.. **v}) + visit::mk_vt(@visit::Visitor {visit_item: |_i, _e, _v| { },.. **v}) } fn check_item_while_true(cx: ty::ctxt, it: @ast::item) { - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - match e.node { - ast::expr_while(cond, _) => { - match cond.node { - ast::expr_lit(@{node: ast::lit_bool(true),_}) => { - cx.sess.span_lint( - while_true, e.id, it.id, - e.span, - ~"denote infinite loops with loop { ... }"); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: |e: @ast::expr| { + match e.node { + ast::expr_while(cond, _) => { + match cond.node { + ast::expr_lit(@{node: ast::lit_bool(true),_}) => { + cx.sess.span_lint( + while_true, e.id, it.id, + e.span, + ~"denote infinite loops \ + with loop { ... }"); + } + _ => () + } } _ => () } - } - _ => () - } - }, - .. *visit::default_simple_visitor() - })); + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -519,7 +543,7 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) { } else { binop }; - match ty::get(ty::expr_ty(cx, @*expr)).sty { + match ty::get(ty::expr_ty(cx, @/*bad*/copy *expr)).sty { ty::ty_int(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i64 = match lit.node { @@ -558,27 +582,30 @@ fn check_item_type_limits(cx: ty::ctxt, it: @ast::item) { } } - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - match e.node { - ast::expr_binary(ref binop, @ref l, @ref r) => { - if is_comparison(*binop) - && !check_limits(cx, *binop, l, r) { - cx.sess.span_lint( - type_limits, e.id, it.id, e.span, - ~"comparison is useless due to type limits"); - } + let visit_expr: @fn(@ast::expr) = |e| { + match e.node { + ast::expr_binary(ref binop, @ref l, @ref r) => { + if is_comparison(*binop) + && !check_limits(cx, *binop, l, r) { + cx.sess.span_lint( + type_limits, e.id, it.id, e.span, + ~"comparison is useless due to type limits"); } - _ => () } - }, - .. *visit::default_simple_visitor() - })); + _ => () + } + }; + + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: visit_expr, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } fn check_item_default_methods(cx: ty::ctxt, item: @ast::item) { - match item.node { + match /*bad*/copy item.node { ast::item_trait(_, _, methods) => { for methods.each |method| { match *method { @@ -611,10 +638,10 @@ fn check_item_deprecated_self(cx: ty::ctxt, item: @ast::item) { parameter or mark the method as static"); } - match item.node { + match /*bad*/copy item.node { ast::item_trait(_, _, methods) => { for methods.each |method| { - match *method { + match /*bad*/copy *method { ast::required(ty_method) => { maybe_warn(cx, item, ty_method.self_ty); } @@ -634,19 +661,20 @@ fn check_item_deprecated_self(cx: ty::ctxt, item: @ast::item) { } fn check_item_structural_records(cx: ty::ctxt, it: @ast::item) { - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - match e.node { - ast::expr_rec(*) => - cx.sess.span_lint( - structural_records, e.id, it.id, - e.span, - ~"structural records are deprecated"), - _ => () - } - }, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: |e: @ast::expr| { + match e.node { + ast::expr_rec(*) => + cx.sess.span_lint( + structural_records, e.id, it.id, + e.span, + ~"structural records are deprecated"), + _ => () + } + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -682,10 +710,11 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) { } match it.node { - ast::item_foreign_mod(nmod) if attr::foreign_abi(it.attrs) != - either::Right(ast::foreign_abi_rust_intrinsic) => { + ast::item_foreign_mod(ref nmod) + if attr::foreign_abi(it.attrs) != + either::Right(ast::foreign_abi_rust_intrinsic) => { for nmod.items.each |ni| { - match ni.node { + match /*bad*/copy ni.node { ast::foreign_item_fn(decl, _, _) => { check_foreign_fn(cx, it.id, decl); } @@ -752,34 +781,36 @@ fn check_item_heap(cx: ty::ctxt, it: @ast::item) { _ => () } - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_expr: fn@(e: @ast::expr) { - let ty = ty::expr_ty(cx, e); - check_type(cx, e.id, it.id, e.span, ty); - }, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_expr: |e: @ast::expr| { + let ty = ty::expr_ty(cx, e); + check_type(cx, e.id, it.id, e.span, ty); + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } fn check_item_path_statement(cx: ty::ctxt, it: @ast::item) { - let visit = item_stopping_visitor(visit::mk_simple_visitor(@{ - visit_stmt: fn@(s: @ast::stmt) { - match s.node { - ast::stmt_semi(@{id: id, - callee_id: _, - node: ast::expr_path(_), - span: _}, _) => { - cx.sess.span_lint( - path_statement, id, it.id, - s.span, - ~"path statement with no effect"); - } - _ => () - } - }, - .. *visit::default_simple_visitor() - })); + let visit = item_stopping_visitor( + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_stmt: |s: @ast::stmt| { + match s.node { + ast::stmt_semi(@{id: id, + callee_id: _, + node: ast::expr_path(_), + span: _}, _) => { + cx.sess.span_lint( + path_statement, id, it.id, + s.span, + ~"path statement with no effect"); + } + _ => () + } + }, + .. *visit::default_simple_visitor() + })); visit::visit_item(it, (), visit); } @@ -793,14 +824,14 @@ fn check_item_non_camel_case_types(cx: ty::ctxt, it: @ast::item) { !ident.contains_char('_') } - fn ident_without_trailing_underscores(ident: ~str) -> ~str { + fn ident_without_trailing_underscores(+ident: ~str) -> ~str { match str::rfind(ident, |c| c != '_') { Some(idx) => (ident).slice(0, idx + 1), None => { ident } // all underscores } } - fn ident_without_leading_underscores(ident: ~str) -> ~str { + fn ident_without_leading_underscores(+ident: ~str) -> ~str { match str::find(ident, |c| c != '_') { Some(idx) => ident.slice(idx, ident.len()), None => { @@ -948,7 +979,7 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) { fn check_crate(tcx: ty::ctxt, crate: @ast::crate) { - let v = visit::mk_simple_visitor(@{ + let v = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |it| check_item(it, tcx), visit_fn: |fk, decl, body, span, id| diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index c481ef81477bb..2cfda6d74b387 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + /*! * A classic liveness analysis based on dataflow over the AST. Computes, * for each local variable in a function, whether that variable is live @@ -103,10 +104,20 @@ */ use middle::capture::{cap_move, cap_drop, cap_copy, cap_ref}; +use middle::capture; +use middle::pat_util; use middle::ty::MoveValue; +use middle::ty; +use middle::typeck; +use core::cmp; use core::dvec::DVec; use core::io::WriterUtil; +use core::io; +use core::ptr; +use core::to_str; +use core::uint; +use core::vec; use std::map::HashMap; use syntax::ast::*; use syntax::codemap::span; @@ -194,7 +205,7 @@ fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str { fn check_crate(tcx: ty::ctxt, method_map: typeck::method_map, crate: @crate) -> last_use_map { - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_fn: visit_fn, visit_local: visit_local, visit_expr: visit_expr, @@ -414,7 +425,7 @@ impl IrMaps { fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span, id: node_id, &&self: @IrMaps, v: vt<@IrMaps>) { debug!("visit_fn: id=%d", id); - let _i = util::common::indenter(); + let _i = ::util::common::indenter(); // swap in a new set of IR maps for this function body: let fn_maps = @IrMaps(self.tcx, self.method_map, @@ -476,7 +487,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, let entry_ln = (*lsets).compute(decl, body); // check for various error conditions - let check_vt = visit::mk_vt(@{ + let check_vt = visit::mk_vt(@visit::Visitor { visit_fn: check_fn, visit_local: check_local, visit_expr: check_expr, @@ -1022,7 +1033,7 @@ impl Liveness { } fn propagate_through_decl(decl: @decl, succ: LiveNode) -> LiveNode { - match decl.node { + match /*bad*/copy decl.node { decl_local(locals) => { do locals.foldr(succ) |local, succ| { self.propagate_through_local(*local, succ) @@ -1071,7 +1082,7 @@ impl Liveness { debug!("propagate_through_expr: %s", expr_to_str(expr, self.tcx.sess.intr())); - match expr.node { + match /*bad*/copy expr.node { // Interesting cases with control flow or which gen/kill expr_path(_) => { @@ -1552,7 +1563,7 @@ fn check_call(args: &[@expr], } fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) { - match expr.node { + match /*bad*/copy expr.node { expr_path(_) => { for self.variable_from_def_map(expr.id, expr.span).each |var| { let ln = self.live_node(expr.id, expr.span); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 8962a1494e50d..9b373ef0c16c2 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + /*! * # Categorization * @@ -46,12 +47,18 @@ * then an index to jump forward to the relevant item. */ -use syntax::ast; +use middle::ty; +use middle::typeck; +use util::ppaux::{ty_to_str, region_to_str}; +use util::common::indenter; + +use core::cmp; +use core::to_bytes; +use core::uint; use syntax::ast::{m_imm, m_const, m_mutbl}; +use syntax::ast; use syntax::codemap::span; use syntax::print::pprust; -use util::ppaux::{ty_to_str, region_to_str}; -use util::common::indenter; enum categorization { cat_rvalue, // result of eval'ing some misc expr @@ -897,7 +904,7 @@ impl &mem_categorization_ctxt { // local(x)->@->@ // // where the id of `local(x)` is the id of the `x` that appears - // in the alt, the id of `local(x)->@` is the `@y` pattern, + // in the match, the id of `local(x)->@` is the `@y` pattern, // and the id of `local(x)->@->@` is the id of the `y` pattern. @@ -907,7 +914,7 @@ impl &mem_categorization_ctxt { pat.id, pprust::pat_to_str(pat, tcx.sess.intr()), self.cmt_to_repr(cmt)); - match pat.node { + match /*bad*/copy pat.node { ast::pat_wild => { // _ } @@ -1111,7 +1118,7 @@ fn field_mutbl(tcx: ty::ctxt, f_name: ast::ident, node_id: ast::node_id) -> Option { // Need to refactor so that records/class fields can be treated uniformly. - match ty::get(base_ty).sty { + match /*bad*/copy ty::get(base_ty).sty { ty::ty_rec(fields) => { for fields.each |f| { if f.ident == f_name { diff --git a/src/librustc/middle/mode.rs b/src/librustc/middle/mode.rs index 28fa77d625d93..397c0e20a6e7e 100644 --- a/src/librustc/middle/mode.rs +++ b/src/librustc/middle/mode.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use middle::pat_util; use middle::ty; use middle::ty::{CopyValue, MoveValue, ReadValue, ValueMode, ctxt}; @@ -89,7 +90,7 @@ fn compute_modes_for_expr(expr: @expr, } }; - match expr.node { + match /*bad*/copy expr.node { expr_call(callee, args, is_block) => { let callee_cx = VisitContext { mode: ReadValue, ..cx }; compute_modes_for_expr(callee, callee_cx, v); @@ -232,7 +233,7 @@ fn compute_modes_for_pat(pat: @pat, } pub fn compute_modes(tcx: ctxt, method_map: method_map, crate: @crate) { - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_expr: compute_modes_for_expr, visit_pat: compute_modes_for_pat, .. *visit::default_visitor() diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index b1bd42758f19a..54d3180dbe49f 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::resolve; use middle::ty::{CopyValue, MoveValue, ReadValue}; +use middle::ty; use syntax::ast::*; use syntax::ast_util; @@ -23,12 +26,12 @@ export pat_is_variant_or_struct, pat_is_binding, pat_is_binding_or_wild; export pat_is_const; export arms_have_by_move_bindings; -type PatIdMap = std::map::HashMap; +type PatIdMap = HashMap; // This is used because same-named variables in alternative patterns need to // use the node_id of their namesake in the first pattern. fn pat_id_map(dm: resolve::DefMap, pat: @pat) -> PatIdMap { - let map = std::map::HashMap(); + let map = HashMap(); do pat_bindings(dm, pat) |_bm, p_id, _s, n| { map.insert(path_to_ident(n), p_id); }; diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 5819db17f58a8..acc5e6410c6a7 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -8,25 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + // A pass that checks to make sure private fields and methods aren't used // outside their scopes. use middle::ty::{ty_struct, ty_enum}; +use middle::ty; use middle::typeck::{method_map, method_origin, method_param, method_self}; use middle::typeck::{method_static, method_trait}; -use /*mod*/ syntax::ast; -use /*mod*/ syntax::visit; -use syntax::ast_map; + +use core::dvec::DVec; +use core::util::ignore; use syntax::ast::{def_variant, expr_field, expr_method_call, expr_struct}; use syntax::ast::{expr_unary, ident, item_struct, item_enum, item_impl}; use syntax::ast::{item_trait, local_crate, node_id, pat_struct, private}; use syntax::ast::{provided, required}; +use syntax::ast; use syntax::ast_map::{node_item, node_method}; +use syntax::ast_map; use syntax::ast_util::{Private, Public, has_legacy_export_attr, is_local}; use syntax::ast_util::{visibility_to_privacy}; - -use core::util::ignore; -use dvec::DVec; +use syntax::visit; fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) { let privileged_items = @DVec(); @@ -186,7 +188,7 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) { } }; - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_mod: |the_module, span, node_id, method_map, visitor| { let n_added = add_privileged_items(the_module.items); @@ -310,7 +312,7 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) { visit::visit_expr(expr, method_map, visitor); }, visit_pat: |pattern, method_map, visitor| { - match pattern.node { + match /*bad*/copy pattern.node { pat_struct(_, fields, _) => { match ty::get(ty::pat_ty(tcx, pattern)).sty { ty_struct(id, _) => { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f746e0236807e..1d9396ee2c37a 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -17,13 +17,17 @@ region parameterized. */ + use driver::session::Session; use metadata::csearch; +use middle::resolve; use middle::ty::{region_variance, rv_covariant, rv_invariant}; use middle::ty::{rv_contravariant}; use middle::ty; +use core::cmp; use core::dvec::DVec; +use core::vec; use std::list; use std::list::list; use std::map::HashMap; @@ -67,7 +71,7 @@ struct ctxt { // that when we visit it we can view it as a parent. root_exprs: HashMap, - // The parent scope is the innermost block, statement, call, or alt + // The parent scope is the innermost block, statement, call, or match // expression during the execution of which the current expression // will be evaluated. Generally speaking, the innermost parent // scope is also the closest suitable ancestor in the AST tree. @@ -347,7 +351,7 @@ fn resolve_crate(sess: Session, def_map: resolve::DefMap, region_map: HashMap(), root_exprs: HashMap(), parent: None}; - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_block: resolve_block, visit_item: resolve_item, visit_fn: resolve_fn, @@ -564,7 +568,7 @@ impl determine_rp_ctxt { self.item_id = item_id; self.anon_implies_rp = anon_implies_rp; debug!("with_item_id(%d, %b)", item_id, anon_implies_rp); - let _i = util::common::indenter(); + let _i = ::util::common::indenter(); f(); self.item_id = old_item_id; self.anon_implies_rp = old_anon_implies_rp; @@ -777,7 +781,7 @@ fn determine_rp_in_crate(sess: Session, mut ambient_variance: rv_covariant}); // Gather up the base set, worklist and dep_map - let visitor = visit::mk_vt(@{ + let visitor = visit::mk_vt(@visit::Visitor { visit_fn: determine_rp_in_fn, visit_item: determine_rp_in_item, visit_ty: determine_rp_in_ty, diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index f8138dc6d325f..9fa524a3fcd35 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + 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}; @@ -16,6 +17,10 @@ use metadata::decoder::{def_like, dl_def, dl_field, dl_impl}; use middle::lang_items::LanguageItems; use middle::lint::{deny, allow, forbid, level, unused_imports, warn}; use middle::pat_util::{pat_bindings}; + +use core::cmp; +use core::str; +use core::vec; use syntax::ast::{_mod, add, arm, binding_mode, bitand, bitor, bitxor, blk}; use syntax::ast::{capture_clause}; use syntax::ast::{crate, crate_num, decl_item, def, def_arg, def_binding}; @@ -35,16 +40,16 @@ use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge}; use syntax::ast::{gt, ident, impure_fn, inherited, item, item_struct}; use syntax::ast::{item_const, item_enum, item_fn, item_foreign_mod}; use syntax::ast::{item_impl, item_mac, item_mod, item_trait, item_ty, le}; -use syntax::ast::{local, local_crate, lt, method, mode, module_ns, mul, ne}; -use syntax::ast::{neg, node_id, pat, pat_enum, pat_ident, path, prim_ty}; -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, struct_dtor}; -use syntax::ast::{struct_field, struct_variant_kind, sty_by_ref, sty_static}; -use syntax::ast::{subtract, trait_ref, tuple_variant_kind, Ty, ty_bool}; -use syntax::ast::{ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16}; -use syntax::ast::{ty_i32, ty_i64, ty_i8, ty_int, ty_param, ty_path, ty_str}; -use syntax::ast::{ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint}; +use syntax::ast::{local, local_crate, lt, method, mode, module_ns, mul}; +use syntax::ast::{named_field, ne, neg, node_id, pat, pat_enum, pat_ident}; +use syntax::ast::{path, pat_box, pat_lit, pat_range, pat_rec, pat_struct}; +use syntax::ast::{pat_tup, pat_uniq, pat_wild, prim_ty, private, provided}; +use syntax::ast::{public, required, rem, self_ty_, shl, shr, stmt_decl}; +use syntax::ast::{struct_dtor, struct_field, struct_variant_kind, sty_by_ref}; +use syntax::ast::{sty_static, subtract, trait_ref, tuple_variant_kind, Ty}; +use syntax::ast::{ty_bool, ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i}; +use syntax::ast::{ty_i16, ty_i32, ty_i64, ty_i8, ty_int, ty_param, ty_path}; +use syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint}; use syntax::ast::{type_value_ns, ty_param_bound, unnamed_field}; use syntax::ast::{variant, view_item, view_item_export, view_item_import}; use syntax::ast::{view_item_use, view_path_glob, view_path_list}; @@ -54,9 +59,11 @@ use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method}; use syntax::ast_util::{Privacy, Public, Private, visibility_to_privacy}; use syntax::ast_util::has_legacy_export_attr; use syntax::attr::{attr_metas, contains_name}; +use syntax::parse::token::ident_interner; +use syntax::parse::token::special_idents; use syntax::print::pprust::{pat_to_str, path_to_str}; use syntax::codemap::span; -use syntax::visit::{default_visitor, fk_method, mk_vt, visit_block}; +use syntax::visit::{default_visitor, fk_method, mk_vt, Visitor, visit_block}; use syntax::visit::{visit_crate, visit_expr, visit_expr_opt, visit_fn}; use syntax::visit::{visit_foreign_item, visit_item, visit_method_helper}; use syntax::visit::{visit_mod, visit_ty, vt}; @@ -66,7 +73,6 @@ use dvec::DVec; use option::{Some, get, is_some, is_none}; use str::{connect, split_str}; use vec::pop; -use syntax::parse::token::ident_interner; use std::list::{Cons, List, Nil}; use std::map::HashMap; @@ -317,9 +323,14 @@ enum UseLexicalScopeFlag { UseLexicalScope } -struct ModulePrefixResult { - result: ResolveResult<@Module>, - prefix_len: uint +enum SearchThroughModulesFlag { + DontSearchThroughModules, + SearchThroughModules +} + +enum ModulePrefixResult { + NoPrefixFound, + PrefixFound(@Module, uint) } impl XrayFlag : cmp::Eq { @@ -475,10 +486,19 @@ enum ParentLink { BlockParentLink(@Module, node_id) } +/// The type of module this is. +enum ModuleKind { + NormalModuleKind, + ExternModuleKind, + TraitModuleKind, + AnonymousModuleKind, +} + /// One node in the tree of modules. struct Module { parent_link: ParentLink, mut def_id: Option, + kind: ModuleKind, children: HashMap, imports: DVec<@ImportDirective>, @@ -527,10 +547,12 @@ struct Module { fn Module(parent_link: ParentLink, def_id: Option, + kind: ModuleKind, legacy_exports: bool) -> Module { Module { parent_link: parent_link, def_id: def_id, + kind: kind, children: HashMap(), imports: DVec(), anonymous_children: HashMap(), @@ -589,10 +611,11 @@ impl NameBindings { fn define_module(privacy: Privacy, parent_link: ParentLink, def_id: Option, + kind: ModuleKind, legacy_exports: bool, sp: span) { // Merges the module with the existing type def or creates a new one. - let module_ = @Module(parent_link, def_id, legacy_exports); + let module_ = @Module(parent_link, def_id, kind, legacy_exports); match self.type_def { None => { self.type_def = Some(TypeNsDef { @@ -794,6 +817,7 @@ fn Resolver(session: Session, lang_items: LanguageItems, (*graph_root).define_module(Public, NoParentLink, Some({ crate: 0, node: 0 }), + NormalModuleKind, has_legacy_export_attr(crate.node.attrs), crate.span); @@ -824,7 +848,7 @@ fn Resolver(session: Session, lang_items: LanguageItems, xray_context: NoXray, current_trait_refs: None, - self_ident: syntax::parse::token::special_idents::self_, + self_ident: special_idents::self_, primitive_type_table: @PrimitiveTypeTable(session. parse_sess.interner), @@ -922,7 +946,7 @@ impl Resolver { fn build_reduced_graph(this: @Resolver) { let initial_parent = ModuleReducedGraphParent((*self.graph_root).get_module()); - visit_crate(*self.crate, initial_parent, mk_vt(@{ + visit_crate(*self.crate, initial_parent, mk_vt(@Visitor { visit_item: |item, context, visitor| (*this).build_reduced_graph_for_item(item, context, visitor), @@ -1103,7 +1127,7 @@ impl Resolver { }; let privacy = visibility_to_privacy(item.vis, legacy); - match item.node { + match /*bad*/copy item.node { item_mod(module_) => { let legacy = has_legacy_export_attr(item.attrs); let (name_bindings, new_parent) = @@ -1111,8 +1135,12 @@ impl Resolver { 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), + NormalModuleKind, + legacy, + sp); let new_parent = ModuleReducedGraphParent((*name_bindings).get_module()); @@ -1134,6 +1162,7 @@ impl Resolver { (*name_bindings).define_module(privacy, parent_link, Some(def_id), + ExternModuleKind, legacy, sp); @@ -1251,8 +1280,12 @@ impl Resolver { 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); + name_bindings.define_module(privacy, + parent_link, + Some(def_id), + TraitModuleKind, + false, + sp); let new_parent = ModuleReducedGraphParent( name_bindings.get_module()); @@ -1313,6 +1346,7 @@ impl Resolver { name_bindings.define_module(privacy, parent_link, Some(local_def(item.id)), + TraitModuleKind, false, sp); module_parent_opt = Some(ModuleReducedGraphParent( @@ -1425,7 +1459,7 @@ impl Resolver { ModuleReducedGraphParent(m) => m.legacy_exports }; let privacy = visibility_to_privacy(view_item.vis, legacy); - match view_item.node { + match /*bad*/copy view_item.node { view_item_import(view_paths) => { for view_paths.each |view_path| { // Extract and intern the module part of the path. For @@ -1568,6 +1602,7 @@ impl Resolver { (*child_name_bindings).define_module(privacy, parent_link, Some(def_id), + NormalModuleKind, false, view_item.span); self.build_reduced_graph_for_external_crate @@ -1592,7 +1627,7 @@ impl Resolver { self.add_child(name, parent, ForbidDuplicateValues, foreign_item.span); - match foreign_item.node { + match /*bad*/copy foreign_item.node { foreign_item_fn(_, purity, type_parameters) => { let def = def_fn(local_def(foreign_item.id), purity); (*name_bindings).define_value(Public, def, foreign_item.span); @@ -1626,7 +1661,9 @@ impl Resolver { let parent_module = self.get_module_from_parent(parent); let new_module = @Module(BlockParentLink(parent_module, block_id), - None, false); + None, + AnonymousModuleKind, + false); parent_module.anonymous_children.insert(block_id, new_module); new_parent = ModuleReducedGraphParent(new_module); } else { @@ -1660,6 +1697,7 @@ impl Resolver { child_name_bindings.define_module(Public, parent_link, Some(def_id), + NormalModuleKind, false, dummy_sp()); modules.insert(def_id, @@ -1772,7 +1810,7 @@ impl Resolver { let mut current_module = root; for pieces.each |ident_str| { - let ident = self.session.ident_of(*ident_str); + let ident = self.session.ident_of(/*bad*/copy *ident_str); // Create or reuse a graph node for the child. let (child_name_bindings, new_parent) = self.add_child(ident, @@ -1791,6 +1829,7 @@ impl Resolver { (*child_name_bindings).define_module(Public, parent_link, None, + NormalModuleKind, false, dummy_sp()); } @@ -1804,6 +1843,7 @@ impl Resolver { (*child_name_bindings).define_module(Public, parent_link, None, + NormalModuleKind, false, dummy_sp()); } @@ -1830,9 +1870,6 @@ impl Resolver { } dl_impl(def) => { // We only process static methods of impls here. - debug!("(building reduced graph for external crate) \ - processing impl %s", final_ident_str); - match get_type_name_if_impl(self.session.cstore, def) { None => {} Some(final_ident) => { @@ -1840,7 +1877,7 @@ impl Resolver { get_static_methods_if_impl( self.session.cstore, def); match static_methods_opt { - Some(static_methods) if + Some(ref static_methods) if static_methods.len() >= 1 => { debug!("(building reduced graph for \ external crate) processing \ @@ -1874,6 +1911,7 @@ impl Resolver { Public, parent_link, Some(def), + NormalModuleKind, false, dummy_sp()); type_module = @@ -1915,7 +1953,7 @@ impl Resolver { } dl_field => { debug!("(building reduced graph for external crate) \ - ignoring field %s", final_ident_str); + ignoring field"); } } } @@ -2046,8 +2084,11 @@ impl Resolver { match self.resolve_import_for_module(module_, import_directive) { Failed => { // We presumably emitted an error. Continue. - self.session.span_err(import_directive.span, - ~"failed to resolve import"); + let idents = import_directive.module_path.get(); + let msg = fmt!("failed to resolve import: %s", + self.import_path_to_str(idents, + *import_directive.subclass)); + self.session.span_err(import_directive.span, msg); } Indeterminate => { // Bail out. We'll come around next time. @@ -2063,20 +2104,29 @@ impl Resolver { } fn idents_to_str(idents: ~[ident]) -> ~str { - // XXX: str::connect should do this. - let mut result = ~""; - let mut first = true; - for idents.each() |ident| { - if first { - first = false; - } else { - result += ~"::"; - } - result += self.session.str_of(*ident); - } - // XXX: Shouldn't copy here. We need string builder functionality. - return result; + let ident_strs = idents.map(|&ident| self.session.str_of(ident)); + return str::connect(ident_strs, "::"); } + + fn import_directive_subclass_to_str(subclass: ImportDirectiveSubclass) + -> ~str { + match subclass { + SingleImport(_target, source, _ns) => self.session.str_of(source), + GlobImport => ~"*" + } + } + + fn import_path_to_str(idents: ~[ident], subclass: ImportDirectiveSubclass) + -> ~str { + if idents.is_empty() { + self.import_directive_subclass_to_str(subclass) + } else { + fmt!("%s::%s", + self.idents_to_str(idents), + self.import_directive_subclass_to_str(subclass)) + } + } + /** * Attempts to resolve the given import. The return value indicates * failure if we're certain the name does not exist, indeterminate if we @@ -2722,23 +2772,13 @@ impl Resolver { self.idents_to_str((*module_path).get()), self.module_to_str(module_)); - // The first element of the module path must be in the current scope - // chain. - - let resolve_result = match use_lexical_scope { - DontUseLexicalScope => { - self.resolve_module_prefix(module_, module_path) - } - UseLexicalScope => { - let result = self.resolve_module_in_lexical_scope( - module_, - module_path.get_elt(0)); - ModulePrefixResult { result: result, prefix_len: 1 } - } - }; + // Resolve the module prefix, if any. + let module_prefix_result = self.resolve_module_prefix(module_, + module_path); let mut search_module; - match resolve_result.result { + let mut start_index; + match module_prefix_result { Failed => { self.session.span_err(span, ~"unresolved name"); return Failed; @@ -2748,21 +2788,61 @@ impl Resolver { bailing"); return Indeterminate; } - Success(resulting_module) => { - search_module = resulting_module; + Success(NoPrefixFound) => { + // There was no prefix, so we're considering the first element + // of the path. How we handle this depends on whether we were + // instructed to use lexical scope or not. + match use_lexical_scope { + DontUseLexicalScope => { + // This is a crate-relative path. We will start the + // resolution process at index zero. + search_module = self.graph_root.get_module(); + start_index = 0; + } + UseLexicalScope => { + // This is not a crate-relative path. We resolve the + // first component of the path in the current lexical + // scope and then proceed to resolve below that. + let result = self.resolve_module_in_lexical_scope( + module_, + module_path.get_elt(0)); + match result { + Failed => { + self.session.span_err(span, + ~"unresolved name"); + return Failed; + } + Indeterminate => { + debug!("(resolving module path for import) \ + indeterminate; bailing"); + return Indeterminate; + } + Success(containing_module) => { + search_module = containing_module; + start_index = 1; + } + } + } + } + } + Success(PrefixFound(containing_module, index)) => { + search_module = containing_module; + start_index = index; } } return self.resolve_module_path_from_root(search_module, module_path, - resolve_result.prefix_len, + start_index, xray, span); } fn resolve_item_in_lexical_scope(module_: @Module, name: ident, - namespace: Namespace) + namespace: Namespace, + search_through_modules: + SearchThroughModulesFlag) -> ResolveResult { debug!("(resolving item in lexical scope) resolving `%s` in \ @@ -2818,7 +2898,30 @@ impl Resolver { module"); return Failed; } - ModuleParentLink(parent_module_node, _) | + ModuleParentLink(parent_module_node, _) => { + match search_through_modules { + DontSearchThroughModules => { + match search_module.kind { + NormalModuleKind => { + // We stop the search here. + debug!("(resolving item in lexical \ + scope) unresolved module: not \ + searching through module \ + parents"); + return Failed; + } + ExternModuleKind | + TraitModuleKind | + AnonymousModuleKind => { + search_module = parent_module_node; + } + } + } + SearchThroughModules => { + search_module = parent_module_node; + } + } + } BlockParentLink(parent_module_node, _) => { search_module = parent_module_node; } @@ -2854,9 +2957,8 @@ impl Resolver { -> ResolveResult<@Module> { // If this module is an anonymous module, resolve the item in the // lexical scope. Otherwise, resolve the item from the crate root. - let resolve_result = self.resolve_item_in_lexical_scope(module_, - name, - TypeNS); + let resolve_result = self.resolve_item_in_lexical_scope( + module_, name, TypeNS, DontSearchThroughModules); match resolve_result { Success(target) => { match target.bindings.type_def { @@ -2894,46 +2996,102 @@ impl Resolver { } /** - * Resolves a "module prefix". A module prefix is one of (a) the name of a - * module; (b) "self::"; (c) some chain of "super::". + * Returns the nearest normal module parent of the given module. + */ + fn get_nearest_normal_module_parent(module_: @Module) -> Option<@Module> { + let mut module_ = module_; + loop { + match module_.parent_link { + NoParentLink => return None, + ModuleParentLink(new_module, _) | + BlockParentLink(new_module, _) => { + match new_module.kind { + NormalModuleKind => return Some(new_module), + ExternModuleKind | + TraitModuleKind | + AnonymousModuleKind => module_ = new_module, + } + } + } + } + } + + /** + * Returns the nearest normal module parent of the given module, or the + * module itself if it is a normal module. + */ + fn get_nearest_normal_module_parent_or_self(module_: @Module) -> @Module { + match module_.kind { + NormalModuleKind => return module_, + ExternModuleKind | TraitModuleKind | AnonymousModuleKind => { + match self.get_nearest_normal_module_parent(module_) { + None => module_, + Some(new_module) => new_module + } + } + } + } + + /** + * Resolves a "module prefix". A module prefix is one of (a) `self::`; + * (b) some chain of `super::`. */ fn resolve_module_prefix(module_: @Module, module_path: @DVec) - -> ModulePrefixResult { + -> ResolveResult { let interner = self.session.parse_sess.interner; - let mut containing_module = self.graph_root.get_module(); - let mut i = 0; - loop { - if *interner.get(module_path.get_elt(i)) == ~"self" { - containing_module = module_; - i += 1; - break; - } - if *interner.get(module_path.get_elt(i)) == ~"super" { - match containing_module.parent_link { - NoParentLink => { - return ModulePrefixResult { - result: Failed, - prefix_len: i - }; - } - BlockParentLink(new_module, _) | - ModuleParentLink(new_module, _) => { - containing_module = new_module; - } + // Start at the current module if we see `self` or `super`, or at the + // top of the crate otherwise. + let mut containing_module; + let mut i; + if *interner.get(module_path.get_elt(0)) == ~"self" { + containing_module = + self.get_nearest_normal_module_parent_or_self(module_); + i = 1; + } else if *interner.get(module_path.get_elt(0)) == ~"super" { + containing_module = + self.get_nearest_normal_module_parent_or_self(module_); + i = 0; // We'll handle `super` below. + } else { + return Success(NoPrefixFound); + } + + // Now loop through all the `super`s we find. + while i < module_path.len() && + *interner.get(module_path.get_elt(i)) == ~"super" { + debug!("(resolving module prefix) resolving `super` at %s", + self.module_to_str(containing_module)); + match self.get_nearest_normal_module_parent(containing_module) { + None => return Failed, + Some(new_module) => { + containing_module = new_module; + i += 1; } - i += 1; - } else { - break; } } + debug!("(resolving module prefix) finished resolving prefix at %s", + self.module_to_str(containing_module)); + + return Success(PrefixFound(containing_module, i)); + + /* + // If we reached the end, return the containing module. + if i == module_path.len() { + return ModulePrefixResult { + result: Success(containing_module), + prefix_len: i + }; + } + // Is the containing module the current module? If so, we allow // globs to be unresolved. let allow_globs = core::managed::ptr_eq(containing_module, module_); let name = module_path.get_elt(i); + i += 1; + let resolve_result = self.resolve_name_in_module(containing_module, name, TypeNS, @@ -2950,13 +3108,13 @@ impl Resolver { module!"); return ModulePrefixResult { result: Failed, - prefix_len: i + 1 + prefix_len: i }; } Some(module_def) => { return ModulePrefixResult { result: Success(module_def), - prefix_len: i + 1 + prefix_len: i }; } } @@ -2966,7 +3124,7 @@ impl Resolver { wasn't actually a module!"); return ModulePrefixResult { result: Failed, - prefix_len: i + 1 + prefix_len: i }; } } @@ -2976,17 +3134,18 @@ impl Resolver { bailing"); return ModulePrefixResult { result: Indeterminate, - prefix_len: i + 1 + prefix_len: i }; } Failed => { debug!("(resolving crate-relative module) failed to resolve"); return ModulePrefixResult { result: Failed, - prefix_len: i + 1 + prefix_len: i }; } } + */ } fn name_is_exported(module_: @Module, name: ident) -> bool { @@ -3109,7 +3268,8 @@ impl Resolver { debug!("(resolving one-level naming result) searching for module"); match self.resolve_item_in_lexical_scope(module_, source_name, - TypeNS) { + TypeNS, + SearchThroughModules) { Failed => { debug!("(resolving one-level renaming import) didn't find \ module result"); @@ -3135,8 +3295,9 @@ impl Resolver { } else { debug!("(resolving one-level naming result) searching for value"); match self.resolve_item_in_lexical_scope(module_, - source_name, - ValueNS) { + source_name, + ValueNS, + SearchThroughModules) { Failed => { debug!("(resolving one-level renaming import) didn't \ @@ -3157,8 +3318,9 @@ impl Resolver { debug!("(resolving one-level naming result) searching for type"); match self.resolve_item_in_lexical_scope(module_, - source_name, - TypeNS) { + source_name, + TypeNS, + SearchThroughModules) { Failed => { debug!("(resolving one-level renaming import) didn't \ @@ -3628,7 +3790,7 @@ impl Resolver { fn resolve_crate(@self) { debug!("(resolving crate) starting"); - visit_crate(*self.crate, (), mk_vt(@{ + visit_crate(*self.crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| self.resolve_item(item, visitor), visit_arm: |arm, _context, visitor| @@ -3652,15 +3814,16 @@ impl Resolver { // Items with the !resolve_unexported attribute are X-ray contexts. // This is used to allow the test runner to run unexported tests. let orig_xray_flag = self.xray_context; - if contains_name(attr_metas(item.attrs), ~"!resolve_unexported") { + if contains_name(attr_metas(/*bad*/copy item.attrs), + ~"!resolve_unexported") { self.xray_context = Xray; } - match item.node { + match /*bad*/copy item.node { // enum item: resolve all the variants' discrs, // then resolve the ty params - item_enum(ref enum_def, type_parameters) => { + item_enum(ref enum_def, ref type_parameters) => { for (*enum_def).variants.each() |variant| { do variant.node.disr_expr.iter() |dis_expr| { @@ -3675,11 +3838,9 @@ impl Resolver { // 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)) - || { - + do self.with_type_parameter_rib( + HasTypeParameters( + type_parameters, item.id, 0, NormalRibKind)) { visit_item(item, (), visitor); } } @@ -3707,7 +3868,7 @@ impl Resolver { visitor); } - item_trait(type_parameters, traits, ref methods) => { + item_trait(ref type_parameters, ref traits, ref methods) => { // Create a new rib for the self type. let self_type_rib = @Rib(NormalRibKind); (*self.type_ribs).push(self_type_rib); @@ -3716,10 +3877,11 @@ impl Resolver { // Create a new rib for the trait-wide type parameters. do self.with_type_parameter_rib - (HasTypeParameters(&type_parameters, item.id, 0, + (HasTypeParameters(type_parameters, item.id, 0, NormalRibKind)) { - self.resolve_type_parameters(type_parameters, visitor); + self.resolve_type_parameters(/*bad*/copy *type_parameters, + visitor); // Resolve derived traits. for traits.each |trt| { @@ -3758,8 +3920,9 @@ impl Resolver { // Resolve the method-specific type // parameters. - self.resolve_type_parameters((*ty_m).tps, - visitor); + self.resolve_type_parameters( + /*bad*/copy (*ty_m).tps, + visitor); for (*ty_m).decl.inputs.each |argument| { self.resolve_type(argument.ty, visitor); @@ -3785,7 +3948,7 @@ impl Resolver { item_struct(struct_def, ty_params) => { self.resolve_struct(item.id, @copy ty_params, - struct_def.fields, + /*bad*/copy struct_def.fields, struct_def.dtor, visitor); } @@ -3800,7 +3963,7 @@ impl Resolver { item_foreign_mod(foreign_module) => { do self.with_scope(Some(item.ident)) { for foreign_module.items.each |foreign_item| { - match foreign_item.node { + match /*bad*/copy foreign_item.node { foreign_item_fn(_, _, type_parameters) => { do self.with_type_parameter_rib (HasTypeParameters(&type_parameters, @@ -3822,7 +3985,7 @@ impl Resolver { } } - item_fn(fn_decl, _, ty_params, ref block) => { + item_fn(ref fn_decl, _, ref ty_params, ref block) => { // If this is the main function, we must record it in the // session. // @@ -3831,15 +3994,15 @@ impl Resolver { if !self.session.building_library && is_none(&self.session.main_fn) && - item.ident == syntax::parse::token::special_idents::main { + item.ident == special_idents::main { self.session.main_fn = Some((item.id, item.span)); } self.resolve_function(OpaqueFunctionRibKind, - Some(@fn_decl), + Some(@/*bad*/copy *fn_decl), HasTypeParameters - (&ty_params, + (ty_params, item.id, 0, OpaqueFunctionRibKind), @@ -3964,7 +4127,8 @@ impl Resolver { // Continue. } HasTypeParameters(type_parameters, _, _, _) => { - self.resolve_type_parameters(*type_parameters, visitor); + self.resolve_type_parameters(/*bad*/copy *type_parameters, + visitor); } } @@ -4036,7 +4200,8 @@ impl Resolver { OpaqueFunctionRibKind)) { // Resolve the type parameters. - self.resolve_type_parameters(*type_parameters, visitor); + self.resolve_type_parameters(/*bad*/copy *type_parameters, + visitor); // Resolve fields. for fields.each |field| { @@ -4083,7 +4248,7 @@ impl Resolver { }; self.resolve_function(rib_kind, - Some(@method.decl), + Some(@/*bad*/copy method.decl), type_parameters, method.body, self_binding, @@ -4105,7 +4270,8 @@ impl Resolver { (borrowed_type_parameters, id, 0, NormalRibKind)) { // Resolve the type parameters. - self.resolve_type_parameters(type_parameters, visitor); + self.resolve_type_parameters(/*bad*/copy type_parameters, + visitor); // Resolve the trait reference, if necessary. let original_trait_refs = self.current_trait_refs; @@ -4349,17 +4515,14 @@ impl Resolver { // Write the result into the def map. debug!("(resolving type) writing resolution for `%s` \ (id %d)", - connect(path.idents.map( - |x| self.session.str_of(*x)), ~"::"), + self.idents_to_str(path.idents), path_id); self.record_def(path_id, def); } None => { self.session.span_err (ty.span, fmt!("use of undeclared type name `%s`", - connect(path.idents.map( - |x| self.session.str_of(*x)), - ~"::"))); + self.idents_to_str(path.idents))); } } } @@ -4553,9 +4716,7 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` does not name a structure", - connect(path.idents.map( - |x| self.session.str_of(*x)), - ~"::"))); + self.idents_to_str(path.idents))); } } } @@ -4571,7 +4732,8 @@ impl Resolver { -> BareIdentifierPatternResolution { match self.resolve_item_in_lexical_scope(self.current_module, name, - ValueNS) { + ValueNS, + SearchThroughModules) { Success(target) => { match target.bindings.value_def { None => { @@ -4608,10 +4770,11 @@ impl Resolver { * If `check_ribs` is true, checks the local definitions first; i.e. * doesn't skip straight to the containing module. */ - fn resolve_path(path: @path, namespace: Namespace, check_ribs: bool, + fn resolve_path(path: @path, + namespace: Namespace, + check_ribs: bool, visitor: ResolveVisitor) -> Option { - // First, resolve the types. for path.types.each |ty| { self.resolve_type(*ty, visitor); @@ -4625,8 +4788,8 @@ impl Resolver { if path.idents.len() > 1 { return self.resolve_module_relative_path(path, - self.xray_context, - namespace); + self.xray_context, + namespace); } return self.resolve_identifier(path.idents.last(), @@ -4797,10 +4960,10 @@ impl Resolver { let mut containing_module; match self.resolve_module_path_from_root(root_module, - module_path_idents, - 0, - xray, - path.span) { + module_path_idents, + 0, + xray, + path.span) { Failed => { self.session.span_err(path.span, @@ -4821,9 +4984,9 @@ impl Resolver { let name = path.idents.last(); match self.resolve_definition_of_name_in_module(containing_module, - name, - namespace, - xray) { + name, + namespace, + xray) { NoNameDefinition => { // We failed to resolve the name. Report an error. return None; @@ -4870,8 +5033,9 @@ impl Resolver { -> Option { // Check the items. match self.resolve_item_in_lexical_scope(self.current_module, - ident, - namespace) { + ident, + namespace, + SearchThroughModules) { Success(target) => { match (*target.bindings).def_for_namespace(namespace) { None => { @@ -4909,10 +5073,8 @@ impl Resolver { item_struct(class_def, _) => { for vec::each(class_def.fields) |field| { match field.node.kind { - syntax::ast::unnamed_field - => {}, - syntax::ast::named_field(ident, _, _) - => { + unnamed_field => {}, + named_field(ident, _, _) => { if str::eq_slice(self.session.str_of(ident), name) { return true @@ -4950,14 +5112,12 @@ impl Resolver { Some(def) => { // Write the result into the def map. debug!("(resolving expr) resolved `%s`", - connect(path.idents.map( - |x| self.session.str_of(*x)), ~"::")); + self.idents_to_str(path.idents)); self.record_def(expr.id, def); } None => { - let wrong_name = - connect(path.idents.map( - |x| self.session.str_of(*x)), ~"::") ; + let wrong_name = self.idents_to_str( + /*bad*/copy path.idents); if self.name_exists_in_scope_struct(wrong_name) { self.session.span_err(expr.span, fmt!("unresolved name: `%s`. \ @@ -4976,10 +5136,10 @@ impl Resolver { visit_expr(expr, (), visitor); } - expr_fn(_, fn_decl, ref block, capture_clause) | - expr_fn_block(fn_decl, ref block, capture_clause) => { + expr_fn(_, ref fn_decl, ref block, capture_clause) | + expr_fn_block(ref fn_decl, ref block, capture_clause) => { self.resolve_function(FunctionRibKind(expr.id, block.node.id), - Some(@fn_decl), + Some(@/*bad*/copy *fn_decl), NoTypeParameters, (*block), NoSelfBinding, @@ -5017,9 +5177,7 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` does not name a structure", - connect(path.idents.map( - |x| self.session.str_of(*x)), - ~"::"))); + self.idents_to_str(path.idents))); } } @@ -5070,60 +5228,60 @@ impl Resolver { } expr_binary(add, _, _) | expr_assign_op(add, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.add_trait); + self.lang_items.add_trait()); } expr_binary(subtract, _, _) | expr_assign_op(subtract, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.sub_trait); + self.lang_items.sub_trait()); } expr_binary(mul, _, _) | expr_assign_op(mul, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.mul_trait); + self.lang_items.mul_trait()); } expr_binary(div, _, _) | expr_assign_op(div, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.div_trait); + self.lang_items.div_trait()); } expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.modulo_trait); + self.lang_items.modulo_trait()); } expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.bitxor_trait); + self.lang_items.bitxor_trait()); } expr_binary(bitand, _, _) | expr_assign_op(bitand, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.bitand_trait); + self.lang_items.bitand_trait()); } expr_binary(bitor, _, _) | expr_assign_op(bitor, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.bitor_trait); + self.lang_items.bitor_trait()); } expr_binary(shl, _, _) | expr_assign_op(shl, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.shl_trait); + self.lang_items.shl_trait()); } expr_binary(shr, _, _) | expr_assign_op(shr, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.shr_trait); + self.lang_items.shr_trait()); } expr_binary(lt, _, _) | expr_binary(le, _, _) | expr_binary(ge, _, _) | expr_binary(gt, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.ord_trait); + self.lang_items.ord_trait()); } expr_binary(eq, _, _) | expr_binary(ne, _, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.eq_trait); + self.lang_items.eq_trait()); } expr_unary(neg, _) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.neg_trait); + self.lang_items.neg_trait()); } expr_index(*) => { self.add_fixed_trait_for_expr(expr.id, - self.lang_items.index_trait); + self.lang_items.index_trait()); } _ => { // Nothing to do. @@ -5242,9 +5400,9 @@ impl Resolver { } } - fn add_fixed_trait_for_expr(expr_id: node_id, +trait_id: Option) { + fn add_fixed_trait_for_expr(expr_id: node_id, +trait_id: def_id) { let traits = @DVec(); - traits.push(trait_id.get()); + traits.push(trait_id); self.trait_map.insert(expr_id, traits); } @@ -5338,7 +5496,7 @@ impl Resolver { // hit. // - /// A somewhat inefficient routine to print out the name of a module. + /// A somewhat inefficient routine to obtain the name of a module. fn module_to_str(module_: @Module) -> ~str { let idents = DVec(); let mut current_module = module_; @@ -5352,7 +5510,7 @@ impl Resolver { current_module = module_; } BlockParentLink(module_, _) => { - idents.push(syntax::parse::token::special_idents::opaque); + idents.push(special_idents::opaque); current_module = module_; } } @@ -5361,22 +5519,7 @@ impl Resolver { if idents.len() == 0 { return ~"???"; } - - let mut string = ~""; - let mut i = idents.len() - 1; - loop { - if i < idents.len() - 1 { - string += ~"::"; - } - string += self.session.str_of(idents.get_elt(i)); - - if i == 0 { - break; - } - i -= 1; - } - - return string; + return self.idents_to_str(vec::reversed(idents.get())); } fn dump_module(module_: @Module) { diff --git a/src/librustc/middle/trans/alt.rs b/src/librustc/middle/trans/_match.rs similarity index 97% rename from src/librustc/middle/trans/alt.rs rename to src/librustc/middle/trans/_match.rs index 922dc2363a053..9733102156016 100644 --- a/src/librustc/middle/trans/alt.rs +++ b/src/librustc/middle/trans/_match.rs @@ -142,20 +142,28 @@ * */ + use back::abi; use lib::llvm::llvm; use lib::llvm::{ValueRef, BasicBlockRef}; +use middle::const_eval; use middle::pat_util::*; use middle::resolve::DefMap; use middle::trans::base::*; use middle::trans::build::*; +use middle::trans::callee; use middle::trans::common::*; +use middle::trans::consts; +use middle::trans::controlflow; use middle::trans::datum::*; use middle::trans::expr::Dest; +use middle::trans::expr; +use middle::trans::glue; use middle::ty::{CopyValue, MoveValue, ReadValue}; use util::common::indenter; use core::dvec::DVec; +use core::dvec; use std::map::HashMap; use syntax::ast::def_id; use syntax::ast; @@ -237,7 +245,7 @@ enum opt_result { range_result(Result, Result), } fn trans_opt(bcx: block, o: &Opt) -> opt_result { - let _icx = bcx.insn_ctxt("alt::trans_opt"); + let _icx = bcx.insn_ctxt("match::trans_opt"); let ccx = bcx.ccx(); let mut bcx = bcx; match *o { @@ -279,7 +287,7 @@ fn variant_opt(tcx: ty::ctxt, pat_id: ast::node_id) -> Opt { return var(v.disr_val, {enm: enum_id, var: var_id}); } } - core::util::unreachable(); + ::core::util::unreachable(); } ast::def_struct(_) => { return lit(UnitLikeStructLit(pat_id)); @@ -455,8 +463,8 @@ fn enter_default(bcx: block, dm: DefMap, m: &[@Match/&r], } // nmatsakis: what does enter_opt do? -// in trans/alt -// trans/alt.rs is like stumbling around in a dark cave +// in trans/match +// trans/match.rs is like stumbling around in a dark cave // pcwalton: the enter family of functions adjust the set of // patterns as needed // yeah, at some point I kind of achieved some level of @@ -492,10 +500,10 @@ fn enter_opt(bcx: block, m: &[@Match/&r], opt: &Opt, col: uint, let tcx = bcx.tcx(); let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, tcx.def_map, m, col, val) |p| { - match p.node { + match /*bad*/copy p.node { ast::pat_enum(_, subpats) => { if opt_eq(tcx, &variant_opt(tcx, p.id), opt) { - Some(option::get_default(subpats, + Some(option::get_or_default(subpats, vec::from_elem(variant_size, dummy))) } else { @@ -593,7 +601,7 @@ fn enter_rec_or_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint, let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { - match p.node { + match /*bad*/copy p.node { ast::pat_rec(fpats, _) | ast::pat_struct(_, fpats, _) => { let mut pats = ~[]; for vec::each(fields) |fname| { @@ -625,7 +633,7 @@ fn enter_tup(bcx: block, dm: DefMap, m: &[@Match/&r], let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { - match p.node { + match /*bad*/copy p.node { ast::pat_tup(elts) => { Some(elts) } @@ -650,7 +658,7 @@ fn enter_tuple_struct(bcx: block, dm: DefMap, m: &[@Match/&r], col: uint, let dummy = @{id: 0, node: ast::pat_wild, span: dummy_sp()}; do enter_match(bcx, dm, m, col, val) |p| { - match p.node { + match /*bad*/copy p.node { ast::pat_enum(_, Some(elts)) => Some(elts), _ => { assert_is_binding_or_wild(bcx, p); @@ -747,7 +755,7 @@ fn get_options(ccx: @crate_ctxt, m: &[@Match], col: uint) -> ~[Opt] { let found = DVec(); for vec::each(m) |br| { let cur = br.pats[col]; - match cur.node { + match /*bad*/copy cur.node { ast::pat_lit(l) => { add_to_set(ccx.tcx, &found, lit(ExprLit(l))); } @@ -802,10 +810,13 @@ fn extract_variant_args(bcx: block, pat_id: ast::node_id, val: ValueRef) -> {vals: ~[ValueRef], bcx: block} { - let _icx = bcx.insn_ctxt("alt::extract_variant_args"); + let _icx = bcx.insn_ctxt("match::extract_variant_args"); let ccx = bcx.fcx.ccx; let enum_ty_substs = match ty::get(node_id_type(bcx, pat_id)).sty { - ty::ty_enum(id, ref substs) => { assert id == vdefs.enm; (*substs).tps } + ty::ty_enum(id, ref substs) => { + assert id == vdefs.enm; + /*bad*/copy (*substs).tps + } _ => bcx.sess().bug(~"extract_variant_args: pattern has non-enum type") }; let mut blobptr = val; @@ -821,7 +832,7 @@ fn extract_variant_args(bcx: block, pat_id: ast::node_id, let vdefs_var = vdefs.var; let args = do vec::from_fn(size) |i| { GEP_enum(bcx, blobptr, vdefs_tg, vdefs_var, - enum_ty_substs, i) + /*bad*/copy enum_ty_substs, i) }; return {vals: args, bcx: bcx}; } @@ -830,7 +841,7 @@ fn extract_vec_elems(bcx: block, pat_id: ast::node_id, elem_count: uint, tail: bool, val: ValueRef) -> {vals: ~[ValueRef], bcx: block} { - let _icx = bcx.insn_ctxt("alt::extract_vec_elems"); + let _icx = bcx.insn_ctxt("match::extract_vec_elems"); let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id)); let unboxed = load_if_immediate(bcx, val, vt.vec_ty); let (base, len) = tvec::get_base_and_len(bcx, unboxed, vt.vec_ty); @@ -866,7 +877,7 @@ fn collect_record_or_struct_fields(bcx: block, m: &[@Match], col: uint) -> ~[ast::ident] { let mut fields: ~[ast::ident] = ~[]; for vec::each(m) |br| { - match br.pats[col].node { + match /*bad*/copy br.pats[col].node { ast::pat_rec(fs, _) => extend(&mut fields, fs), ast::pat_struct(_, fs, _) => { match ty::get(node_id_type(bcx, br.pats[col].id)).sty { @@ -898,7 +909,7 @@ fn root_pats_as_necessary(bcx: block, m: &[@Match], match bcx.ccx().maps.root_map.find({id:pat_id, derefs:0u}) { None => (), Some(scope_id) => { - // Note: the scope_id will always be the id of the alt. See + // Note: the scope_id will always be the id of the match. See // the extended comment in rustc::middle::borrowck::preserve() // for details (look for the case covering cat_discr). @@ -1015,7 +1026,7 @@ fn compare_values(cx: block, lhs: ValueRef, rhs: ValueRef, rhs_t: ty::t) -> Store(cx, lhs, scratch_lhs); let scratch_rhs = alloca(cx, val_ty(rhs)); Store(cx, rhs, scratch_rhs); - let did = cx.tcx().lang_items.uniq_str_eq_fn.get(); + let did = cx.tcx().lang_items.uniq_str_eq_fn(); let bcx = callee::trans_rtcall_or_lang_call(cx, did, ~[scratch_lhs, scratch_rhs], @@ -1026,7 +1037,7 @@ fn compare_values(cx: block, lhs: ValueRef, rhs: ValueRef, rhs_t: ty::t) -> ty::ty_estr(_) => { let scratch_result = scratch_datum(cx, ty::mk_bool(cx.tcx()), false); - let did = cx.tcx().lang_items.str_eq_fn.get(); + let did = cx.tcx().lang_items.str_eq_fn(); let bcx = callee::trans_rtcall_or_lang_call(cx, did, ~[lhs, rhs], expr::SaveIn( @@ -1190,7 +1201,7 @@ fn compile_submatch(bcx: block, For an empty match, a fall-through case must exist */ assert(m.len() > 0u || chk.is_some()); - let _icx = bcx.insn_ctxt("alt::compile_submatch"); + let _icx = bcx.insn_ctxt("match::compile_submatch"); let mut bcx = bcx; let tcx = bcx.tcx(), dm = tcx.def_map; if m.len() == 0u { @@ -1252,7 +1263,7 @@ fn compile_submatch(bcx: block, if any_tup_pat(m, col) { let tup_ty = node_id_type(bcx, pat_id); - let n_tup_elts = match ty::get(tup_ty).sty { + let n_tup_elts = match /*bad*/copy ty::get(tup_ty).sty { ty::ty_tup(elts) => elts.len(), _ => ccx.sess.bug(~"non-tuple type in tuple pattern") }; @@ -1478,7 +1489,7 @@ fn compile_submatch(bcx: block, var(_, vdef) => { let args = extract_variant_args(opt_cx, pat_id, vdef, val); size = args.vals.len(); - unpacked = args.vals; + unpacked = /*bad*/copy args.vals; opt_cx = args.bcx; } vec_len_eq(n) | vec_len_ge(n) => { @@ -1488,7 +1499,7 @@ fn compile_submatch(bcx: block, }; let args = extract_vec_elems(opt_cx, pat_id, n, tail, val); size = args.vals.len(); - unpacked = args.vals; + unpacked = /*bad*/copy args.vals; opt_cx = args.bcx; } lit(_) | range(_, _) => () @@ -1509,22 +1520,22 @@ fn compile_submatch(bcx: block, } } -fn trans_alt(bcx: block, - alt_expr: @ast::expr, +fn trans_match(bcx: block, + match_expr: @ast::expr, discr_expr: @ast::expr, arms: ~[ast::arm], dest: Dest) -> block { - let _icx = bcx.insn_ctxt("alt::trans_alt"); - do with_scope(bcx, alt_expr.info(), ~"alt") |bcx| { - trans_alt_inner(bcx, discr_expr, arms, dest) + let _icx = bcx.insn_ctxt("match::trans_match"); + do with_scope(bcx, match_expr.info(), ~"match") |bcx| { + trans_match_inner(bcx, discr_expr, arms, dest) } } -fn trans_alt_inner(scope_cx: block, +fn trans_match_inner(scope_cx: block, discr_expr: @ast::expr, arms: &[ast::arm], dest: Dest) -> block { - let _icx = scope_cx.insn_ctxt("alt::trans_alt_inner"); + let _icx = scope_cx.insn_ctxt("match::trans_match_inner"); let mut bcx = scope_cx; let tcx = bcx.tcx(); @@ -1543,7 +1554,7 @@ fn trans_alt_inner(scope_cx: block, // to an alloca() that will be the value for that local variable. // Note that we use the names because each binding will have many ids // from the various alternatives. - let bindings_map = std::map::HashMap(); + let bindings_map = HashMap(); do pat_bindings(tcx.def_map, arm.pats[0]) |bm, p_id, s, path| { let ident = path_to_ident(path); let variable_ty = node_id_type(bcx, p_id); @@ -1627,7 +1638,7 @@ fn trans_alt_inner(scope_cx: block, return controlflow::join_blocks(scope_cx, dvec::unwrap(move arm_cxs)); - fn mk_fail(bcx: block, sp: span, msg: ~str, + fn mk_fail(bcx: block, sp: span, +msg: ~str, finished: @mut Option) -> BasicBlockRef { match *finished { Some(bb) => return bb, _ => () } let fail_cx = sub_block(bcx, ~"case_fallthrough"); @@ -1644,19 +1655,19 @@ enum IrrefutablePatternBindingMode { BindArgument } -// Not alt-related, but similar to the pattern-munging code above +// Not match-related, but similar to the pattern-munging code above fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef, make_copy: bool, binding_mode: IrrefutablePatternBindingMode) -> block { - let _icx = bcx.insn_ctxt("alt::bind_irrefutable_pat"); + let _icx = bcx.insn_ctxt("match::bind_irrefutable_pat"); let ccx = bcx.fcx.ccx; let mut bcx = bcx; - // Necessary since bind_irrefutable_pat is called outside trans_alt - match pat.node { + // Necessary since bind_irrefutable_pat is called outside trans_match + match /*bad*/copy pat.node { ast::pat_ident(_, _,inner) => { if pat_is_variant_or_struct(bcx.tcx().def_map, pat) { return bcx; diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index d0ce66da43f52..38c461d595d44 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -23,6 +23,7 @@ // but many TypeRefs correspond to one ty::t; for instance, tup(int, int, // int) and rec(x=int, y=int, z=int) will have the same TypeRef. + use back::link::{mangle_exported_name}; use back::link::{mangle_internal_name_by_path_and_seq}; use back::link::{mangle_internal_name_by_path}; @@ -34,20 +35,43 @@ use driver::session::Session; use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef}; use lib::llvm::{True, False}; use lib::llvm::{llvm, mk_target_data, mk_type_names}; +use lib; use metadata::common::link_meta; use metadata::{csearch, cstore, decoder, encoder}; +use middle::astencode; use middle::pat_util::*; +use middle::resolve; +use middle::trans::_match; use middle::trans::build::*; +use middle::trans::callee; use middle::trans::common::*; +use middle::trans::consts; +use middle::trans::controlflow; +use middle::trans::datum; +use middle::trans::debuginfo; +use middle::trans::expr; +use middle::trans::foreign; +use middle::trans::glue; +use middle::trans::inline; +use middle::trans::meth; +use middle::trans::monomorphize; +use middle::trans::reachable; use middle::trans::shape::*; +use middle::trans::tvec; use middle::trans::type_of::*; use util::common::indenter; use util::common::is_main_name; use util::ppaux::{ty_to_str, ty_to_short_str}; use util::ppaux; +use core::either; +use core::hash; +use core::int; +use core::io; use core::libc::{c_uint, c_ulonglong}; use core::option::{is_none, is_some}; +use core::option; +use core::uint; use std::map::HashMap; use std::smallintmap; use std::{map, time, list}; @@ -103,7 +127,7 @@ impl fn_ctxt: get_insn_ctxt { } } -fn log_fn_time(ccx: @crate_ctxt, name: ~str, start: time::Timespec, +fn log_fn_time(ccx: @crate_ctxt, +name: ~str, start: time::Timespec, end: time::Timespec) { let elapsed = 1000 * ((end.sec - start.sec) as int) + ((end.nsec as int) - (start.nsec as int)) / 1000000; @@ -119,13 +143,13 @@ fn decl_fn(llmod: ModuleRef, name: ~str, cc: lib::llvm::CallConv, return llfn; } -fn decl_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) -> ValueRef { +fn decl_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) -> ValueRef { return decl_fn(llmod, name, lib::llvm::CCallConv, llty); } // Only use this if you are going to actually define the function. It's // not valid to simply declare a function as internal. -fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) -> +fn decl_internal_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) -> ValueRef { let llfn = decl_cdecl_fn(llmod, name, llty); lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); @@ -133,17 +157,22 @@ fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) -> } fn get_extern_fn(externs: HashMap<~str, ValueRef>, - llmod: ModuleRef, name: ~str, - cc: lib::llvm::CallConv, ty: TypeRef) -> ValueRef { - if externs.contains_key(name) { return externs.get(name); } - let f = decl_fn(llmod, name, cc, ty); + llmod: ModuleRef, + +name: ~str, + cc: lib::llvm::CallConv, + ty: TypeRef) -> ValueRef { + // XXX: Bad copy. + if externs.contains_key(copy name) { return externs.get(name); } + // XXX: Bad copy. + let f = decl_fn(llmod, copy name, cc, ty); externs.insert(name, f); return f; } fn get_extern_const(externs: HashMap<~str, ValueRef>, llmod: ModuleRef, - name: ~str, ty: TypeRef) -> ValueRef { - if externs.contains_key(name) { return externs.get(name); } + +name: ~str, ty: TypeRef) -> ValueRef { + // XXX: Bad copy. + if externs.contains_key(copy name) { return externs.get(name); } let c = str::as_c_str(name, |buf| llvm::LLVMAddGlobal(llmod, ty, buf)); externs.insert(name, c); return c; @@ -152,7 +181,8 @@ fn get_extern_const(externs: HashMap<~str, ValueRef>, llmod: ModuleRef, fn get_simple_extern_fn(cx: block, externs: HashMap<~str, ValueRef>, llmod: ModuleRef, - name: ~str, n_args: int) -> ValueRef { + +name: ~str, + n_args: int) -> ValueRef { let _icx = cx.insn_ctxt("get_simple_extern_fn"); let ccx = cx.fcx.ccx; let inputs = vec::from_elem(n_args as uint, ccx.int_type); @@ -162,7 +192,7 @@ fn get_simple_extern_fn(cx: block, } fn trans_foreign_call(cx: block, externs: HashMap<~str, ValueRef>, - llmod: ModuleRef, name: ~str, args: ~[ValueRef]) -> + llmod: ModuleRef, +name: ~str, args: ~[ValueRef]) -> ValueRef { let _icx = cx.insn_ctxt("trans_foreign_call"); let n = args.len() as int; @@ -239,14 +269,20 @@ fn opaque_box_body(bcx: block, // malloc_raw_dyn: allocates a box to contain a given type, but with a // potentially dynamic size. -fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, +fn malloc_raw_dyn(bcx: block, + t: ty::t, + heap: heap, size: ValueRef) -> Result { let _icx = bcx.insn_ctxt("malloc_raw"); let ccx = bcx.ccx(); - let (mk_fn, rtcall) = match heap { - heap_shared => (ty::mk_imm_box, ~"malloc"), - heap_exchange => (ty::mk_imm_uniq, ~"exchange_malloc") + let (mk_fn, langcall) = match heap { + heap_shared => { + (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn()) + } + heap_exchange => { + (ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn()) + } }; // Grab the TypeRef type of box_ptr_ty. @@ -260,8 +296,11 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, // Allocate space: let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8())); let rval = alloca_zeroed(bcx, T_ptr(T_i8())); - let bcx = callee::trans_rtcall(bcx, rtcall, ~[tydesc, size], - expr::SaveIn(rval)); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, + langcall, + ~[tydesc, size], + expr::SaveIn(rval)); return rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty)); } @@ -381,8 +420,9 @@ fn set_glue_inlining(f: ValueRef, t: ty::t) { // Double-check that we never ask LLVM to declare the same symbol twice. It // silently mangles such symbols, breaking our linkage model. -fn note_unique_llvm_symbol(ccx: @crate_ctxt, sym: ~str) { - if ccx.all_llvm_symbols.contains_key(sym) { +fn note_unique_llvm_symbol(ccx: @crate_ctxt, +sym: ~str) { + // XXX: Bad copy. + if ccx.all_llvm_symbols.contains_key(copy sym) { ccx.sess.bug(~"duplicate LLVM symbol: " + sym); } ccx.all_llvm_symbols.insert(sym, ()); @@ -453,11 +493,10 @@ fn compare_scalar_types(cx: block, lhs: ValueRef, rhs: ValueRef, fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef, nt: scalar_type, op: ast::binop) -> ValueRef { let _icx = cx.insn_ctxt("compare_scalar_values"); - fn die_(cx: block) -> ! { + fn die(cx: block) -> ! { cx.tcx().sess.bug(~"compare_scalar_values: must be a\ comparison operator"); } - let die = fn@() -> ! { die_(cx) }; match nt { nil_type => { // We don't need to do actual comparisons for nil. @@ -466,7 +505,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef, ast::eq | ast::le | ast::ge => return C_bool(true), ast::ne | ast::lt | ast::gt => return C_bool(false), // refinements would be nice - _ => die() + _ => die(cx) } } floating_point => { @@ -477,7 +516,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef, ast::le => lib::llvm::RealOLE, ast::gt => lib::llvm::RealOGT, ast::ge => lib::llvm::RealOGE, - _ => die() + _ => die(cx) }; return FCmp(cx, cmp, lhs, rhs); } @@ -489,7 +528,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef, ast::le => lib::llvm::IntSLE, ast::gt => lib::llvm::IntSGT, ast::ge => lib::llvm::IntSGE, - _ => die() + _ => die(cx) }; return ICmp(cx, cmp, lhs, rhs); } @@ -501,7 +540,7 @@ fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef, ast::le => lib::llvm::IntULE, ast::gt => lib::llvm::IntUGT, ast::ge => lib::llvm::IntUGE, - _ => die() + _ => die(cx) }; return ICmp(cx, cmp, lhs, rhs); } @@ -538,23 +577,24 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, let mut j = 0u; 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 llfldp_a = GEP_enum(cx, a_tup, tid, v_id, + /*bad*/copy tps, j); // 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; } } - _ => cx.tcx().sess.bug(~"iter_variant: not a function type") + _ => cx.tcx().sess.bug(fmt!("iter_variant: not a function type: \ + %s (variant name = %s)", + cx.ty_to_str(fn_ty), + cx.sess().str_of(variant.name))) } return cx; } - /* - Typestate constraint that shows the unimpl case doesn't happen? - */ let mut cx = cx; - match ty::get(t).sty { + match /*bad*/copy ty::get(t).sty { ty::ty_rec(*) | ty::ty_struct(*) => { do expr::with_field_tys(cx.tcx(), t, None) |_has_dtor, field_tys| { for vec::eachi(field_tys) |i, field_ty| { @@ -580,8 +620,12 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, // Cast the enums to types we can GEP into. if n_variants == 1u { - return iter_variant(cx, av, variants[0], - (*substs).tps, tid, f); + return iter_variant(cx, + av, + variants[0], + /*bad*/copy substs.tps, + tid, + f); } let ccx = cx.ccx(); @@ -606,7 +650,7 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb); let variant_cx = iter_variant(variant_cx, llunion_a_ptr, *variant, - (*substs).tps, tid, f); + /*bad*/copy (*substs).tps, tid, f); Br(variant_cx, next_cx.llbb); } return next_cx; @@ -676,7 +720,7 @@ fn fail_if_zero(cx: block, span: span, divmod: ast::binop, } }; do with_cond(cx, is_zero) |bcx| { - controlflow::trans_fail(bcx, Some(span), text) + controlflow::trans_fail(bcx, Some(span), /*bad*/copy text) } } @@ -719,7 +763,7 @@ fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef { } } -fn invoke(bcx: block, llfn: ValueRef, llargs: ~[ValueRef]) -> block { +fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block { let _icx = bcx.insn_ctxt("invoke_"); if bcx.unreachable { return bcx; } if need_invoke(bcx) { @@ -919,16 +963,17 @@ fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef { return v; } -fn trans_trace(bcx: block, sp_opt: Option, trace_str: ~str) { +fn trans_trace(bcx: block, sp_opt: Option, +trace_str: ~str) { if !bcx.sess().trace() { return; } let _icx = bcx.insn_ctxt("trans_trace"); - add_comment(bcx, trace_str); + // XXX: Bad copy. + add_comment(bcx, copy trace_str); let V_trace_str = C_cstr(bcx.ccx(), trace_str); let {V_filename, V_line} = match sp_opt { Some(sp) => { let sess = bcx.sess(); let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo); - {V_filename: C_cstr(bcx.ccx(), loc.file.name), + {V_filename: C_cstr(bcx.ccx(), /*bad*/copy loc.file.name), V_line: loc.line as int} } None => { @@ -999,11 +1044,11 @@ fn init_local(bcx: block, local: @ast::local) -> block { bcx.to_str()); add_clean(bcx, llptr, ty); - return alt::bind_irrefutable_pat(bcx, - local.node.pat, - llptr, - false, - alt::BindLocal); + return _match::bind_irrefutable_pat(bcx, + local.node.pat, + llptr, + false, + _match::BindLocal); } fn trans_stmt(cx: block, s: ast::stmt) -> block { @@ -1022,7 +1067,7 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block { bcx = expr::trans_into(cx, e, expr::Ignore); } ast::stmt_decl(d, _) => { - match d.node { + match /*bad*/copy d.node { ast::decl_local(locals) => { for vec::each(locals) |local| { bcx = init_local(bcx, *local); @@ -1043,7 +1088,7 @@ fn trans_stmt(cx: block, s: ast::stmt) -> block { // You probably don't want to use this one. See the // next three functions instead. fn new_block(cx: fn_ctxt, parent: Option, +kind: block_kind, - is_lpad: bool, name: ~str, opt_node_info: Option) + is_lpad: bool, +name: ~str, opt_node_info: Option) -> block { let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo { @@ -1060,8 +1105,13 @@ fn new_block(cx: fn_ctxt, parent: Option, +kind: block_kind, } fn simple_block_scope() -> block_kind { - block_scope({loop_break: None, loop_label: None, mut cleanups: ~[], - mut cleanup_paths: ~[], mut landing_pad: None}) + block_scope(scope_info { + loop_break: None, + loop_label: None, + mut cleanups: ~[], + mut cleanup_paths: ~[], + mut landing_pad: None + }) } // Use this when you're at the top block of a function or the like. @@ -1072,14 +1122,14 @@ fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option) -> block { fn scope_block(bcx: block, opt_node_info: Option, - n: ~str) -> block { + +n: ~str) -> block { return new_block(bcx.fcx, Some(bcx), simple_block_scope(), bcx.is_lpad, n, opt_node_info); } 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({ + +n: ~str, opt_node_info: Option) -> block { + return new_block(bcx.fcx, Some(bcx), block_scope(scope_info { loop_break: Some(loop_break), loop_label: loop_label, mut cleanups: ~[], @@ -1089,12 +1139,12 @@ fn loop_scope_block(bcx: block, loop_break: block, loop_label: Option, } // Use this when creating a block for the inside of a landing pad. -fn lpad_block(bcx: block, n: ~str) -> block { +fn lpad_block(bcx: block, +n: ~str) -> block { new_block(bcx.fcx, Some(bcx), block_non_scope, true, n, None) } // Use this when you're making a general CFG BB within a scope. -fn sub_block(bcx: block, n: ~str) -> block { +fn sub_block(bcx: block, +n: ~str) -> block { new_block(bcx.fcx, Some(bcx), block_non_scope, bcx.is_lpad, n, None) } @@ -1200,7 +1250,7 @@ fn leave_block(bcx: block, out_of: block) -> block { } fn with_scope(bcx: block, opt_node_info: Option, - name: ~str, f: fn(block) -> block) -> block { + +name: ~str, f: fn(block) -> block) -> block { let _icx = bcx.insn_ctxt("with_scope"); debug!("with_scope(bcx=%s, opt_node_info=%?, name=%s)", @@ -1212,10 +1262,11 @@ fn with_scope(bcx: block, opt_node_info: Option, leave_block(f(scope_cx), scope_cx) } -fn with_scope_result(bcx: block, opt_node_info: Option, - name: ~str, f: fn(block) -> Result) - -> Result -{ +fn with_scope_result(bcx: block, + opt_node_info: Option, + +name: ~str, + f: fn(block) -> Result) + -> Result { let _icx = bcx.insn_ctxt("with_scope_result"); let scope_cx = scope_block(bcx, opt_node_info, name); Br(bcx, scope_cx.llbb); @@ -1224,7 +1275,7 @@ fn with_scope_result(bcx: block, opt_node_info: Option, } fn with_scope_datumblock(bcx: block, opt_node_info: Option, - name: ~str, f: fn(block) -> datum::DatumBlock) + +name: ~str, f: fn(block) -> datum::DatumBlock) -> datum::DatumBlock { use middle::trans::datum::DatumBlock; @@ -1240,7 +1291,7 @@ fn block_locals(b: ast::blk, it: fn(@ast::local)) { for vec::each(b.node.stmts) |s| { match s.node { ast::stmt_decl(d, _) => { - match d.node { + match /*bad*/copy d.node { ast::decl_local(locals) => { for vec::each(locals) |local| { it(*local); @@ -1403,14 +1454,15 @@ fn mk_standard_basic_blocks(llfn: ValueRef) -> // - new_fn_ctxt // - trans_args fn new_fn_ctxt_w_id(ccx: @crate_ctxt, - path: path, + +path: path, llfndecl: ValueRef, id: ast::node_id, impl_id: Option, - param_substs: Option, + +param_substs: Option, sp: Option) -> fn_ctxt { let llbbs = mk_standard_basic_blocks(llfndecl); - return @{llfn: llfndecl, + return @fn_ctxt_ { + llfn: llfndecl, llenv: llvm::LLVMGetParam(llfndecl, 1u as c_uint), llretptr: llvm::LLVMGetParam(llfndecl, 0u as c_uint), mut llstaticallocas: llbbs.sa, @@ -1427,11 +1479,15 @@ fn new_fn_ctxt_w_id(ccx: @crate_ctxt, param_substs: param_substs, span: sp, path: path, - ccx: ccx}; + ccx: ccx + }; } -fn new_fn_ctxt(ccx: @crate_ctxt, path: path, llfndecl: ValueRef, - sp: Option) -> fn_ctxt { +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, None, sp); } @@ -1540,11 +1596,11 @@ fn copy_args_to_allocas(fcx: fn_ctxt, } } - bcx = alt::bind_irrefutable_pat(bcx, - args[arg_n].pat, - llarg, - false, - alt::BindArgument); + bcx = _match::bind_irrefutable_pat(bcx, + args[arg_n].pat, + llarg, + false, + _match::BindArgument); fcx.llargs.insert(arg_id, local_mem(llarg)); @@ -1583,10 +1639,13 @@ enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, } // trans_closure: Builds an LLVM function out of a source function. // If the function closes over its environment a closure will be // returned. -fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, - body: ast::blk, llfndecl: ValueRef, +fn trans_closure(ccx: @crate_ctxt, + +path: path, + decl: ast::fn_decl, + body: ast::blk, + llfndecl: ValueRef, ty_self: self_arg, - param_substs: Option, + +param_substs: Option, id: ast::node_id, impl_id: Option, maybe_load_env: fn(fn_ctxt), @@ -1598,7 +1657,8 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // Set up arguments to the function. 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); + let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, + /*bad*/copy decl.inputs); // Set GC for function. if ccx.sess.opts.gc { @@ -1642,12 +1702,12 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, // trans_fn: creates an LLVM function corresponding to a source language // function. fn trans_fn(ccx: @crate_ctxt, - path: path, + +path: path, decl: ast::fn_decl, body: ast::blk, llfndecl: ValueRef, ty_self: self_arg, - param_substs: Option, + +param_substs: Option, id: ast::node_id, impl_id: Option) { let do_time = ccx.sess.trans_stats(); @@ -1656,7 +1716,8 @@ fn trans_fn(ccx: @crate_ctxt, debug!("trans_fn(ty_self=%?)", ty_self); let _icx = ccx.insn_ctxt("trans_fn"); ccx.stats.n_fns += 1; - trans_closure(ccx, path, decl, body, llfndecl, ty_self, + // XXX: Bad copy of `path`. + trans_closure(ccx, copy path, decl, body, llfndecl, ty_self, param_substs, id, impl_id, |fcx| { if ccx.sess.opts.extra_debuginfo { @@ -1676,7 +1737,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, args: ~[ast::variant_arg], disr: int, is_degen: bool, - param_substs: Option, + +param_substs: Option, llfndecl: ValueRef) { let _icx = ccx.insn_ctxt("trans_enum_variant"); // Translate variant arguments to function arguments. @@ -1687,11 +1748,13 @@ fn trans_enum_variant(ccx: @crate_ctxt, ast_util::dummy_sp(), special_idents::arg), id: varg.id}); + // XXX: Bad copy of `param_substs`. 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); + copy param_substs, None); + // XXX: Bad copy. + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args); let ty_param_substs = match param_substs { - Some(substs) => substs.tys, + Some(ref substs) => /*bad*/copy substs.tys, None => ~[] }; let bcx = top_scope_block(fcx, None), lltop = bcx.llbb; @@ -1712,7 +1775,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, let v_id = local_def(variant.node.id); for vec::eachi(args) |i, va| { let lldestptr = GEP_enum(bcx, llblobptr, t_id, v_id, - ty_param_substs, i); + /*bad*/copy ty_param_substs, i); // If this argument to this function is a enum, it'll have come in to // this function as an opaque blob due to the way that type_of() // works. So we have to cast to the destination's view of the type. @@ -1732,7 +1795,7 @@ fn trans_enum_variant(ccx: @crate_ctxt, fn trans_tuple_struct(ccx: @crate_ctxt, fields: ~[@ast::struct_field], ctor_id: ast::node_id, - param_substs: Option, + +param_substs: Option, llfndecl: ValueRef) { let _icx = ccx.insn_ctxt("trans_tuple_struct"); @@ -1750,7 +1813,9 @@ fn trans_tuple_struct(ccx: @crate_ctxt, let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, None, param_substs, None); - let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args); + + // XXX: Bad copy. + let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args); let bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; @@ -1774,11 +1839,14 @@ fn trans_tuple_struct(ccx: @crate_ctxt, finish_fn(fcx, lltop); } -fn trans_struct_dtor(ccx: @crate_ctxt, path: path, - body: ast::blk, dtor_id: ast::node_id, - psubsts: Option, - hash_id: Option, parent_id: ast::def_id) - -> ValueRef { +fn trans_struct_dtor(ccx: @crate_ctxt, + +path: path, + body: ast::blk, + dtor_id: ast::node_id, + +psubsts: Option, + hash_id: Option, + parent_id: ast::def_id) + -> ValueRef { let tcx = ccx.tcx; /* Look up the parent class's def_id */ let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty; @@ -1791,7 +1859,8 @@ fn trans_struct_dtor(ccx: @crate_ctxt, path: path, and returns () */ let lldty = type_of_dtor(ccx, class_ty); - let s = get_dtor_symbol(ccx, path, dtor_id, psubsts); + // XXX: Bad copies. + let s = get_dtor_symbol(ccx, copy path, dtor_id, copy psubsts); /* Register the dtor as a function. It has external linkage */ let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty); @@ -1817,23 +1886,23 @@ fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def, *i += 1; match variant.node.kind { - ast::tuple_variant_kind(args) if args.len() > 0 => { + ast::tuple_variant_kind(ref args) if args.len() > 0 => { let llfn = get_item_val(ccx, variant.node.id); - trans_enum_variant(ccx, id, *variant, args, disr_val, - degen, None, llfn); + trans_enum_variant(ccx, id, *variant, /*bad*/copy *args, + disr_val, degen, None, llfn); } ast::tuple_variant_kind(_) => { // Nothing to do. } ast::struct_variant_kind(struct_def) => { - trans_struct_def(ccx, struct_def, tps, path, + trans_struct_def(ccx, struct_def, /*bad*/copy tps, path, variant.node.id); } ast::enum_variant_kind(ref enum_definition) => { trans_enum_def(ccx, *enum_definition, id, - tps, + /*bad*/copy tps, degen, path, vi, @@ -1850,19 +1919,20 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { // tjc: ? _ => fail ~"trans_item", }; - match item.node { - ast::item_fn(decl, purity, tps, ref body) => { + match /*bad*/copy item.node { + // XXX: Bad copies. + ast::item_fn(copy decl, purity, copy tps, ref body) => { if purity == ast::extern_fn { let llfndecl = get_item_val(ccx, item.id); foreign::trans_foreign_fn(ccx, vec::append( - *path, + /*bad*/copy *path, ~[path_name(item.ident)]), decl, (*body), llfndecl, item.id); } else if tps.is_empty() { let llfndecl = get_item_val(ccx, item.id); trans_fn(ccx, - vec::append(*path, ~[path_name(item.ident)]), + vec::append(/*bad*/copy *path, ~[path_name(item.ident)]), decl, (*body), llfndecl, no_self, None, item.id, None); } else { for vec::each((*body).node.stmts) |stmt| { @@ -1876,26 +1946,27 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { } } ast::item_impl(tps, _, _, ms) => { - meth::trans_impl(ccx, *path, item.ident, ms, tps, None, + meth::trans_impl(ccx, /*bad*/copy *path, item.ident, ms, tps, None, item.id); } ast::item_mod(m) => { trans_mod(ccx, m); } - ast::item_enum(ref enum_definition, tps) => { + ast::item_enum(ref enum_definition, ref tps) => { if tps.len() == 0u { let degen = (*enum_definition).variants.len() == 1u; let vi = ty::enum_variants(ccx.tcx, local_def(item.id)); let mut i = 0; - trans_enum_def(ccx, (*enum_definition), item.id, tps, degen, path, - vi, &mut i); + trans_enum_def(ccx, (*enum_definition), item.id, /*bad*/copy *tps, + degen, path, vi, &mut i); } } ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id), ast::item_foreign_mod(foreign_mod) => { let abi = match attr::foreign_abi(item.attrs) { either::Right(abi_) => abi_, - either::Left(ref msg) => ccx.sess.span_fatal(item.span, (*msg)) + either::Left(ref msg) => ccx.sess.span_fatal(item.span, + /*bad*/copy *msg) }; foreign::trans_foreign_mod(ccx, foreign_mod, abi); } @@ -1914,7 +1985,7 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, if tps.len() == 0u { // Translate the destructor. do option::iter(&struct_def.dtor) |dtor| { - trans_struct_dtor(ccx, *path, dtor.node.body, + trans_struct_dtor(ccx, /*bad*/copy *path, dtor.node.body, dtor.node.id, None, None, local_def(id)); }; @@ -1924,8 +1995,8 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def, // otherwise this is a unit-like struct. Some(ctor_id) if struct_def.fields.len() > 0 => { let llfndecl = get_item_val(ccx, ctor_id); - trans_tuple_struct(ccx, struct_def.fields, ctor_id, None, - llfndecl); + trans_tuple_struct(ccx, /*bad*/copy struct_def.fields, + ctor_id, None, llfndecl); } Some(_) | None => {} } @@ -1949,30 +2020,35 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef { return struct_elt(llpairty, 0u); } -fn register_fn(ccx: @crate_ctxt, sp: span, path: path, - node_id: ast::node_id) -> ValueRef { +fn register_fn(ccx: @crate_ctxt, + sp: span, + +path: path, + node_id: ast::node_id) + -> ValueRef { let t = ty::node_id_to_type(ccx.tcx, node_id); register_fn_full(ccx, sp, path, node_id, t) } -fn register_fn_full(ccx: @crate_ctxt, sp: span, path: path, +fn register_fn_full(ccx: @crate_ctxt, sp: span, +path: path, node_id: ast::node_id, node_type: ty::t) -> ValueRef { let llfty = type_of_fn_from_ty(ccx, node_type); register_fn_fuller(ccx, sp, path, node_id, node_type, lib::llvm::CCallConv, llfty) } -fn register_fn_fuller(ccx: @crate_ctxt, sp: span, path: path, +fn register_fn_fuller(ccx: @crate_ctxt, sp: span, +path: path, node_id: ast::node_id, node_type: ty::t, cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef { - let ps: ~str = mangle_exported_name(ccx, path, node_type); - let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty); - ccx.item_symbols.insert(node_id, ps); - - debug!("register_fn_fuller created fn %s for item %d with path %s", - val_str(ccx.tn, llfn), node_id, + debug!("register_fn_fuller creating fn for item %d with path %s", + node_id, ast_map::path_to_str(path, ccx.sess.parse_sess.interner)); + // XXX: Bad copy. + let ps: ~str = mangle_exported_name(ccx, copy path, node_type); + // XXX: Bad copy. + let llfn: ValueRef = decl_fn(ccx.llmod, copy ps, cc, llfty); + ccx.item_symbols.insert(node_id, ps); + let is_main = is_main_name(path) && !ccx.sess.building_library; if is_main { create_main_wrapper(ccx, sp, llfn); } llfn @@ -2056,7 +2132,7 @@ fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef, fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path { vec::append( - *match ccx.tcx.items.get(i.id) { + /*bad*/copy *match ccx.tcx.items.get(i.id) { ast_map::node_item(_, p) => p, // separate map for paths? _ => fail ~"item_path" @@ -2066,17 +2142,21 @@ fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path { /* If there's already a symbol for the dtor with and substs , return it; otherwise, create one and register it, returning it as well */ -fn get_dtor_symbol(ccx: @crate_ctxt, path: path, id: ast::node_id, - substs: Option) -> ~str { +fn get_dtor_symbol(ccx: @crate_ctxt, + +path: path, + id: ast::node_id, + +substs: Option) + -> ~str { let t = ty::node_id_to_type(ccx.tcx, id); match ccx.item_symbols.find(id) { - Some(ref s) => (*s), + Some(ref s) => (/*bad*/copy *s), None if substs.is_none() => { let s = mangle_exported_name( ccx, vec::append(path, ~[path_name((ccx.names)(~"dtor"))]), t); - ccx.item_symbols.insert(id, s); + // XXX: Bad copy, use `@str`? + ccx.item_symbols.insert(id, copy s); s } None => { @@ -2110,7 +2190,8 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { let mut exprt = false; let val = match ccx.tcx.items.get(id) { ast_map::node_item(i, pth) => { - let my_path = vec::append(*pth, ~[path_name(i.ident)]); + let my_path = vec::append(/*bad*/copy *pth, + ~[path_name(i.ident)]); match i.node { ast::item_const(_, _) => { let typ = ty::node_id_to_type(ccx.tcx, i.id); @@ -2127,7 +2208,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } else { foreign::register_foreign_fn(ccx, i.span, my_path, i.id) }; - set_inline_hint_if_appr(i.attrs, llfn); + set_inline_hint_if_appr(/*bad*/copy i.attrs, llfn); llfn } _ => fail ~"get_item_val: weird result in table" @@ -2155,7 +2236,8 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { match ni.node { ast::foreign_item_fn(*) => { register_fn(ccx, ni.span, - vec::append(*pth, ~[path_name(ni.ident)]), + vec::append(/*bad*/copy *pth, + ~[path_name(ni.ident)]), ni.id) } ast::foreign_item_const(*) => { @@ -2181,7 +2263,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { let lldty = T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(tcx))), T_ptr(type_of(ccx, class_ty))], llvm::LLVMVoidType()); - let s = get_dtor_symbol(ccx, *pt, dt.node.id, None); + let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None); /* Make the declaration for the dtor */ let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty); @@ -2191,10 +2273,10 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { ast_map::node_variant(ref v, enm, pth) => { let llfn; - match (*v).node.kind { + match /*bad*/copy (*v).node.kind { ast::tuple_variant_kind(args) => { assert args.len() != 0u; - let pth = vec::append(*pth, + let pth = vec::append(/*bad*/copy *pth, ~[path_name(enm.ident), path_name((*v).node.name)]); llfn = match enm.node { @@ -2224,7 +2306,7 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { } Some(ctor_id) => { let llfn = register_fn(ccx, struct_item.span, - *struct_path, ctor_id); + /*bad*/copy *struct_path, ctor_id); set_inline_hint(llfn); llfn } @@ -2247,10 +2329,10 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef { fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path, m: @ast::method) -> ValueRef { let mty = ty::node_id_to_type(ccx.tcx, id); - let pth = vec::append(*pth, ~[path_name((ccx.names)(~"meth")), + let pth = vec::append(/*bad*/copy *pth, ~[path_name((ccx.names)(~"meth")), path_name(m.ident)]); let llfn = register_fn_full(ccx, m.span, pth, id, mty); - set_inline_hint_if_appr(m.attrs, llfn); + set_inline_hint_if_appr(/*bad*/copy m.attrs, llfn); llfn } @@ -2264,11 +2346,14 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item) { let mut i = 0; let path = item_path(ccx, it); for vec::each((*enum_definition).variants) |variant| { - let p = vec::append(path, ~[path_name(variant.node.name), - path_name(special_idents::descrim)]); + let p = vec::append(/*bad*/copy path, ~[ + path_name(variant.node.name), + path_name(special_idents::descrim) + ]); let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx)); let disr_val = vi[i].disr_val; - note_unique_llvm_symbol(ccx, s); + // XXX: Bad copy. + note_unique_llvm_symbol(ccx, copy s); let discrim_gvar = str::as_c_str(s, |buf| { llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf) }); @@ -2285,10 +2370,12 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item) { } fn trans_constants(ccx: @crate_ctxt, crate: @ast::crate) { - visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{ - visit_item: |a| trans_constant(ccx, a), - ..*visit::default_simple_visitor() - })); + visit::visit_crate( + *crate, (), + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_item: |a| trans_constant(ccx, a), + ..*visit::default_simple_visitor() + })); } fn vp2i(cx: block, v: ValueRef) -> ValueRef { @@ -2420,6 +2507,12 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { T_fn(~[T_i32(), T_i1()], T_i32())); let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64", T_fn(~[T_i64(), T_i1()], T_i64())); + let bswap16 = decl_cdecl_fn(llmod, ~"llvm.bswap.i16", + T_fn(~[T_i16()], T_i16())); + let bswap32 = decl_cdecl_fn(llmod, ~"llvm.bswap.i32", + T_fn(~[T_i32()], T_i32())); + let bswap64 = decl_cdecl_fn(llmod, ~"llvm.bswap.i64", + T_fn(~[T_i64()], T_i64())); let intrinsics = HashMap(); intrinsics.insert(~"llvm.gcroot", gcroot); @@ -2472,6 +2565,9 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> { intrinsics.insert(~"llvm.cttz.i16", cttz16); intrinsics.insert(~"llvm.cttz.i32", cttz32); intrinsics.insert(~"llvm.cttz.i64", cttz64); + intrinsics.insert(~"llvm.bswap.i16", bswap16); + intrinsics.insert(~"llvm.bswap.i32", bswap32); + intrinsics.insert(~"llvm.bswap.i64", bswap64); return intrinsics; } @@ -2497,92 +2593,6 @@ fn trap(bcx: block) { } } -fn push_rtcall(ccx: @crate_ctxt, name: ~str, did: ast::def_id) { - match ccx.rtcalls.find(name) { - Some(existing_did) if did != existing_did => { - ccx.sess.fatal(fmt!("multiple definitions for runtime call %s", - name)); - } - Some(_) | None => { - ccx.rtcalls.insert(name, did); - } - } -} - -fn gather_local_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) { - visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{ - visit_item: |item| match item.node { - ast::item_fn(*) => { - let attr_metas = attr::attr_metas( - attr::find_attrs_by_name(item.attrs, ~"rt")); - for vec::each(attr_metas) |attr_meta| { - match attr::get_meta_item_list(*attr_meta) { - Some(list) => { - let head = vec::head(list); - let name = attr::get_meta_item_name(head); - push_rtcall(ccx, name, {crate: ast::local_crate, - node: item.id}); - } - None => () - } - } - } - _ => () - }, - ..*visit::default_simple_visitor() - })); -} - -fn gather_external_rtcalls(ccx: @crate_ctxt) { - do cstore::iter_crate_data(ccx.sess.cstore) |_cnum, cmeta| { - let get_crate_data: decoder::GetCrateDataCb = |cnum| { - cstore::get_crate_data(ccx.sess.cstore, cnum) - }; - do decoder::each_path(ccx.sess.intr(), cmeta, get_crate_data) |path| { - let pathname = path.path_string; - match path.def_like { - decoder::dl_def(d) => { - match d { - ast::def_fn(did, _) => { - // FIXME (#2861): This should really iterate attributes - // like gather_local_rtcalls, but we'll need to - // export attributes in metadata/encoder before we can do - // that. - let sentinel = ~"rt::rt_"; - let slen = str::len(sentinel); - if str::starts_with(pathname, sentinel) { - let name = str::substr(pathname, - slen, str::len(pathname)-slen); - push_rtcall(ccx, name, did); - } - } - _ => () - } - } - _ => () - } - true - } - } -} - -fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) { - gather_local_rtcalls(ccx, crate); - gather_external_rtcalls(ccx); - - // FIXME (#2861): Check for other rtcalls too, once they are - // supported. Also probably want to check type signature so we don't crash - // in some obscure place in LLVM if the user provides the wrong signature - // for an rtcall. - let expected_rtcalls = - ~[~"exchange_free", ~"exchange_malloc", ~"fail_", ~"free", ~"malloc"]; - for vec::each(expected_rtcalls) |name| { - if !ccx.rtcalls.contains_key(*name) { - fail fmt!("no definition for runtime call %s", *name); - } - } -} - fn decl_gc_metadata(ccx: @crate_ctxt, llmod_id: ~str) { if !ccx.sess.opts.gc || !ccx.uses_gc { return; @@ -2655,7 +2665,7 @@ fn fill_crate_map(ccx: @crate_ctxt, map: ValueRef) { subcrates.push(C_int(ccx, 0)); let llannihilatefn; - let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn.get(); + let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn(); if annihilate_def_id.crate == ast::local_crate { llannihilatefn = get_item_val(ccx, annihilate_def_id.node); } else { @@ -2674,11 +2684,10 @@ fn fill_crate_map(ccx: @crate_ctxt, map: ValueRef) { C_array(ccx.int_type, subcrates)])); } -fn crate_ctxt_to_encode_parms(cx: @crate_ctxt) - -> encoder::encode_parms { - +fn crate_ctxt_to_encode_parms(cx: @crate_ctxt) -> encoder::encode_parms { + // XXX: Bad copy of `c`, whatever it is. let encode_inlined_item = - |a,b,c,d| astencode::encode_inlined_item(a, b, c, d, cx.maps); + |a,b,c,d| astencode::encode_inlined_item(a, b, copy c, d, cx.maps); return { diag: cx.sess.diagnostic(), @@ -2687,7 +2696,7 @@ fn crate_ctxt_to_encode_parms(cx: @crate_ctxt) reexports2: cx.exp_map2, item_symbols: cx.item_symbols, discrim_symbols: cx.discrim_symbols, - link_meta: cx.link_meta, + link_meta: /*bad*/copy cx.link_meta, cstore: cx.sess.cstore, encode_inlined_item: encode_inlined_item }; @@ -2750,8 +2759,8 @@ fn trans_crate(sess: session::Session, llvm::LLVMModuleCreateWithNameInContext (buf, llvm::LLVMGetGlobalContext()) }); - let data_layout = sess.targ_cfg.target_strs.data_layout; - let targ_triple = sess.targ_cfg.target_strs.target_triple; + let data_layout = /*bad*/copy sess.targ_cfg.target_strs.data_layout; + let targ_triple = /*bad*/copy sess.targ_cfg.target_strs.target_triple; let _: () = str::as_c_str(data_layout, |buf| llvm::LLVMSetDataLayout(llmod, buf)); @@ -2759,7 +2768,8 @@ fn trans_crate(sess: session::Session, str::as_c_str(targ_triple, |buf| llvm::LLVMSetTarget(llmod, buf)); let targ_cfg = sess.targ_cfg; - let td = mk_target_data(sess.targ_cfg.target_strs.data_layout); + let td = mk_target_data( + /*bad*/copy sess.targ_cfg.target_strs.data_layout); let tn = mk_type_names(); let intrinsics = declare_intrinsics(llmod); if sess.opts.extra_debuginfo { @@ -2774,13 +2784,13 @@ fn trans_crate(sess: session::Session, lib::llvm::associate_type(tn, ~"tydesc", tydesc_type); let crate_map = decl_crate_map(sess, link_meta, llmod); let dbg_cx = if sess.opts.debuginfo { - option::Some(debuginfo::mk_ctxt(llmod_id, sess.parse_sess.interner)) + Some(debuginfo::mk_ctxt(copy llmod_id, sess.parse_sess.interner)) } else { - option::None + None }; - let ccx = - @{sess: sess, + let ccx = @crate_ctxt { + sess: sess, llmod: llmod, td: td, tn: tn, @@ -2791,7 +2801,7 @@ fn trans_crate(sess: session::Session, reachable: reachable, item_symbols: HashMap(), mut main_fn: None::, - link_meta: link_meta, + link_meta: copy link_meta, // XXX: Bad copy. enum_sizes: ty::new_ty_hash(), discrims: HashMap(), discrim_symbols: HashMap(), @@ -2827,9 +2837,7 @@ fn trans_crate(sess: session::Session, llvm_insn_ctxt: @mut ~[], llvm_insns: HashMap(), fn_times: @mut ~[]}, - upcalls: - upcall::declare_upcalls(targ_cfg, llmod), - rtcalls: HashMap(), + upcalls: upcall::declare_upcalls(targ_cfg, llmod), tydesc_type: tydesc_type, int_type: int_type, float_type: float_type, @@ -2840,10 +2848,8 @@ fn trans_crate(sess: session::Session, crate_map: crate_map, mut uses_gc: false, dbg_cx: dbg_cx, - mut do_not_commit_warning_issued: false}; - - - gather_rtcalls(ccx, crate); + mut do_not_commit_warning_issued: false + }; { let _icx = ccx.insn_ctxt("data"); diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs index 614a02a970052..98151ff008820 100644 --- a/src/librustc/middle/trans/build.rs +++ b/src/librustc/middle/trans/build.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use codemap::span; use lib::llvm::llvm; use lib::llvm::{CallConv, TypeKind, AtomicBinOp, AtomicOrdering}; @@ -16,6 +17,10 @@ use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef}; use libc::{c_uint, c_int}; use middle::trans::common::*; +use core::cast; +use core::libc; +use core::str; +use core::vec; use std::map::HashMap; use syntax::codemap; @@ -49,8 +54,8 @@ fn count_insn(cx: block, category: &str) { let mut s = ~"."; i = 0u; while i < len { - let e = v[i]; - i = mm.get(e); + let e = /*bad*/copy v[i]; + i = mm.get(/*bad*/ copy e); s += ~"/"; s += e; i += 1u; @@ -658,7 +663,7 @@ fn add_span_comment(bcx: block, sp: span, text: ~str) { if !ccx.sess.no_asm_comments() { let s = text + ~" (" + ccx.sess.codemap.span_to_str(sp) + ~")"; - log(debug, s); + log(debug, copy s); add_comment(bcx, s); } } diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index eb0d86b6d045b..c34b8fd151caa 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -16,12 +16,19 @@ // and methods are represented as just a fn ptr and not a full // closure. + use lib::llvm::ValueRef; use middle::trans::base::{get_item_val, trans_external_path}; use middle::trans::build::*; +use middle::trans::callee; +use middle::trans::closure; use middle::trans::common::{block, node_id_type_params}; use middle::trans::datum::*; use middle::trans::datum::Datum; +use middle::trans::inline; +use middle::trans::meth; +use middle::trans::monomorphize; +use middle::typeck; use util::common::indenter; use syntax::ast; @@ -153,7 +160,7 @@ fn trans_fn_ref(bcx: block, fn trans_fn_ref_with_vtables_to_callee(bcx: block, def_id: ast::def_id, ref_id: ast::node_id, - type_params: ~[ty::t], + +type_params: ~[ty::t], vtables: Option) -> Callee { @@ -166,7 +173,7 @@ fn trans_fn_ref_with_vtables( bcx: block, // def_id: ast::def_id, // def id of fn ref_id: ast::node_id, // node id of use of fn; may be zero if N/A - type_params: ~[ty::t], // values for fn's ty params + +type_params: ~[ty::t], // values for fn's ty params vtables: Option) -> FnData { @@ -327,13 +334,6 @@ fn trans_method_call(in_cx: block, DontAutorefArg) } -fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: expr::Dest) - -> block -{ - let did = bcx.ccx().rtcalls[name]; - return trans_rtcall_or_lang_call(bcx, did, args, dest); -} - fn trans_rtcall_or_lang_call(bcx: block, did: ast::def_id, args: ~[ValueRef], dest: expr::Dest) -> block { let fty = if did.crate == ast::local_crate { @@ -389,7 +389,7 @@ fn trans_rtcall_or_lang_call_with_type_params(bcx: block, fn body_contains_ret(body: ast::blk) -> bool { let cx = {mut found: false}; - visit::visit_block(body, cx, visit::mk_vt(@{ + visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor { visit_item: |_i, _cx, _v| { }, visit_expr: |e: @ast::expr, cx: {mut found: bool}, v| { if !cx.found { @@ -416,7 +416,7 @@ fn trans_call_inner( autoref_arg: AutorefArg) -> block { do base::with_scope(in_cx, call_info, ~"call") |cx| { - let ret_in_loop = match args { + let ret_in_loop = match /*bad*/copy args { ArgExprs(args) => { args.len() > 0u && match vec::last(args).node { ast::expr_loop_body(@{ @@ -460,10 +460,10 @@ fn trans_call_inner( } }; - let args_res = trans_args(bcx, llenv, args, fn_expr_ty, + let args_res = trans_args(bcx, llenv, /*bad*/copy args, fn_expr_ty, dest, ret_flag, autoref_arg); bcx = args_res.bcx; - let mut llargs = args_res.args; + let mut llargs = /*bad*/copy args_res.args; let llretslot = args_res.retslot; @@ -520,8 +520,12 @@ enum CallArgs { ArgVals(~[ValueRef]) } -fn trans_args(cx: block, llenv: ValueRef, args: CallArgs, fn_ty: ty::t, - dest: expr::Dest, ret_flag: Option, +fn trans_args(cx: block, + llenv: ValueRef, + +args: CallArgs, + fn_ty: ty::t, + dest: expr::Dest, + ret_flag: Option, +autoref_arg: AutorefArg) -> {bcx: block, args: ~[ValueRef], retslot: ValueRef} { @@ -615,14 +619,18 @@ fn trans_arg_expr(bcx: block, Some(_) => { match arg_expr.node { ast::expr_loop_body( - blk@@{node:ast::expr_fn_block(decl, ref body, cap), _}) => + // XXX: Bad copy. + blk@@{ + node: ast::expr_fn_block(copy decl, ref body, cap), + _ + }) => { let scratch_ty = expr_ty(bcx, blk); let scratch = alloc_ty(bcx, scratch_ty); let arg_ty = expr_ty(bcx, arg_expr); let proto = ty::ty_fn_proto(arg_ty); let bcx = closure::trans_expr_fn( - bcx, proto, decl, (*body), blk.id, cap, + bcx, proto, decl, /*bad*/copy *body, blk.id, cap, Some(ret_flag), expr::SaveIn(scratch)); DatumBlock {bcx: bcx, datum: Datum {val: scratch, diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 5110bc261f7a9..6a0c2aceda35a 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -8,15 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use back::abi; use back::link::{mangle_internal_name_by_path_and_seq}; use back::link::{mangle_internal_name_by_path}; use lib::llvm::llvm; use lib::llvm::{ValueRef, TypeRef}; +use middle::capture; use middle::trans::base::*; use middle::trans::build::*; +use middle::trans::callee; use middle::trans::common::*; use middle::trans::datum::{Datum, INIT, ByRef, ByValue, FromLvalue}; +use middle::trans::expr; +use middle::trans::glue; use middle::trans::type_of::*; use util::ppaux::ty_to_str; @@ -207,7 +212,8 @@ fn store_environment(bcx: block, let ccx = bcx.ccx(), tcx = ccx.tcx; // compute the shape of the closure - let cdata_ty = mk_closure_tys(tcx, bound_values); + // XXX: Bad copy. + let cdata_ty = mk_closure_tys(tcx, copy bound_values); // allocate closure in the heap let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty); @@ -370,8 +376,8 @@ fn load_environment(fcx: fn_ctxt, fn trans_expr_fn(bcx: block, proto: ast::Proto, - decl: ast::fn_decl, - body: ast::blk, + +decl: ast::fn_decl, + +body: ast::blk, id: ast::node_id, cap_clause: ast::capture_clause, is_loop_body: Option>, @@ -388,19 +394,24 @@ fn trans_expr_fn(bcx: block, let ccx = bcx.ccx(); let fty = node_id_type(bcx, id); let llfnty = type_of_fn_from_ty(ccx, fty); - let sub_path = vec::append_one(bcx.fcx.path, + let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path, path_name(special_idents::anon)); - let s = mangle_internal_name_by_path_and_seq(ccx, sub_path, ~"expr_fn"); + // XXX: Bad copy. + let s = mangle_internal_name_by_path_and_seq(ccx, + copy sub_path, + ~"expr_fn"); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); - let trans_closure_env = fn@(proto: ast::Proto) -> Result { + // XXX: Bad copies. + let trans_closure_env = |proto, copy body, copy sub_path, copy decl| { 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, proto, + // XXX: Bad copy. + let {llbox, cdata_ty, bcx} = build_closure(bcx, copy cap_vars, proto, ret_handle); - trans_closure(ccx, sub_path, decl, body, llfn, no_self, - bcx.fcx.param_substs, id, None, |fcx| { + trans_closure(ccx, /*bad*/copy sub_path, decl, body, llfn, no_self, + /*bad*/copy bcx.fcx.param_substs, id, None, |fcx| { load_environment(fcx, cdata_ty, cap_vars, ret_handle.is_some(), proto); }, |bcx| { @@ -488,11 +499,13 @@ fn make_opaque_cbox_take_glue( let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx))); // Allocate memory, update original ptr, and copy existing data - let malloc = ~"exchange_malloc"; let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8())); let rval = alloca_zeroed(bcx, T_ptr(T_i8())); - let bcx = callee::trans_rtcall(bcx, malloc, ~[opaque_tydesc, sz], - expr::SaveIn(rval)); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, + bcx.tcx().lang_items.exchange_malloc_fn(), + ~[opaque_tydesc, sz], + expr::SaveIn(rval)); let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty); call_memcpy(bcx, cbox_out, cbox_in, sz); Store(bcx, cbox_out, cboxptr); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 25cd169c403f2..ee2028200e413 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -8,36 +8,62 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + /** Code that is useful in various trans modules. */ -use libc::c_uint; -use vec::raw::to_ptr; -use std::map::{HashMap,Set}; -use syntax::{ast, ast_map}; -use driver::session; -use session::Session; -use middle::ty; use back::{link, abi, upcall}; -use syntax::codemap::span; -use lib::llvm::{llvm, target_data, type_names, associate_type, - name_has_type}; +use driver::session; +use driver::session::Session; use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef}; use lib::llvm::{True, False, Bool}; -use metadata::{csearch}; +use lib::llvm::{llvm, target_data, type_names, associate_type, name_has_type}; +use lib; use metadata::common::link_meta; +use metadata::{csearch}; +use middle::astencode; +use middle::resolve; +use middle::trans::base; +use middle::trans::build; +use middle::trans::callee; +use middle::trans::datum; +use middle::trans::debuginfo; +use middle::trans::glue; +use middle::trans::meth; +use middle::trans::reachable; +use middle::trans::shape; +use middle::trans::type_of; +use middle::trans::type_use; +use middle::ty; +use middle::typeck; +use util::ppaux::{expr_repr, ty_to_str}; + +use core::cast; +use core::cmp; +use core::hash; +use core::libc::c_uint; +use core::ptr; +use core::str; +use core::to_bytes; +use core::vec::raw::to_ptr; +use core::vec; +use std::map::{HashMap, Set}; +use syntax::ast::ident; use syntax::ast_map::path; -use util::ppaux::ty_to_str; -use syntax::print::pprust::expr_to_str; +use syntax::codemap::span; use syntax::parse::token::ident_interner; -use syntax::ast::ident; +use syntax::print::pprust::expr_to_str; +use syntax::{ast, ast_map}; type namegen = fn@(~str) -> ident; fn new_namegen(intr: @ident_interner) -> namegen { return fn@(prefix: ~str) -> ident { - return intr.gensym(@fmt!("%s_%u", prefix, intr.gensym(@prefix).repr)) + // XXX: Bad copies. + return intr.gensym(@fmt!("%s_%u", + prefix, + intr.gensym(@copy prefix).repr)) }; } @@ -119,7 +145,7 @@ fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res { } // Crate context. Every crate we compile has one of these. -type crate_ctxt = { +struct crate_ctxt { sess: session::Session, llmod: ModuleRef, td: target_data, @@ -175,7 +201,6 @@ type crate_ctxt = { maps: astencode::maps, stats: stats, upcalls: @upcall::upcalls, - rtcalls: HashMap<~str, ast::def_id>, tydesc_type: TypeRef, int_type: TypeRef, float_type: TypeRef, @@ -189,7 +214,8 @@ type crate_ctxt = { // is not emitted by LLVM's GC pass when no functions use GC. mut uses_gc: bool, dbg_cx: Option, - mut do_not_commit_warning_issued: bool}; + mut do_not_commit_warning_issued: bool +} // Types used for llself. struct ValSelfData { @@ -202,10 +228,12 @@ 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], - self_ty: Option}; +struct param_substs { + tys: ~[ty::t], + vtables: Option, + 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:%?}", @@ -216,7 +244,7 @@ fn param_substs_to_str(tcx: ty::ctxt, substs: ¶m_substs) -> ~str { // Function context. Every LLVM function we create will have one of // these. -type fn_ctxt = @{ +struct fn_ctxt_ { // The ValueRef returned from a call to llvm::LLVMAddFunction; the // address of the first instruction in the sequence of // instructions for this function that will go in the .text @@ -280,7 +308,9 @@ type fn_ctxt = @{ // This function's enclosing crate context. ccx: @crate_ctxt -}; +} + +pub type fn_ctxt = @fn_ctxt_; fn warn_not_to_commit(ccx: @crate_ctxt, msg: ~str) { if !ccx.do_not_commit_warning_issued { @@ -444,7 +474,7 @@ fn revoke_clean(cx: block, val: ValueRef) { fn block_cleanups(bcx: block) -> ~[cleanup] { match bcx.kind { block_non_scope => ~[], - block_scope(ref inf) => (*inf).cleanups + block_scope(ref inf) => /*bad*/copy inf.cleanups } } @@ -462,7 +492,7 @@ enum block_kind { block_non_scope, } -type scope_info = { +struct scope_info { loop_break: Option, loop_label: Option, // A list of functions that must be run at when leaving this @@ -474,7 +504,7 @@ type scope_info = { mut cleanup_paths: ~[cleanup_path], // Unwinding landing pad. Also cleared when cleanups change. mut landing_pad: Option, -}; +} trait get_node_info { fn info() -> Option; @@ -633,7 +663,7 @@ impl block { } fn expr_to_str(e: @ast::expr) -> ~str { - util::ppaux::expr_repr(self.tcx(), e) + expr_repr(self.tcx(), e) } fn expr_is_lval(e: @ast::expr) -> bool { @@ -1051,7 +1081,7 @@ fn C_u8(i: uint) -> ValueRef { return C_integral(T_i8(), i as u64, False); } // This is a 'c-like' raw string, which differs from // our boxed-and-length-annotated strings. -fn C_cstr(cx: @crate_ctxt, s: ~str) -> ValueRef { +fn C_cstr(cx: @crate_ctxt, +s: ~str) -> ValueRef { match cx.const_cstr_cache.find(s) { Some(llval) => return llval, None => () @@ -1072,9 +1102,12 @@ fn C_cstr(cx: @crate_ctxt, s: ~str) -> ValueRef { return g; } -fn C_estr_slice(cx: @crate_ctxt, s: ~str) -> ValueRef { +// NB: Do not use `do_spill_noroot` to make this into a constant string, or +// you will be kicked off fast isel. See issue #4352 for an example of this. +fn C_estr_slice(cx: @crate_ctxt, +s: ~str) -> ValueRef { + let len = str::len(s); let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8())); - C_struct(~[cs, C_uint(cx, str::len(s) + 1u /* +1 for null */)]) + C_struct(~[cs, C_uint(cx, len + 1u /* +1 for null */)]) } // Returns a Plain Old LLVM String: @@ -1121,7 +1154,7 @@ fn C_bytes_plus_null(bytes: ~[u8]) -> ValueRef unsafe { bytes.len() as c_uint, False); } -fn C_shape(ccx: @crate_ctxt, bytes: ~[u8]) -> ValueRef { +fn C_shape(ccx: @crate_ctxt, +bytes: ~[u8]) -> ValueRef { let llshape = C_bytes_plus_null(bytes); let name = fmt!("shape%u", (ccx.names)(~"shape").repr); let llglobal = str::as_c_str(name, |buf| { @@ -1147,29 +1180,30 @@ enum mono_param_id { datum::DatumMode), } -type mono_id_ = { +struct mono_id_ { def: ast::def_id, params: ~[mono_param_id], impl_did_opt: Option -}; +} type mono_id = @mono_id_; impl mono_param_id : cmp::Eq { pure fn eq(&self, other: &mono_param_id) -> bool { - match ((*self), (*other)) { - (mono_precise(ty_a, ids_a), mono_precise(ty_b, ids_b)) => { + match (self, other) { + (&mono_precise(ty_a, ref ids_a), + &mono_precise(ty_b, ref ids_b)) => { ty_a == ty_b && ids_a == ids_b } - (mono_any, mono_any) => true, - (mono_repr(size_a, align_a, is_float_a, mode_a), - mono_repr(size_b, align_b, is_float_b, mode_b)) => { + (&mono_any, &mono_any) => true, + (&mono_repr(size_a, align_a, is_float_a, mode_a), + &mono_repr(size_b, align_b, is_float_b, mode_b)) => { size_a == size_b && align_a == align_b && is_float_a == is_float_b && mode_a == mode_b } - (mono_precise(*), _) => false, - (mono_any, _) => false, - (mono_repr(*), _) => false + (&mono_precise(*), _) => false, + (&mono_any, _) => false, + (&mono_repr(*), _) => false } } pure fn ne(&self, other: &mono_param_id) -> bool { !(*self).eq(other) } @@ -1184,7 +1218,7 @@ impl mono_id_ : cmp::Eq { impl mono_param_id : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - match *self { + match /*bad*/copy *self { mono_precise(t, mids) => to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), &mids, lsb0, f), @@ -1196,7 +1230,7 @@ impl mono_param_id : to_bytes::IterBytes { } } -impl mono_id_ : core::to_bytes::IterBytes { +impl mono_id_ : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f); } @@ -1233,7 +1267,7 @@ fn path_str(sess: session::Session, p: path) -> ~str { } fn monomorphize_type(bcx: block, t: ty::t) -> ty::t { - match bcx.fcx.param_substs { + match /*bad*/copy bcx.fcx.param_substs { Some(substs) => { ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t) } @@ -1254,7 +1288,7 @@ fn expr_ty(bcx: block, ex: @ast::expr) -> ty::t { fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] { let tcx = bcx.tcx(); let params = ty::node_id_to_type_params(tcx, id); - match bcx.fcx.param_substs { + match /*bad*/copy bcx.fcx.param_substs { Some(substs) => { do vec::map(params) |t| { ty::subst_tps(tcx, substs.tys, substs.self_ty, *t) @@ -1278,13 +1312,13 @@ fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res) // Apply the typaram substitutions in the fn_ctxt to a vtable. This should // eliminate any vtable_params. -fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin) +fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, +vt: typeck::vtable_origin) -> typeck::vtable_origin { let tcx = fcx.ccx.tcx; match vt { typeck::vtable_static(trait_id, tys, sub) => { - let tys = match fcx.param_substs { + let tys = match /*bad*/copy fcx.param_substs { Some(substs) => { do vec::map(tys) |t| { ty::subst_tps(tcx, substs.tys, substs.self_ty, *t) @@ -1302,12 +1336,12 @@ fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin) } _ => { tcx.sess.bug(fmt!( - "resolve_vtable_in_fn_ctxt: asked to lookup %? but \ - no vtables in the fn_ctxt!", vt)) + "resolve_vtable_in_fn_ctxt: asked to lookup but \ + no vtables in the fn_ctxt!")) } } } - _ => vt + vt => vt } } @@ -1324,10 +1358,10 @@ fn find_vtable(tcx: ty::ctxt, ps: ¶m_substs, let vtables_to_skip = ty::count_traits_and_supertraits(tcx, first_n_bounds); let vtable_off = vtables_to_skip + n_bound; - ps.vtables.get()[vtable_off] + /*bad*/ copy ps.vtables.get()[vtable_off] } -fn dummy_substs(tps: ~[ty::t]) -> ty::substs { +fn dummy_substs(+tps: ~[ty::t]) -> ty::substs { {self_r: Some(ty::re_bound(ty::br_self)), self_ty: None, tps: tps} diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 355e78014805d..0d698b2871d76 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -8,8 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::const_eval; use middle::trans::base::get_insn_ctxt; use middle::trans::common::*; +use middle::trans::consts; +use middle::trans::expr; +use middle::ty; use syntax::{ast, ast_util, codemap, ast_map}; @@ -32,12 +37,12 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit) ~"integer literal doesn't have a type") } } - ast::lit_float(fs, t) => C_floating(*fs, T_float_ty(cx, t)), + ast::lit_float(fs, t) => C_floating(/*bad*/copy *fs, T_float_ty(cx, t)), ast::lit_float_unsuffixed(fs) => { let lit_float_ty = ty::node_id_to_type(cx.tcx, e.id); match ty::get(lit_float_ty).sty { ty::ty_float(t) => { - C_floating(*fs, T_float_ty(cx, t)) + C_floating(/*bad*/copy *fs, T_float_ty(cx, t)) } _ => { cx.sess.span_bug(lit.span, @@ -48,7 +53,7 @@ fn const_lit(cx: @crate_ctxt, e: @ast::expr, lit: ast::lit) } ast::lit_bool(b) => C_bool(b), ast::lit_nil => C_nil(), - ast::lit_str(s) => C_estr_slice(cx, *s) + ast::lit_str(s) => C_estr_slice(cx, /*bad*/copy *s) } } @@ -125,7 +130,7 @@ fn get_const_val(cx: @crate_ctxt, def_id: ast::def_id) -> ValueRef { fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { let _icx = cx.insn_ctxt("const_expr"); - return match e.node { + return match /*bad*/copy e.node { ast::expr_lit(lit) => consts::const_lit(cx, e, *lit), ast::expr_binary(b, e1, e2) => { let te1 = const_expr(cx, e1); @@ -354,7 +359,7 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { const_expr(cx, e) } ast::expr_vstore(sub, ast::expr_vstore_slice) => { - match sub.node { + match /*bad*/copy sub.node { ast::expr_lit(lit) => { match lit.node { ast::lit_str(*) => { const_expr(cx, sub) } @@ -394,7 +399,6 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { // forbids paths that don't map to C-like enum variants. let ety = ty::expr_ty(cx.tcx, e); let llty = type_of::type_of(cx, ety); - let llstructtys = lib::llvm::struct_element_types(llty); // Can't use `discrims` from the crate context here because // those discriminants have an extra level of indirection, @@ -418,8 +422,14 @@ fn const_expr(cx: @crate_ctxt, e: @ast::expr) -> ValueRef { lldiscrim = found_lldiscrim; } } + let fields = if ty::enum_is_univariant(cx.tcx, enum_did) { + ~[lldiscrim] + } else { + let llstructtys = lib::llvm::struct_element_types(llty); + ~[lldiscrim, C_null(llstructtys[1])] + }; - C_named_struct(llty, ~[ lldiscrim, C_null(llstructtys[1]) ]) + C_named_struct(llty, fields) } Some(ast::def_struct(_)) => { let ety = ty::expr_ty(cx.tcx, e); diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 2a9cece231b73..7ae3fbcd1b8c4 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use lib::llvm::ValueRef; use middle::trans::base::*; +use middle::trans::callee; use middle::trans::common::*; use middle::trans::datum::*; +use core::str; + fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block { @@ -168,13 +172,15 @@ fn trans_log(log_ex: @ast::expr, } let modpath = vec::append( - ~[path_mod(ccx.sess.ident_of(ccx.link_meta.name))], + ~[path_mod(ccx.sess.ident_of(/*bad*/copy ccx.link_meta.name))], vec::filter(bcx.fcx.path, |e| match *e { path_mod(_) => true, _ => false } )); - let modname = path_str(ccx.sess, modpath); + // XXX: Bad copy. + let modname = path_str(ccx.sess, copy modpath); - let global = if ccx.module_data.contains_key(modname) { + // XXX: Bad copy. + let global = if ccx.module_data.contains_key(copy modname) { ccx.module_data.get(modname) } else { let s = link::mangle_internal_name_by_path_and_seq( @@ -205,7 +211,7 @@ fn trans_log(log_ex: @ast::expr, // Call the polymorphic log function let val = val_datum.to_ref_llval(bcx); - let did = bcx.tcx().lang_items.log_type_fn.get(); + let did = bcx.tcx().lang_items.log_type_fn(); let bcx = callee::trans_rtcall_or_lang_call_with_type_params( bcx, did, ~[level, val], ~[val_datum.ty], expr::Ignore); bcx @@ -221,7 +227,11 @@ fn trans_break_cont(bcx: block, opt_label: Option, to_end: bool) let mut target; loop { match unwind.kind { - block_scope({loop_break: Some(brk), loop_label: l, _}) => { + block_scope(scope_info { + loop_break: Some(brk), + loop_label: l, + _ + }) => { // If we're looking for a labeled loop, check the label... target = if to_end { brk @@ -303,7 +313,7 @@ fn trans_check_expr(bcx: block, chk_expr: @ast::expr, } }; do with_cond(bcx, Not(bcx, val)) |bcx| { - trans_fail(bcx, Some(pred_expr.span), expr_str) + trans_fail(bcx, Some(pred_expr.span), /*bad*/copy expr_str) } } @@ -333,7 +343,7 @@ fn trans_fail_expr(bcx: block, } } -fn trans_fail(bcx: block, sp_opt: Option, fail_str: ~str) +fn trans_fail(bcx: block, sp_opt: Option, +fail_str: ~str) -> block { let _icx = bcx.insn_ctxt("trans_fail"); @@ -350,7 +360,7 @@ fn trans_fail_value(bcx: block, sp_opt: Option, V_fail_str: ValueRef) Some(sp) => { let sess = bcx.sess(); let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo); - {V_filename: C_cstr(bcx.ccx(), loc.file.name), + {V_filename: C_cstr(bcx.ccx(), /*bad*/copy loc.file.name), V_line: loc.line as int} } None => { @@ -361,7 +371,8 @@ fn trans_fail_value(bcx: block, sp_opt: Option, V_fail_str: ValueRef) let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8())); let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8())); let args = ~[V_str, V_filename, C_int(ccx, V_line)]; - let bcx = callee::trans_rtcall(bcx, ~"fail_", args, expr::Ignore); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore); Unreachable(bcx); return bcx; } @@ -373,12 +384,12 @@ fn trans_fail_bounds_check(bcx: block, sp: span, let loc = bcx.sess().parse_sess.cm.lookup_char_pos(sp.lo); let line = C_int(ccx, loc.line as int); - let filename_cstr = C_cstr(bcx.ccx(), loc.file.name); + let filename_cstr = C_cstr(bcx.ccx(), /*bad*/copy loc.file.name); let filename = PointerCast(bcx, filename_cstr, T_ptr(T_i8())); let args = ~[filename, line, index, len]; - let bcx = callee::trans_rtcall(bcx, ~"fail_bounds_check", args, - expr::Ignore); + let bcx = callee::trans_rtcall_or_lang_call( + bcx, bcx.tcx().lang_items.fail_bounds_check_fn(), args, expr::Ignore); Unreachable(bcx); return bcx; } diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index e303b3611c577..5c13364ddeb79 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -95,13 +95,23 @@ * methods themselves. Most are only suitable for some types of * values. */ + use lib::llvm::ValueRef; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::common::*; +use middle::trans::common; +use middle::trans::tvec; +use middle::typeck; use util::common::indenter; use util::ppaux::ty_to_str; +use core::cmp; +use core::option; +use core::uint; +use core::vec; +use syntax::parse::token::special_idents; + enum CopyAction { INIT, DROP_EXISTING @@ -669,7 +679,7 @@ impl Datum { // Check whether this struct is a newtype struct. let fields = ty::struct_fields(ccx.tcx, did, substs); if fields.len() != 1 || fields[0].ident != - syntax::parse::token::special_idents::unnamed_field { + special_idents::unnamed_field { return None; } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index b255b47bab30b..10edfb2f92925 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use driver::session; use lib::llvm::ValueRef; use lib::llvm::llvm; @@ -15,9 +16,15 @@ use middle::pat_util::*; use middle::trans::base; use middle::trans::build::B; use middle::trans::common::*; +use middle::trans::shape; +use middle::trans::type_of; +use middle::trans; use middle::ty; use util::ppaux::ty_to_str; +use core::libc; +use core::option; +use core::sys; use std::map::HashMap; use std::map; use syntax::ast::Ty; @@ -101,7 +108,7 @@ type debug_ctxt = { crate_file: ~str }; -fn mk_ctxt(crate: ~str, intr: @ident_interner) -> debug_ctxt { +fn mk_ctxt(+crate: ~str, intr: @ident_interner) -> debug_ctxt { {llmetadata: map::HashMap(), names: new_namegen(intr), crate_file: crate} @@ -175,7 +182,7 @@ fn cached_metadata(cache: metadata_cache, mdtag: int, fn create_compile_unit(cx: @crate_ctxt) -> @metadata unsafe { let cache = get_cache(cx); - let crate_name = cx.dbg_cx.get().crate_file; + let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; let tg = CompileUnitTag; match cached_metadata::<@metadata>(cache, tg, |md| md.data.name == crate_name) { @@ -188,7 +195,7 @@ fn create_compile_unit(cx: @crate_ctxt) let unit_metadata = ~[lltag(tg), llunused(), lli32(DW_LANG_RUST), - llstr(crate_name), + llstr(copy crate_name), llstr(work_dir), llstr(env!("CFG_VERSION")), lli1(true), // deprecated: main compile unit @@ -205,7 +212,7 @@ fn create_compile_unit(cx: @crate_ctxt) } fn get_cache(cx: @crate_ctxt) -> metadata_cache { - cx.dbg_cx.get().llmetadata + (/*bad*/copy cx.dbg_cx).get().llmetadata } fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) { @@ -217,7 +224,7 @@ fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) { }, str::from_slice(work_dir)) } -fn create_file(cx: @crate_ctxt, full_path: ~str) -> @metadata { +fn create_file(cx: @crate_ctxt, +full_path: ~str) -> @metadata { let cache = get_cache(cx);; let tg = FileDescriptorTag; match cached_metadata::<@metadata>( @@ -256,10 +263,10 @@ fn create_block(cx: block) -> @metadata { let sp = cx.node_info.get().span; let start = cx.sess().codemap.lookup_char_pos(sp.lo); - let fname = start.file.name; + let fname = /*bad*/copy start.file.name; let end = cx.sess().codemap.lookup_char_pos(sp.hi); let tg = LexicalBlockTag; - /*alt cached_metadata::<@metadata>( + /*match cached_metadata::<@metadata>( cache, tg, {|md| start == md.data.start && end == md.data.end}) { option::Some(md) { return md; } @@ -359,12 +366,18 @@ type struct_ctxt = { }; fn finish_structure(cx: @struct_ctxt) -> ValueRef { - return create_composite_type(StructureTypeTag, cx.name, cx.file, cx.line, - cx.total_size, cx.align, 0, option::None, - option::Some(cx.members)); -} - -fn create_structure(file: @metadata, name: ~str, line: int) + return create_composite_type(StructureTypeTag, + /*bad*/copy cx.name, + cx.file, + cx.line, + cx.total_size, + cx.align, + 0, + option::None, + option::Some(/*bad*/copy cx.members)); +} + +fn create_structure(file: @metadata, +name: ~str, line: int) -> @struct_ctxt { let cx = @{file: file.node, name: name, @@ -376,7 +389,7 @@ fn create_structure(file: @metadata, name: ~str, line: int) return cx; } -fn create_derived_type(type_tag: int, file: ValueRef, name: ~str, line: int, +fn create_derived_type(type_tag: int, file: ValueRef, +name: ~str, line: int, size: int, align: int, offset: int, ty: ValueRef) -> ValueRef { let lldata = ~[lltag(type_tag), @@ -392,7 +405,7 @@ fn create_derived_type(type_tag: int, file: ValueRef, name: ~str, line: int, return llmdnode(lldata); } -fn add_member(cx: @struct_ctxt, name: ~str, line: int, size: int, align: int, +fn add_member(cx: @struct_ctxt, +name: ~str, line: int, size: int, align: int, ty: ValueRef) { cx.members.push(create_derived_type(MemberTag, cx.file, name, line, size * 8, align * 8, cx.total_size, @@ -406,7 +419,8 @@ fn create_record(cx: @crate_ctxt, t: ty::t, fields: ~[ast::ty_field], let file_node = create_file(cx, fname); let scx = create_structure(file_node, cx.sess.str_of( - (cx.dbg_cx.get().names)(~"rec")), + ((/*bad*/copy cx.dbg_cx).get().names) + (~"rec")), line_from_span(cx.sess.codemap, span) as int); for fields.each |field| { @@ -449,10 +463,10 @@ fn create_boxed_type(cx: @crate_ctxt, outer: ty::t, _inner: ty::t, return mdval; } -fn create_composite_type(type_tag: int, name: ~str, file: ValueRef, line: int, - size: int, align: int, offset: int, +fn create_composite_type(type_tag: int, +name: ~str, file: ValueRef, + line: int, size: int, align: int, offset: int, derived: Option, - members: Option<~[ValueRef]>) + +members: Option<~[ValueRef]>) -> ValueRef { let lldata = ~[lltag(type_tag), file, @@ -608,10 +622,10 @@ fn create_ty(_cx: @crate_ctxt, _t: ty::t, _ty: @ast::Ty) } fn filename_from_span(cx: @crate_ctxt, sp: codemap::span) -> ~str { - cx.sess.codemap.lookup_char_pos(sp.lo).file.name + /*bad*/copy cx.sess.codemap.lookup_char_pos(sp.lo).file.name } -fn create_var(type_tag: int, context: ValueRef, name: ~str, file: ValueRef, +fn create_var(type_tag: int, context: ValueRef, +name: ~str, file: ValueRef, line: int, ret_ty: ValueRef) -> ValueRef { let lldata = ~[lltag(type_tag), context, @@ -643,7 +657,7 @@ fn create_local_var(bcx: block, local: @ast::local) let loc = cx.sess.codemap.lookup_char_pos(local.span.lo); let ty = node_id_type(bcx, local.node.id); let tymd = create_ty(cx, ty, local.node.ty); - let filemd = create_file(cx, loc.file.name); + let filemd = create_file(cx, /*bad*/copy loc.file.name); let context = match bcx.parent { None => create_function(bcx.fcx).node, Some(_) => create_block(bcx).node @@ -687,7 +701,7 @@ fn create_arg(bcx: block, arg: ast::arg, sp: span) let loc = cx.sess.codemap.lookup_char_pos(sp.lo); let ty = node_id_type(bcx, arg.id); let tymd = create_ty(cx, ty, arg.ty); - let filemd = create_file(cx, loc.file.name); + let filemd = create_file(cx, /*bad*/copy loc.file.name); let context = create_function(bcx.fcx); match arg.pat.node { @@ -734,7 +748,7 @@ fn update_source_pos(cx: block, s: span) { fn create_function(fcx: fn_ctxt) -> @metadata { let cx = fcx.ccx; - let dbg_cx = cx.dbg_cx.get(); + let dbg_cx = (/*bad*/copy cx.dbg_cx).get(); debug!("~~"); log(debug, fcx.id); @@ -744,7 +758,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata { let (ident, ret_ty, id) = match cx.tcx.items.get(fcx.id) { ast_map::node_item(item, _) => { - match item.node { + match /*bad*/copy item.node { ast::item_fn(decl, _, _, _) => { (item.ident, decl.output, item.id) } @@ -756,7 +770,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata { (method.ident, method.decl.output, method.id) } ast_map::node_expr(expr) => { - match expr.node { + match /*bad*/copy expr.node { ast::expr_fn(_, decl, _, _) => { ((dbg_cx.names)(~"fn"), decl.output, expr.id) } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 662469655332c..ed9abea465b1b 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -111,11 +111,20 @@ lvalues are *never* stored by value. */ + use lib::llvm::ValueRef; +use middle::resolve; use middle::trans::base::*; use middle::trans::callee::{AutorefArg, DoAutorefArg, DontAutorefArg}; +use middle::trans::callee; +use middle::trans::closure; use middle::trans::common::*; +use middle::trans::consts; +use middle::trans::controlflow; use middle::trans::datum::*; +use middle::trans::machine; +use middle::trans::meth; +use middle::trans::tvec; use middle::ty::MoveValue; use middle::ty::struct_mutable_fields; use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn}; @@ -506,7 +515,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr))); - match expr.node { + // XXX: This copy is really bad. + match /*bad*/copy expr.node { ast::expr_paren(e) => { return trans_rvalue_dps_unadjusted(bcx, e, dest); } @@ -518,7 +528,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, return controlflow::trans_if(bcx, cond, (*thn), els, dest); } ast::expr_match(discr, ref arms) => { - return alt::trans_alt(bcx, expr, discr, (*arms), dest); + return _match::trans_match(bcx, expr, discr, /*bad*/copy *arms, + dest); } ast::expr_block(ref blk) => { return do base::with_scope(bcx, (*blk).info(), @@ -546,13 +557,14 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, ast::expr_vec(*) | ast::expr_repeat(*) => { return tvec::trans_fixed_vstore(bcx, expr, expr, dest); } - ast::expr_fn(proto, decl, ref body, cap_clause) => { + // XXX: Bad copy. + ast::expr_fn(proto, copy decl, ref body, cap_clause) => { // Don't use this function for anything real. Use the one in // astconv instead. - return closure::trans_expr_fn(bcx, proto, decl, *body, expr.id, - cap_clause, None, dest); + return closure::trans_expr_fn(bcx, proto, decl, /*bad*/copy *body, + expr.id, cap_clause, None, dest); } - ast::expr_fn_block(decl, ref body, cap_clause) => { + ast::expr_fn_block(ref decl, ref body, cap_clause) => { let expr_ty = expr_ty(bcx, expr); match ty::get(expr_ty).sty { ty::ty_fn(ref fn_ty) => { @@ -560,7 +572,8 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, expr_to_str(expr, tcx.sess.intr()), ty_to_str(tcx, expr_ty)); return closure::trans_expr_fn( - bcx, fn_ty.meta.proto, decl, *body, expr.id, + bcx, fn_ty.meta.proto, /*bad*/copy *decl, + /*bad*/copy *body, expr.id, cap_clause, None, dest); } _ => { @@ -573,10 +586,16 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr, match ty::get(expr_ty(bcx, expr)).sty { ty::ty_fn(ref fn_ty) => { match blk.node { - ast::expr_fn_block(decl, ref body, cap) => { + ast::expr_fn_block(copy decl, ref body, cap) => { return closure::trans_expr_fn( - bcx, fn_ty.meta.proto, decl, *body, blk.id, - cap, Some(None), dest); + bcx, + fn_ty.meta.proto, + decl, + /*bad*/copy *body, + blk.id, + cap, + Some(None), + dest); } _ => { bcx.sess().impossible_case( diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index e7cdf82fd1516..85aed8d5387d8 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -11,27 +11,33 @@ // 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 back::{link, abi}; use driver::session::arch_x86_64; use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg}; use lib::llvm::{Struct, Array, ModuleRef, CallConv, Attribute}; use lib::llvm::{StructRetAttribute, ByValAttribute}; use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double}; +use lib; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee::*; use middle::trans::common::*; use middle::trans::datum::*; use middle::trans::expr::{Dest, Ignore}; +use middle::trans::glue; +use middle::trans::machine; +use middle::trans::shape; use middle::trans::type_of::*; +use middle::trans::type_of; use middle::ty::{FnTyBase, FnMeta, FnSig}; use util::ppaux::ty_to_str; use core::libc::c_uint; -use std::map::HashMap; use syntax::codemap::span; use syntax::{ast, ast_util}; use syntax::{attr, ast_map}; +use syntax::parse::token::special_idents; export link_name, trans_foreign_mod, register_foreign_fn, trans_foreign_fn, trans_intrinsic; @@ -436,7 +442,7 @@ fn decl_x86_64_fn(tys: x86_64_tys, fn link_name(ccx: @crate_ctxt, i: @ast::foreign_item) -> ~str { match attr::first_attr_value_str_by_name(i.attrs, ~"link_name") { None => ccx.sess.str_of(i.ident), - option::Some(ref ln) => (*ln) + option::Some(ref ln) => (/*bad*/copy *ln) } } @@ -453,7 +459,9 @@ fn c_arg_and_ret_lltys(ccx: @crate_ctxt, id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) { match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty { ty::ty_fn(ref fn_ty) => { - let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs); + let llargtys = type_of_explicit_args( + ccx, + /*bad*/copy fn_ty.sig.inputs); let llretty = type_of::type_of(ccx, fn_ty.sig.output); (llargtys, llretty, fn_ty.sig.output) } @@ -464,7 +472,8 @@ fn c_arg_and_ret_lltys(ccx: @crate_ctxt, fn c_stack_tys(ccx: @crate_ctxt, id: ast::node_id) -> @c_stack_tys { let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, id); - let bundle_ty = T_struct(vec::append_one(llargtys, T_ptr(llretty))); + // XXX: Bad copy. + let bundle_ty = T_struct(vec::append_one(copy llargtys, T_ptr(llretty))); let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); let x86_64 = if ccx.sess.targ_cfg.arch == arch_x86_64 { option::Some(x86_64_tys(llargtys, llretty, ret_def)) @@ -488,7 +497,7 @@ type shim_ret_builder = fn(bcx: block, tys: @c_stack_tys, llargbundle: ValueRef, llretval: ValueRef); fn build_shim_fn_(ccx: @crate_ctxt, - shim_name: ~str, + +shim_name: ~str, llbasefn: ValueRef, tys: @c_stack_tys, cc: lib::llvm::CallConv, @@ -610,8 +619,8 @@ fn trans_foreign_mod(ccx: @crate_ctxt, match tys.x86_64_tys { Some(ref x86_64) => { - let mut atys = (*x86_64).arg_tys; - let mut attrs = (*x86_64).attrs; + let mut atys = /*bad*/copy (*x86_64).arg_tys; + let mut attrs = /*bad*/copy (*x86_64).attrs; if (*x86_64).sret { let llretptr = GEPi(bcx, llargbundle, [0u, n]); let llretloc = Load(bcx, llretptr); @@ -691,24 +700,24 @@ fn trans_foreign_mod(ccx: @crate_ctxt, } let lname = link_name(ccx, foreign_item); - let llbasefn = base_fn(ccx, lname, tys, cc); + let llbasefn = base_fn(ccx, copy lname, tys, cc); // Name the shim function let shim_name = lname + ~"__c_stack_shim"; return build_shim_fn_(ccx, shim_name, llbasefn, tys, cc, build_args, build_ret); } - fn base_fn(ccx: @crate_ctxt, lname: ~str, tys: @c_stack_tys, + fn base_fn(ccx: @crate_ctxt, +lname: ~str, tys: @c_stack_tys, cc: lib::llvm::CallConv) -> ValueRef { // Declare the "prototype" for the base function F: match tys.x86_64_tys { Some(ref x86_64) => { do decl_x86_64_fn((*x86_64)) |fnty| { - decl_fn(ccx.llmod, lname, cc, fnty) + decl_fn(ccx.llmod, /*bad*/copy lname, cc, fnty) } } _ => { - let llbasefnty = T_fn(tys.arg_tys, tys.ret_ty); + let llbasefnty = T_fn(/*bad*/copy tys.arg_tys, tys.ret_ty); decl_fn(ccx.llmod, lname, cc, llbasefnty) } } @@ -781,7 +790,7 @@ fn trans_foreign_mod(ccx: @crate_ctxt, if abi != ast::foreign_abi_rust_intrinsic { let llwrapfn = get_item_val(ccx, id); let tys = c_stack_tys(ccx, id); - if attr::attrs_contains_name(foreign_item.attrs, + if attr::attrs_contains_name(/*bad*/copy foreign_item.attrs, ~"rust_stack") { build_direct_fn(ccx, llwrapfn, *foreign_item, tys, cc); } else { @@ -801,13 +810,14 @@ fn trans_foreign_mod(ccx: @crate_ctxt, } fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, - path: ast_map::path, substs: param_substs, + +path: ast_map::path, +substs: param_substs, ref_id: Option) { debug!("trans_intrinsic(item.ident=%s)", ccx.sess.str_of(item.ident)); + // XXX: Bad copy. let fcx = new_fn_ctxt_w_id(ccx, path, decl, item.id, None, - Some(substs), Some(item.span)); + Some(copy substs), Some(item.span)); let mut bcx = top_scope_block(fcx, None), lltop = bcx.llbb; match ccx.sess.str_of(item.ident) { ~"atomic_cxchg" => { @@ -1012,8 +1022,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, proto: ast::ProtoBorrowed, onceness: ast::Many, region: ty::re_bound(ty::br_anon(0)), - bounds: @~[], - ret_style: ast::return_val}, + bounds: @~[]}, sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), ty: star_u8}], output: ty::mk_nil(bcx.tcx())} @@ -1262,6 +1271,21 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, let cttz = ccx.intrinsics.get(~"llvm.cttz.i64"); Store(bcx, Call(bcx, cttz, ~[x, y]), fcx.llretptr) } + ~"bswap16" => { + let x = get_param(decl, first_real_arg); + let cttz = ccx.intrinsics.get(~"llvm.bswap.i16"); + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + } + ~"bswap32" => { + let x = get_param(decl, first_real_arg); + let cttz = ccx.intrinsics.get(~"llvm.bswap.i32"); + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + } + ~"bswap64" => { + let x = get_param(decl, first_real_arg); + let cttz = ccx.intrinsics.get(~"llvm.bswap.i64"); + Store(bcx, Call(bcx, cttz, ~[x]), fcx.llretptr) + } _ => { // Could we make this an enum rather than a string? does it get // checked earlier? @@ -1272,19 +1296,20 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item, finish_fn(fcx, lltop); } -fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, - body: ast::blk, llwrapfn: ValueRef, id: ast::node_id) { - +fn trans_foreign_fn(ccx: @crate_ctxt, +path: ast_map::path, + decl: ast::fn_decl, body: ast::blk, llwrapfn: ValueRef, + id: ast::node_id) { let _icx = ccx.insn_ctxt("foreign::build_foreign_fn"); - fn build_rust_fn(ccx: @crate_ctxt, path: ast_map::path, + fn build_rust_fn(ccx: @crate_ctxt, +path: ast_map::path, decl: ast::fn_decl, body: ast::blk, id: ast::node_id) -> ValueRef { let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn"); let t = ty::node_id_to_type(ccx.tcx, id); + // XXX: Bad copy. let ps = link::mangle_internal_name_by_path( - ccx, vec::append_one(path, ast_map::path_name( - syntax::parse::token::special_idents::clownshoe_abi + ccx, vec::append_one(copy path, ast_map::path_name( + special_idents::clownshoe_abi ))); let llty = type_of_fn_from_ty(ccx, t); let llfndecl = decl_internal_cdecl_fn(ccx.llmod, ps, llty); @@ -1292,9 +1317,8 @@ fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, return llfndecl; } - fn build_shim_fn(ccx: @crate_ctxt, path: ast_map::path, + fn build_shim_fn(ccx: @crate_ctxt, +path: ast_map::path, llrustfn: ValueRef, tys: @c_stack_tys) -> ValueRef { - let _icx = ccx.insn_ctxt("foreign::foreign::build_shim_fn"); fn build_args(bcx: block, tys: @c_stack_tys, @@ -1323,7 +1347,7 @@ fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, let shim_name = link::mangle_internal_name_by_path( ccx, vec::append_one(path, ast_map::path_name( - syntax::parse::token::special_idents::clownshoe_stack_shim + special_idents::clownshoe_stack_shim ))); return build_shim_fn_(ccx, shim_name, llrustfn, tys, lib::llvm::CCallConv, @@ -1340,8 +1364,8 @@ fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args"); match tys.x86_64_tys { option::Some(ref x86_64) => { - let mut atys = (*x86_64).arg_tys; - let mut attrs = (*x86_64).attrs; + let mut atys = /*bad*/copy (*x86_64).arg_tys; + let mut attrs = /*bad*/copy (*x86_64).attrs; let mut j = 0u; let llretptr = if (*x86_64).sret { atys = vec::tail(atys); @@ -1425,16 +1449,19 @@ fn trans_foreign_fn(ccx: @crate_ctxt, path: ast_map::path, decl: ast::fn_decl, let tys = c_stack_tys(ccx, id); // The internal Rust ABI function - runs on the Rust stack - let llrustfn = build_rust_fn(ccx, path, decl, body, id); + // XXX: Bad copy. + let llrustfn = build_rust_fn(ccx, copy path, decl, body, id); // The internal shim function - runs on the Rust stack let llshimfn = build_shim_fn(ccx, path, llrustfn, tys); // The foreign C function - runs on the C stack build_wrap_fn(ccx, llshimfn, llwrapfn, tys) } -fn register_foreign_fn(ccx: @crate_ctxt, sp: span, - path: ast_map::path, node_id: ast::node_id) - -> ValueRef { +fn register_foreign_fn(ccx: @crate_ctxt, + sp: span, + +path: ast_map::path, + node_id: ast::node_id) + -> ValueRef { let _icx = ccx.insn_ctxt("foreign::register_foreign_fn"); let t = ty::node_id_to_type(ccx.tcx, node_id); let (llargtys, llretty, ret_ty) = c_arg_and_ret_lltys(ccx, node_id); @@ -1442,7 +1469,7 @@ fn register_foreign_fn(ccx: @crate_ctxt, sp: span, let ret_def = !ty::type_is_bot(ret_ty) && !ty::type_is_nil(ret_ty); let x86_64 = x86_64_tys(llargtys, llretty, ret_def); do decl_x86_64_fn(x86_64) |fnty| { - register_fn_fuller(ccx, sp, path, node_id, + register_fn_fuller(ccx, sp, /*bad*/copy path, node_id, t, lib::llvm::CCallConv, fnty) } } else { @@ -1462,7 +1489,9 @@ fn abi_of_foreign_fn(ccx: @crate_ctxt, i: @ast::foreign_item) }, Some(_) => match attr::foreign_abi(i.attrs) { either::Right(abi) => abi, - either::Left(ref msg) => ccx.sess.span_fatal(i.span, (*msg)) + either::Left(ref msg) => { + ccx.sess.span_fatal(i.span, (/*bad*/copy *msg)) + } } } } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index a42dee615e4b5..2ea3873ebcd49 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -12,22 +12,36 @@ // // Code relating to taking, dropping, etc as well as type descriptors. + use lib::llvm::{ValueRef, TypeRef}; use middle::trans::base::*; +use middle::trans::callee; +use middle::trans::closure; use middle::trans::common::*; use middle::trans::build::*; +use middle::trans::reflect; +use middle::trans::tvec; use middle::trans::type_of::type_of; +use middle::trans::uniq; + +use core::io; +use core::str; fn trans_free(cx: block, v: ValueRef) -> block { let _icx = cx.insn_ctxt("trans_free"); - callee::trans_rtcall(cx, ~"free", ~[PointerCast(cx, v, T_ptr(T_i8()))], - expr::Ignore) + callee::trans_rtcall_or_lang_call( + cx, + cx.tcx().lang_items.free_fn(), + ~[PointerCast(cx, v, T_ptr(T_i8()))], + expr::Ignore) } fn trans_unique_free(cx: block, v: ValueRef) -> block { let _icx = cx.insn_ctxt("trans_unique_free"); - callee::trans_rtcall( - cx, ~"exchange_free", ~[PointerCast(cx, v, T_ptr(T_i8()))], + callee::trans_rtcall_or_lang_call( + cx, + cx.tcx().lang_items.exchange_free_fn(), + ~[PointerCast(cx, v, T_ptr(T_i8()))], expr::Ignore) } @@ -434,7 +448,7 @@ fn trans_struct_drop(bcx: block, // Find and call the actual destructor let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, - class_did, substs.tps); + class_did, /*bad*/copy substs.tps); // The second argument is the "self" argument for drop let params = lib::llvm::fn_ty_param_tys( @@ -643,7 +657,8 @@ fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info { } else { mangle_internal_name_by_seq(ccx, ~"tydesc") }; - note_unique_llvm_symbol(ccx, name); + // XXX: Bad copy. + note_unique_llvm_symbol(ccx, copy name); log(debug, fmt!("+++ declare_tydesc %s %s", ty_to_str(ccx.tcx, t), name)); let gvar = str::as_c_str(name, |buf| { llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf) @@ -665,7 +680,7 @@ fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info { type glue_helper = fn@(block, ValueRef, ty::t); fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef, - name: ~str) -> ValueRef { + +name: ~str) -> ValueRef { let _icx = ccx.insn_ctxt("declare_generic_glue"); let name = name; let mut fn_nm; @@ -676,7 +691,8 @@ fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef, fn_nm = mangle_internal_name_by_seq(ccx, (~"glue_" + name)); } debug!("%s is for type %s", fn_nm, ty_to_str(ccx.tcx, t)); - note_unique_llvm_symbol(ccx, fn_nm); + // XXX: Bad copy. + note_unique_llvm_symbol(ccx, copy fn_nm); let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty); set_glue_inlining(llfn, t); return llfn; diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 6f5aa792c4748..28955f49844f0 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::astencode; use middle::trans::base::{get_insn_ctxt}; use middle::trans::base::{impl_owned_self, impl_self, no_self}; use middle::trans::base::{trans_item, get_item_val, self_arg, trans_fn}; use middle::trans::common::*; +use middle::trans::common; +use middle::trans::inline; +use middle::trans::monomorphize; +use core::vec; use syntax::ast; use syntax::ast_map::{path, path_mod, path_name}; use syntax::ast_util::local_def; diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs index 1c6e500d80682..5c7ed2dd0ba8a 100644 --- a/src/librustc/middle/trans/machine.rs +++ b/src/librustc/middle/trans/machine.rs @@ -10,7 +10,12 @@ // Information concerning the machine representation of various types. + use middle::trans::common::*; +use middle::trans::type_of; +use middle::ty; + +use syntax::parse::token::special_idents; // Creates a simpler, size-equivalent type. The resulting type is guaranteed // to have (a) the same size as the type that was passed in; (b) to be non- @@ -39,7 +44,7 @@ pub fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t { ty::ty_struct(did, ref substs) => { let simpl_fields = (if ty::ty_dtor(tcx, did).is_present() { // remember the drop flag - ~[{ident: syntax::parse::token::special_idents::dtor, + ~[{ident: special_idents::dtor, mt: {ty: ty::mk_u8(tcx), mutbl: ast::m_mutbl}}] } else { ~[] }) + @@ -148,8 +153,9 @@ pub fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint { let mut max_size = 0u; let variants = ty::enum_variants(cx.tcx, tid); for vec::each(*variants) |variant| { - let tup_ty = simplify_type(cx.tcx, - ty::mk_tup(cx.tcx, variant.args)); + let tup_ty = simplify_type( + cx.tcx, + ty::mk_tup(cx.tcx, /*bad*/copy variant.args)); // Perform any type parameter substitutions. let tup_ty = ty::subst(cx.tcx, substs, tup_ty); // Here we possibly do a recursive call. diff --git a/src/librustc/middle/trans/macros.rs b/src/librustc/middle/trans/macros.rs index 99175e09af59d..dad4a8bd2bf4b 100644 --- a/src/librustc/middle/trans/macros.rs +++ b/src/librustc/middle/trans/macros.rs @@ -52,4 +52,4 @@ macro_rules! trace( ) ); -} \ No newline at end of file +} diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 1dd3ae0ef0e1b..070a3b667bd33 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -9,16 +9,24 @@ // except according to those terms. use back::{link, abi}; +use driver; use lib::llvm::llvm::LLVMGetParam; use lib::llvm::llvm; use lib::llvm::{ValueRef, TypeRef}; +use lib; use metadata::csearch; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee::*; +use middle::trans::callee; use middle::trans::common::*; use middle::trans::expr::{SaveIn, Ignore}; +use middle::trans::expr; +use middle::trans::glue; +use middle::trans::inline; +use middle::trans::monomorphize; use middle::trans::type_of::*; +use middle::typeck; use util::ppaux::{ty_to_str, tys_to_str}; use core::libc::c_uint; @@ -36,7 +44,7 @@ for non-monomorphized methods only. Other methods will be generated once they are invoked with specific type parameters, see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`. */ -fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, +fn trans_impl(ccx: @crate_ctxt, +path: path, name: ast::ident, methods: ~[@ast::method], tps: ~[ast::ty_param], self_ty: Option, id: ast::node_id) { let _icx = ccx.insn_ctxt("impl::trans_impl"); @@ -45,13 +53,14 @@ fn trans_impl(ccx: @crate_ctxt, path: path, name: ast::ident, for vec::each(methods) |method| { if method.tps.len() == 0u { let llfn = get_item_val(ccx, method.id); - let path = vec::append_one(sub_path, path_name(method.ident)); + let path = vec::append_one(/*bad*/copy sub_path, + path_name(method.ident)); let param_substs_opt; match self_ty { None => param_substs_opt = None, Some(self_ty) => { - param_substs_opt = Some({ + param_substs_opt = Some(param_substs { tys: ~[], vtables: None, bounds: @~[], @@ -82,13 +91,12 @@ Translates a (possibly monomorphized) method body. - `impl_id`: the node ID of the impl this method is inside */ fn trans_method(ccx: @crate_ctxt, - path: path, + +path: path, method: &ast::method, - param_substs: Option, + +param_substs: Option, base_self_ty: Option, llfn: ValueRef, impl_id: ast::def_id) { - // figure out how self is being passed let self_arg = match method.self_ty.node { ast::sty_static => { @@ -104,7 +112,7 @@ fn trans_method(ccx: @crate_ctxt, } let self_ty = match param_substs { None => self_ty, - Some({tys: ref tys, _}) => { + Some(param_substs {tys: ref tys, _}) => { ty::subst_tps(ccx.tcx, *tys, None, self_ty) } }; @@ -281,7 +289,7 @@ fn trans_static_method_callee(bcx: block, let vtbls = resolve_vtables_in_fn_ctxt( bcx.fcx, ccx.maps.vtable_map.get(callee_id)); - match vtbls[bound_index] { + match /*bad*/copy vtbls[bound_index] { typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => { let mth_id = method_with_name(bcx.ccx(), impl_did, mname); @@ -317,8 +325,11 @@ fn method_with_name(ccx: @crate_ctxt, impl_id: ast::def_id, name: ast::ident) -> ast::def_id { if impl_id.crate == ast::local_crate { match ccx.tcx.items.get(impl_id.node) { - ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => { - method_from_methods(ms, name).get() + ast_map::node_item(@{ + node: ast::item_impl(_, _, _, ref ms), + _ + }, _) => { + method_from_methods(/*bad*/copy *ms, name).get() } _ => fail ~"method_with_name" } @@ -331,8 +342,10 @@ fn method_with_name_or_default(ccx: @crate_ctxt, impl_id: ast::def_id, name: ast::ident) -> ast::def_id { if impl_id.crate == ast::local_crate { match ccx.tcx.items.get(impl_id.node) { - ast_map::node_item(@{node: ast::item_impl(_, _, _, ms), _}, _) => { - let did = method_from_methods(ms, name); + ast_map::node_item(@{ + node: ast::item_impl(_, _, _, ref ms), _ + }, _) => { + let did = method_from_methods(/*bad*/copy *ms, name); if did.is_some() { return did.get(); } else { @@ -392,7 +405,7 @@ fn trans_monomorphized_callee(bcx: block, mentry: typeck::method_map_entry, trait_id: ast::def_id, n_method: uint, - vtbl: typeck::vtable_origin) + +vtbl: typeck::vtable_origin) -> Callee { let _icx = bcx.insn_ctxt("impl::trans_monomorphized_callee"); @@ -454,7 +467,7 @@ fn combine_impl_and_methods_tps(bcx: block, mth_did: ast::def_id, impl_did: ast::def_id, callee_id: ast::node_id, - rcvr_substs: ~[ty::t]) + +rcvr_substs: ~[ty::t]) -> ~[ty::t] { /*! @@ -477,12 +490,12 @@ fn combine_impl_and_methods_tps(bcx: block, let ccx = bcx.ccx(); let n_m_tps = method_ty_param_count(ccx, mth_did, impl_did); let node_substs = node_id_type_params(bcx, callee_id); + debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t))); let ty_substs = vec::append(rcvr_substs, vec::tailn(node_substs, node_substs.len() - n_m_tps)); debug!("n_m_tps=%?", n_m_tps); - debug!("rcvr_substs=%?", rcvr_substs.map(|t| bcx.ty_to_str(*t))); debug!("node_substs=%?", node_substs.map(|t| bcx.ty_to_str(*t))); debug!("ty_substs=%?", ty_substs.map(|t| bcx.ty_to_str(*t))); @@ -527,7 +540,7 @@ fn combine_impl_and_methods_origins(bcx: block, let m_origins = vec::tailn(*r_m_origins, r_m_origins.len() - m_vtables); // Combine rcvr + method to find the final result: - @vec::append(*rcvr_origins, m_origins) + @vec::append(/*bad*/copy *rcvr_origins, m_origins) } @@ -698,7 +711,7 @@ fn trans_trait_callee_from_llval(bcx: block, }; } -fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id { +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( @@ -714,18 +727,20 @@ fn vtable_id(ccx: @crate_ctxt, origin: typeck::vtable_origin) -> mono_id { None) } typeck::vtable_trait(trait_id, substs) => { - @{def: trait_id, - params: vec::map(substs, |t| mono_precise(*t, None)), - impl_did_opt: None} + @mono_id_ { + def: trait_id, + params: vec::map(substs, |t| mono_precise(*t, None)), + impl_did_opt: None + } } // can't this be checked at the callee? _ => fail ~"vtable_id" } } -fn get_vtable(ccx: @crate_ctxt, origin: typeck::vtable_origin) - -> ValueRef { - let hash_id = vtable_id(ccx, origin); +fn get_vtable(ccx: @crate_ctxt, +origin: typeck::vtable_origin) -> ValueRef { + // XXX: Bad copy. + let hash_id = vtable_id(ccx, copy origin); match ccx.vtables.find(hash_id) { Some(val) => val, None => match origin { @@ -858,7 +873,7 @@ fn trans_trait_cast(bcx: block, } // Store the vtable into the pair or triple. - let orig = ccx.maps.vtable_map.get(id)[0]; + let orig = /*bad*/copy ccx.maps.vtable_map.get(id)[0]; let orig = resolve_vtable_in_fn_ctxt(bcx.fcx, orig); let vtable = get_vtable(bcx.ccx(), orig); Store(bcx, vtable, PointerCast(bcx, diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 9d662f875510c..ccbced417e245 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -8,16 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use back::link::mangle_exported_name; use middle::trans::base::{get_insn_ctxt}; use middle::trans::base::{set_inline_hint_if_appr, set_inline_hint}; use middle::trans::base::{trans_enum_variant, trans_struct_dtor}; use middle::trans::base::{trans_fn, impl_self, decl_internal_cdecl_fn}; use middle::trans::base::{trans_item, get_item_val, no_self, self_arg}; +use middle::trans::base; use middle::trans::common::*; +use middle::trans::datum; +use middle::trans::foreign; +use middle::trans::machine; +use middle::trans::meth; +use middle::trans::shape; use middle::trans::type_of::type_of_fn_from_ty; +use middle::trans::type_of; +use middle::trans::type_use; use middle::ty::{FnTyBase, FnMeta, FnSig}; +use middle::typeck; +use core::option; +use core::vec; use syntax::ast; use syntax::ast_map::{path, path_mod, path_name}; use syntax::ast_util::local_def; @@ -42,7 +54,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, impl_did_opt, + // XXX: Bad copy. + let hash_id = make_mono_id(ccx, fn_id, copy substs, vtables, impl_did_opt, Some(param_uses)); if vec::any(hash_id.params, |p| match *p { mono_precise(_, _) => false, _ => true }) { @@ -125,7 +138,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_or_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. @@ -135,17 +148,17 @@ fn monomorphic_fn(ccx: @crate_ctxt, } ccx.monomorphizing.insert(fn_id, depth + 1); - let pt = vec::append(*pt, + let pt = vec::append(/*bad*/copy *pt, ~[path_name((ccx.names)(ccx.sess.str_of(name)))]); - let s = mangle_exported_name(ccx, pt, mono_ty); + let s = mangle_exported_name(ccx, /*bad*/copy pt, mono_ty); - let mk_lldecl = || { - let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, llfty); + let mk_lldecl = |/*bad*/copy s| { + let lldecl = decl_internal_cdecl_fn(ccx.llmod, /*bad*/copy s, llfty); ccx.monomorphized.insert(hash_id, lldecl); lldecl }; - let psubsts = Some({ + let psubsts = Some(param_substs { tys: substs, vtables: vtables, bounds: tpt.bounds, @@ -154,11 +167,12 @@ fn monomorphic_fn(ccx: @crate_ctxt, let lldecl = match map_node { ast_map::node_item(i@@{ - node: ast::item_fn(decl, _, _, ref body), + // XXX: Bad copy. + node: ast::item_fn(copy decl, _, _, ref body), _ }, _) => { let d = mk_lldecl(); - set_inline_hint_if_appr(i.attrs, d); + set_inline_hint_if_appr(/*bad*/copy i.attrs, d); trans_fn(ccx, pt, decl, *body, d, no_self, psubsts, fn_id.node, None); d } @@ -178,9 +192,9 @@ fn monomorphic_fn(ccx: @crate_ctxt, let d = mk_lldecl(); set_inline_hint(d); match (*v).node.kind { - ast::tuple_variant_kind(args) => { - trans_enum_variant(ccx, enum_item.id, (*v), args, - this_tv.disr_val, (*tvs).len() == 1u, + ast::tuple_variant_kind(ref args) => { + trans_enum_variant(ccx, enum_item.id, *v, /*bad*/copy *args, + this_tv.disr_val, tvs.len() == 1u, psubsts, d); } ast::struct_variant_kind(_) => @@ -193,7 +207,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, 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); + set_inline_hint_if_appr(/*bad*/copy mth.attrs, d); // Override the impl def ID if necessary. let impl_did; @@ -212,14 +226,14 @@ fn monomorphic_fn(ccx: @crate_ctxt, None => ccx.sess.span_bug(dtor.span, ~"Bad self ty in \ dtor") }; - trans_struct_dtor(ccx, *pt, dtor.node.body, + trans_struct_dtor(ccx, /*bad*/copy *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); + set_inline_hint_if_appr(/*bad*/copy mth.attrs, d); debug!("monomorphic_fn impl_did_opt is %?", impl_did_opt); - meth::trans_method(ccx, *pt, mth, psubsts, None, d, + meth::trans_method(ccx, /*bad*/copy *pt, mth, psubsts, None, d, impl_did_opt.get()); d } @@ -227,7 +241,7 @@ fn monomorphic_fn(ccx: @crate_ctxt, let d = mk_lldecl(); set_inline_hint(d); base::trans_tuple_struct(ccx, - struct_def.fields, + /*bad*/copy struct_def.fields, option::expect(struct_def.ctor_id, ~"ast-mapped tuple struct \ didn't have a ctor id"), @@ -266,8 +280,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option { proto: fty.meta.proto, onceness: ast::Many, region: ty::re_static, - bounds: @~[], - ret_style: ast::return_val}, + bounds: @~[]}, sig: FnSig {inputs: ~[], output: ty::mk_nil(tcx)}})) } @@ -278,8 +291,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> Option { proto: ast::ProtoBox, onceness: ast::Many, region: ty::re_static, - bounds: @~[], - ret_style: ast::return_val}, + bounds: @~[]}, sig: FnSig {inputs: ~[], output: ty::mk_nil(tcx)}})) } @@ -305,7 +317,7 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], for bounds.each |bound| { match *bound { ty::bound_trait(_) => { - v.push(meth::vtable_id(ccx, vts[i])); + v.push(meth::vtable_id(ccx, /*bad*/copy vts[i])); i += 1u; } _ => () @@ -319,15 +331,16 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], } }; let param_ids = match param_uses { - Some(uses) => { - vec::map2(precise_param_ids, uses, |id, uses| { + Some(ref uses) => { + vec::map2(precise_param_ids, *uses, |id, uses| { if ccx.sess.no_monomorphic_collapse() { match *id { (a, b) => mono_precise(a, b) } } else { match *id { - (a, b@Some(_)) => mono_precise(a, b), + // XXX: Bad copy. + (a, copy b@Some(_)) => mono_precise(a, b), (subst, None) => { if *uses == 0u { mono_any @@ -370,5 +383,5 @@ fn make_mono_id(ccx: @crate_ctxt, item: ast::def_id, substs: ~[ty::t], }) } }; - @{def: item, params: param_ids, impl_did_opt: impl_did_opt} + @mono_id_ {def: item, params: param_ids, impl_did_opt: impl_did_opt} } diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index fbaa038b4cc9a..5de7ebadb2b31 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -15,28 +15,40 @@ // makes all other generics or inline functions that it references // reachable as well. + +use driver::session::*; +use middle::resolve; +use middle::ty; +use middle::typeck; + +use core::vec; +use std::map::HashMap; use syntax::ast::*; -use syntax::{visit, ast_util, ast_map}; use syntax::ast_util::def_id_of_def; use syntax::attr; use syntax::print::pprust::expr_to_str; -use std::map::HashMap; -use driver::session::*; +use syntax::{visit, ast_util, ast_map}; export map, find_reachable; -type map = std::map::HashMap; +type map = HashMap; -type ctx = {exp_map2: resolve::ExportMap2, - tcx: ty::ctxt, - method_map: typeck::method_map, - rmap: map}; +struct ctx { + exp_map2: resolve::ExportMap2, + tcx: ty::ctxt, + method_map: typeck::method_map, + rmap: map +} fn find_reachable(crate_mod: _mod, exp_map2: resolve::ExportMap2, tcx: ty::ctxt, method_map: typeck::method_map) -> map { - let rmap = std::map::HashMap(); - let cx = {exp_map2: exp_map2, tcx: tcx, - method_map: method_map, rmap: rmap}; + let rmap = HashMap(); + let cx = ctx { + exp_map2: exp_map2, + tcx: tcx, + method_map: method_map, + rmap: rmap + }; traverse_public_mod(cx, ast::crate_node_id, crate_mod); traverse_all_resources_and_impls(cx, crate_mod); rmap @@ -60,7 +72,7 @@ fn traverse_def_id(cx: ctx, did: def_id) { if did.crate != local_crate { return; } let n = match cx.tcx.items.find(did.node) { None => return, // This can happen for self, for example - Some(ref n) => (*n) + Some(ref n) => (/*bad*/copy *n) }; match n { ast_map::node_item(item, _) => traverse_public_item(cx, item), @@ -87,7 +99,7 @@ fn traverse_public_mod(cx: ctx, mod_id: node_id, m: _mod) { fn traverse_public_item(cx: ctx, item: @item) { if cx.rmap.contains_key(item.id) { return; } cx.rmap.insert(item.id, ()); - match item.node { + match /*bad*/copy item.node { item_mod(m) => traverse_public_mod(cx, item.id, m), item_foreign_mod(nm) => { if !traverse_exports(cx, item.id) { @@ -96,7 +108,7 @@ fn traverse_public_item(cx: ctx, item: @item) { } } } - item_fn(_, _, tps, ref blk) => { + item_fn(_, _, ref tps, ref blk) => { if tps.len() > 0u || attr::find_inline_attr(item.attrs) != attr::ia_none { traverse_inline_body(cx, (*blk)); @@ -130,7 +142,8 @@ fn traverse_public_item(cx: ctx, item: @item) { } fn mk_ty_visitor() -> visit::vt { - visit::mk_vt(@{visit_ty: traverse_ty, ..*visit::default_visitor()}) + visit::mk_vt(@visit::Visitor {visit_ty: traverse_ty, + ..*visit::default_visitor()}) } fn traverse_ty(ty: @Ty, cx: ctx, v: visit::vt) { @@ -197,7 +210,7 @@ fn traverse_inline_body(cx: ctx, body: blk) { fn traverse_item(i: @item, cx: ctx, _v: visit::vt) { traverse_public_item(cx, i); } - visit::visit_block(body, cx, visit::mk_vt(@{ + visit::visit_block(body, cx, visit::mk_vt(@visit::Visitor { visit_expr: traverse_expr, visit_item: traverse_item, ..*visit::default_visitor() @@ -205,21 +218,23 @@ fn traverse_inline_body(cx: ctx, body: blk) { } fn traverse_all_resources_and_impls(cx: ctx, crate_mod: _mod) { - visit::visit_mod(crate_mod, ast_util::dummy_sp(), 0, cx, visit::mk_vt(@{ - visit_expr: |_e, _cx, _v| { }, - visit_item: |i, cx, v| { - visit::visit_item(i, cx, v); - match i.node { - item_struct(struct_def, _) if struct_def.dtor.is_some() => { - traverse_public_item(cx, i); - } - item_impl(*) => { - traverse_public_item(cx, i); - } - _ => () - } - }, - ..*visit::default_visitor() - })); + visit::visit_mod( + crate_mod, ast_util::dummy_sp(), 0, cx, + visit::mk_vt(@visit::Visitor { + visit_expr: |_e, _cx, _v| { }, + visit_item: |i, cx, v| { + visit::visit_item(i, cx, v); + match i.node { + item_struct(sdef, _) if sdef.dtor.is_some() => { + traverse_public_item(cx, i); + } + item_impl(*) => { + traverse_public_item(cx, i); + } + _ => () + } + }, + ..*visit::default_visitor() + })); } diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index d15a9c101b955..39ab5735dee3f 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -8,14 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use back::abi; use lib::llvm::{TypeRef, ValueRef}; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee::{ArgVals, DontAutorefArg}; +use middle::trans::callee; use middle::trans::common::*; use middle::trans::datum::*; use middle::trans::expr::SaveIn; +use middle::trans::glue; +use middle::trans::meth; +use middle::trans::shape; use middle::trans::type_of::*; use util::ppaux::ty_to_str; @@ -41,9 +46,18 @@ impl reflector { C_int(self.bcx.ccx(), i) } - fn c_slice(s: ~str) -> ValueRef { - let ss = C_estr_slice(self.bcx.ccx(), s); - do_spill_noroot(self.bcx, ss) + fn c_slice(+s: ~str) -> ValueRef { + // We're careful to not use first class aggregates here because that + // will kick us off fast isel. (Issue #4352.) + let bcx = self.bcx; + let str_vstore = ty::vstore_slice(ty::re_static); + let str_ty = ty::mk_estr(bcx.tcx(), str_vstore); + let scratch = scratch_datum(bcx, str_ty, false); + let len = C_uint(bcx.ccx(), s.len() + 1); + let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), T_ptr(T_i8())); + Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ])); + Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ])); + scratch.val } fn c_size_and_align(t: ty::t) -> ~[ValueRef] { @@ -72,7 +86,9 @@ impl reflector { tcx.sess.ident_of(~"visit_" + ty_name), *self.visitor_methods).expect(fmt!("Couldn't find visit method \ for %s", ty_name)); - let mth_ty = ty::mk_fn(tcx, self.visitor_methods[mth_idx].fty); + let mth_ty = ty::mk_fn( + tcx, + /*bad*/copy self.visitor_methods[mth_idx].fty); let v = self.visitor_val; debug!("passing %u args:", vec::len(args)); let bcx = self.bcx; @@ -97,16 +113,17 @@ impl reflector { self.bcx = next_bcx } - fn bracketed(bracket_name: ~str, extra: ~[ValueRef], + fn bracketed(bracket_name: ~str, +extra: ~[ValueRef], inner: fn()) { - self.visit(~"enter_" + bracket_name, extra); + // XXX: Bad copy. + self.visit(~"enter_" + bracket_name, copy extra); inner(); self.visit(~"leave_" + bracket_name, extra); } fn vstore_name_and_extra(t: ty::t, vstore: ty::vstore, - f: fn(~str,~[ValueRef])) { + f: fn(+s: ~str,+v: ~[ValueRef])) { match vstore { ty::vstore_fixed(n) => { let extra = vec::append(~[self.c_uint(n)], @@ -119,7 +136,7 @@ impl reflector { } } - fn leaf(name: ~str) { + fn leaf(+name: ~str) { self.visit(name, ~[]); } @@ -130,7 +147,7 @@ impl reflector { debug!("reflect::visit_ty %s", ty_to_str(bcx.ccx().tcx, t)); - match ty::get(t).sty { + match /*bad*/copy ty::get(t).sty { ty::ty_bot => self.leaf(~"bot"), ty::ty_nil => self.leaf(~"nil"), ty::ty_bool => self.leaf(~"bool"), @@ -202,15 +219,12 @@ impl reflector { ast::extern_fn => 3u }; let protoval = ast_proto_constant(fty.meta.proto); - let retval = match fty.meta.ret_style { - ast::noreturn => 0u, - ast::return_val => 1u - }; + let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; let extra = ~[self.c_uint(pureval), self.c_uint(protoval), self.c_uint(vec::len(fty.sig.inputs)), self.c_uint(retval)]; - self.visit(~"enter_fn", extra); + self.visit(~"enter_fn", copy extra); // XXX: Bad copy. for fty.sig.inputs.eachi |i, arg| { let modeval = match arg.mode { ast::infer(_) => 0u, diff --git a/src/librustc/middle/trans/shape.rs b/src/librustc/middle/trans/shape.rs index 51c3cb9362f39..9f107997a6554 100644 --- a/src/librustc/middle/trans/shape.rs +++ b/src/librustc/middle/trans/shape.rs @@ -11,18 +11,21 @@ // A "shape" is a compact encoding of a type that is used by interpreted glue. // This substitutes for the runtime tags used by e.g. MLs. + use back::abi; use lib::llvm::llvm; use lib::llvm::{True, False, ModuleRef, TypeRef, ValueRef}; use middle::trans::base; use middle::trans::common::*; use middle::trans::machine::*; +use middle::trans; use middle::ty::field; use middle::ty; use util::ppaux::ty_to_str; use core::dvec::DVec; use core::option::is_some; +use core::vec; use std::map::HashMap; use syntax::ast; use syntax::ast_util::dummy_sp; @@ -36,13 +39,13 @@ type ctxt = {mut next_tag_id: u16, pad: u16, pad2: u32}; fn mk_global(ccx: @crate_ctxt, name: ~str, llval: ValueRef, internal: bool) -> ValueRef { let llglobal = do str::as_c_str(name) |buf| { - lib::llvm::llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf) + llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf) }; - lib::llvm::llvm::LLVMSetInitializer(llglobal, llval); - lib::llvm::llvm::LLVMSetGlobalConstant(llglobal, True); + llvm::LLVMSetInitializer(llglobal, llval); + llvm::LLVMSetGlobalConstant(llglobal, True); if internal { - lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage); + ::lib::llvm::SetLinkage(llglobal, ::lib::llvm::InternalLinkage); } return llglobal; @@ -51,7 +54,7 @@ fn mk_global(ccx: @crate_ctxt, name: ~str, llval: ValueRef, internal: bool) -> fn mk_ctxt(llmod: ModuleRef) -> ctxt { let llshapetablesty = trans::common::T_named_struct(~"shapes"); let _llshapetables = str::as_c_str(~"shapes", |buf| { - lib::llvm::llvm::LLVMAddGlobal(llmod, llshapetablesty, buf) + llvm::LLVMAddGlobal(llmod, llshapetablesty, buf) }); return {mut next_tag_id: 0u16, pad: 0u16, pad2: 0u32}; diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 2eaf15818d89f..ee44c80943bb9 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -8,13 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use back::abi; use lib::llvm::{ValueRef, TypeRef}; use middle::trans::build::*; use middle::trans::common::*; use middle::trans::datum::*; use middle::trans::expr::{Dest, Ignore, SaveIn}; +use middle::trans::expr; +use middle::trans::glue; use middle::trans::shape::llsize_of; +use middle::trans::type_of; +use middle::ty; use util::common::indenter; use util::ppaux::ty_to_str; @@ -253,7 +258,7 @@ fn trans_lit_str(bcx: block, SaveIn(lldest) => { let bytes = lit_str.len() + 1; // count null-terminator too let llbytes = C_uint(bcx.ccx(), bytes); - let llcstr = C_cstr(bcx.ccx(), *lit_str); + let llcstr = C_cstr(bcx.ccx(), /*bad*/copy *lit_str); let llcstr = llvm::LLVMConstPointerCast(llcstr, T_ptr(T_i8())); Store(bcx, llcstr, GEPi(bcx, lldest, [0u, abi::slice_elt_base])); Store(bcx, llbytes, GEPi(bcx, lldest, [0u, abi::slice_elt_len])); @@ -310,7 +315,7 @@ fn write_content(bcx: block, bcx.expr_to_str(vstore_expr)); let _indenter = indenter(); - match content_expr.node { + match /*bad*/copy content_expr.node { ast::expr_lit(@{node: ast::lit_str(s), span: _}) => { match dest { Ignore => { @@ -319,7 +324,7 @@ fn write_content(bcx: block, SaveIn(lldest) => { let bytes = s.len() + 1; // copy null-terminator too let llbytes = C_uint(bcx.ccx(), bytes); - let llcstr = C_cstr(bcx.ccx(), *s); + let llcstr = C_cstr(bcx.ccx(), /*bad*/copy *s); base::call_memcpy(bcx, lldest, llcstr, llbytes); return bcx; } @@ -416,7 +421,7 @@ fn vec_types(bcx: block, vec_ty: ty::t) -> VecTypes { fn elements_required(bcx: block, content_expr: @ast::expr) -> uint { //! Figure out the number of elements we need to store this content - match content_expr.node { + match /*bad*/copy content_expr.node { ast::expr_lit(@{node: ast::lit_str(s), span: _}) => s.len() + 1, ast::expr_vec(es, _) => es.len(), ast::expr_repeat(_, count_expr, _) => { diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index f146d556a9d9a..9f413a65332a8 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use lib::llvm::llvm; use lib::llvm::{TypeRef}; use middle::trans::common::*; +use middle::trans::common; +use middle::trans::expr; +use util::ppaux; use std::map::HashMap; use syntax::ast; @@ -104,7 +108,8 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { return llty; } - let llty = match ty::get(t).sty { + // XXX: This is a terrible terrible copy. + let llty = match /*bad*/copy ty::get(t).sty { ty::ty_nil | ty::ty_bot => T_nil(), ty::ty_bool => T_bool(), ty::ty_int(t) => T_int_ty(cx, t), @@ -119,7 +124,10 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { // avoids creating more than one copy of the enum when one // of the enum's variants refers to the enum itself. - common::T_named_struct(llvm_type_name(cx, an_enum, did, substs.tps)) + common::T_named_struct(llvm_type_name(cx, + an_enum, + did, + /*bad*/copy substs.tps)) } ty::ty_estr(ty::vstore_box) => { T_box_ptr(T_box(cx, T_vec(cx, T_i8()))) @@ -184,7 +192,10 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { // in *after* placing it into the type cache. This prevents // infinite recursion with recursive struct types. - common::T_named_struct(llvm_type_name(cx, a_struct, did, substs.tps)) + common::T_named_struct(llvm_type_name(cx, + a_struct, + did, + /*bad*/ copy substs.tps)) } ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"), ty::ty_infer(*) => cx.tcx.sess.bug(~"type_of with ty_infer"), @@ -227,7 +238,7 @@ fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t, debug!("type_of_enum %?: %?", t, ty::get(t)); let lltys = { - let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u; + let degen = ty::enum_is_univariant(cx.tcx, did); let size = shape::static_size_of_enum(cx, t); if !degen { ~[T_enum_discrim(cx), T_array(T_i8(), size)] @@ -258,7 +269,7 @@ fn llvm_type_name(cx: @crate_ctxt, return fmt!( "%s %s[#%d]", name, - util::ppaux::parameterized( + ppaux::parameterized( cx.tcx, ty::item_path_str(cx.tcx, did), None, diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 7f3b78359fec4..e17a9c8c0ede7 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -27,9 +27,15 @@ // much information, but have the disadvantage of being very // invasive.) + use metadata::csearch; +use middle::freevars; use middle::trans::common::*; +use middle::trans::inline; +use core::option; +use core::uint; +use core::vec; use std::list::{List, Cons, Nil}; use std::list; use std::map::HashMap; @@ -79,11 +85,11 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) if fn_id_loc.crate != local_crate { let uses = vec::from_mut(copy cx.uses); - ccx.type_use_cache.insert(fn_id, uses); + ccx.type_use_cache.insert(fn_id, copy uses); return uses; } let map_node = match ccx.tcx.items.find(fn_id_loc.node) { - Some(ref x) => (*x), + Some(ref x) => (/*bad*/copy *x), None => ccx.sess.bug(fmt!("type_uses_for: unbound item ID %?", fn_id_loc)) }; @@ -135,6 +141,8 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) ~"ctlz8" | ~"ctlz16" | ~"ctlz32" | ~"ctlz64" => 0, ~"cttz8" | ~"cttz16" | ~"cttz32" | ~"cttz64" => 0, + ~"bswap16" | ~"bswap32" | ~"bswap64" => 0, + // would be cool to make these an enum instead of strings! _ => fail ~"unknown intrinsic in type_use" }; @@ -158,7 +166,8 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint) } } let uses = vec::from_mut(copy cx.uses); - ccx.type_use_cache.insert(fn_id, uses); + // XXX: Bad copy, use @vec instead? + ccx.type_use_cache.insert(fn_id, copy uses); uses } @@ -331,7 +340,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { } fn handle_body(cx: ctx, body: blk) { - let v = visit::mk_vt(@{ + let v = visit::mk_vt(@visit::Visitor { visit_expr: |e, cx, v| { visit::visit_expr(e, cx, v); mark_for_expr(cx, e); diff --git a/src/librustc/middle/trans/uniq.rs b/src/librustc/middle/trans/uniq.rs index 30d47d60e5892..58853224891d8 100644 --- a/src/librustc/middle/trans/uniq.rs +++ b/src/librustc/middle/trans/uniq.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use back; use lib::llvm::ValueRef; use middle::trans::base::*; use middle::trans::build::*; use middle::trans::common::*; use middle::trans::datum::immediate_rvalue; +use middle::trans::datum; +use middle::trans::glue; use syntax::ast; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index dc2632156466c..7c6df9eadf934 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -10,31 +10,50 @@ #[warn(deprecated_pattern)]; -use core::dvec::DVec; -use std::{map, smallintmap}; -use result::Result; -use std::map::HashMap; use driver::session; -use session::Session; -use syntax::{ast, ast_map}; -use syntax::ast_util; -use syntax::ast_util::{is_local, local_def}; -use syntax::codemap::span; use metadata::csearch; -use util::ppaux::{region_to_str, explain_region, vstore_to_str, - note_and_explain_region, bound_region_to_str}; -use middle::lint; +use metadata; +use middle::const_eval; +use middle::freevars; 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 middle::lint; use middle::resolve::{Impl, MethodInfo}; +use middle::resolve; +use middle::ty; +use middle::typeck; +use middle; +use session::Session; +use util::ppaux::{note_and_explain_region, bound_region_to_str}; +use util::ppaux::{region_to_str, explain_region, vstore_to_str}; +use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str}; + +use core::cast; +use core::cmp; +use core::dvec::DVec; +use core::dvec; +use core::ops; +use core::option; +use core::ptr::to_unsafe_ptr; +use core::result::Result; +use core::result; +use core::to_bytes; +use core::uint; +use core::vec; +use std::map::HashMap; +use std::{map, smallintmap}; +use syntax::ast::*; +use syntax::ast_util::{is_local, local_def}; +use syntax::ast_util; +use syntax::codemap::span; +use syntax::print::pprust; +use syntax::{ast, ast_map}; +use syntax; export ProvidedMethodSource; export ProvidedMethodInfo; export ProvidedMethodsMap; export InstantiatedTraitRef; -export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid; +export TyVid, IntVid, FloatVid, FnVid, RegionVid, Vid; export br_hashmap; export is_instantiable; export node_id_to_type; @@ -53,7 +72,7 @@ export expr_ty_params_and_ty; export expr_is_lval, expr_kind; export ExprKind, LvalueExpr, RvalueDatumExpr, RvalueDpsExpr, RvalueStmtExpr; export field_ty; -export fold_ty, fold_sty_to_ty, fold_region, fold_regions; +export fold_ty, fold_sty_to_ty, fold_region, fold_regions, fold_sig; export apply_op_on_t_to_ty_fn; export fold_regions_and_ty, walk_regions_and_ty; export field; @@ -97,7 +116,8 @@ export ty_opaque_closure_ptr, mk_opaque_closure_ptr; export ty_opaque_box, mk_opaque_box; export ty_float, mk_float, mk_mach_float, type_is_fp; export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn; -export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty; +export ty_fn_proto, ty_fn_purity, ty_fn_ret, tys_in_fn_sig; +export replace_fn_return_type; export ty_int, mk_int, mk_mach_int, mk_char; export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64; export mk_f32, mk_f64; @@ -118,7 +138,8 @@ export ty_tup, mk_tup; export ty_type, mk_type; export ty_uint, mk_uint, mk_mach_uint; export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box; -export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var, mk_float_var; +export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var; +export mk_float_var; export InferTy, TyVar, IntVar, FloatVar; export ValueMode, ReadValue, CopyValue, MoveValue; export ty_self, mk_self, type_has_self; @@ -126,7 +147,7 @@ export ty_struct; export Region, bound_region, encl_region; export re_bound, re_free, re_scope, re_static, re_infer; export ReVar, ReSkolemized; -export br_self, br_anon, br_named, br_cap_avoid; +export br_self, br_anon, br_named, br_cap_avoid, br_fresh; export get, type_has_params, type_needs_infer, type_has_regions; export type_is_region_ptr; export type_id; @@ -144,10 +165,11 @@ export kind_is_durable; export meta_kind, kind_lteq, type_kind, type_kind_ext; export operators; export type_err, terr_vstore_kind; -export terr_mismatch, terr_onceness_mismatch; +export terr_integer_as_char, terr_mismatch, terr_onceness_mismatch; export type_err_to_str, note_and_explain_type_err; export expected_found; export type_needs_drop; +export type_is_char; export type_is_empty; export type_is_integral; export type_is_numeric; @@ -199,9 +221,7 @@ export terr_regions_not_same, terr_regions_no_overlap; export terr_regions_insufficiently_polymorphic; export terr_regions_overly_polymorphic; export terr_proto_mismatch; -export terr_ret_style_mismatch; export terr_fn, terr_trait; -export purity_to_str; export onceness_to_str; export param_tys_in_type; export eval_repeat_count; @@ -285,18 +305,22 @@ impl creader_cache_key : to_bytes::IterBytes { } } -type intern_key = {sty: sty, o_def_id: Option}; +type intern_key = {sty: *sty, o_def_id: Option}; impl intern_key : cmp::Eq { pure fn eq(&self, other: &intern_key) -> bool { - (*self).sty == (*other).sty && (*self).o_def_id == (*other).o_def_id + unsafe { + *self.sty == *other.sty && self.o_def_id == other.o_def_id + } } pure fn ne(&self, other: &intern_key) -> bool { !(*self).eq(other) } } impl intern_key : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_2(&self.sty, &self.o_def_id, lsb0, f); + unsafe { + to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f); + } } } @@ -493,15 +517,14 @@ pure fn type_id(t: t) -> uint { get(t).id } * - `onceness` indicates whether the function can be called one time or many * times. * - `region` is the region bound on the function's upvars (often &static). - * - `bounds` is the parameter bounds on the function's upvars. - * - `ret_style` indicates whether the function returns a value or fails. */ + * - `bounds` is the parameter bounds on the function's upvars. */ +#[deriving_eq] struct FnMeta { purity: ast::purity, proto: ast::Proto, onceness: ast::Onceness, region: Region, - bounds: @~[param_bound], - ret_style: ret_style + bounds: @~[param_bound] } /** @@ -510,6 +533,7 @@ struct FnMeta { * * - `inputs` is the list of arguments and their modes. * - `output` is the return type. */ +#[deriving_eq] struct FnSig { inputs: ~[arg], output: t @@ -520,9 +544,16 @@ struct FnSig { * type signature. This particular type is parameterized * by the meta information because, in some cases, the * meta information is inferred. */ +#[deriving_eq] struct FnTyBase { - meta: M, - sig: FnSig + meta: M, // Either FnMeta or FnVid + sig: FnSig // Types of arguments/return type +} + +impl FnTyBase : to_bytes::IterBytes { + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_2(&self.meta, &self.sig, lsb0, f) + } } type FnTy = FnTyBase; @@ -585,6 +616,9 @@ enum bound_region { /// Named region parameters for functions (a in &a/T) br_named(ast::ident), + /// Fresh bound identifiers created during GLB computations. + br_fresh(uint), + /** * Handles capture-avoiding substitution in a rather subtle case. If you * have a closure whose argument types are being inferred based on the @@ -647,7 +681,7 @@ enum sty { ty_param(param_ty), // type parameter ty_self, // special, implicit `self` type parameter - ty_infer(InferTy), // soething used only during inference/typeck + ty_infer(InferTy), // something used only during inference/typeck ty_err, // Also only used during inference/typeck, to represent // the type of an erroneous expression (helps cut down // on non-useful type error messages) @@ -671,7 +705,6 @@ struct expected_found { // Data structures used in type unification enum type_err { terr_mismatch, - terr_ret_style_mismatch(expected_found), terr_purity_mismatch(expected_found), terr_onceness_mismatch(expected_found), terr_mutability, @@ -696,6 +729,7 @@ enum type_err { terr_in_field(@type_err, ast::ident), terr_sorts(expected_found), terr_self_substs, + terr_integer_as_char, terr_no_integral_type, terr_no_floating_point_type, } @@ -716,6 +750,7 @@ enum FnVid = uint; #[auto_decode] enum RegionVid = uint; +#[deriving_eq] enum InferTy { TyVar(TyVid), IntVar(IntVid), @@ -727,7 +762,7 @@ impl InferTy : to_bytes::IterBytes { match *self { TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f), IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f), - FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f) + FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f), } } } @@ -778,61 +813,64 @@ impl param_bound : to_bytes::IterBytes { } } -trait vid { +trait Vid { pure fn to_uint() -> uint; - pure fn to_str() -> ~str; } -impl TyVid: vid { +impl TyVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl TyVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl IntVid: vid { +impl IntVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl IntVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl FloatVid: vid { +impl FloatVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl FloatVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl FnVid: vid { +impl FnVid: Vid { pure fn to_uint() -> uint { *self } +} + +impl FnVid: ToStr { pure fn to_str() -> ~str { fmt!("", self.to_uint()) } } -impl RegionVid: vid { +impl RegionVid: Vid { pure fn to_uint() -> uint { *self } - pure fn to_str() -> ~str { fmt!("%?", self) } } -impl InferTy { - pure fn to_hash() -> uint { - match self { - TyVar(v) => v.to_uint() << 1, - IntVar(v) => (v.to_uint() << 1) + 1, - FloatVar(v) => (v.to_uint() << 1) + 2 - } - } +impl RegionVid: ToStr { + pure fn to_str() -> ~str { fmt!("%?", self) } +} +impl FnSig : ToStr { pure fn to_str() -> ~str { - match self { - TyVar(v) => v.to_str(), - IntVar(v) => v.to_str(), - FloatVar(v) => v.to_str() - } + // grr, without tcx not much we can do. + return ~"(...)"; } } -trait purity_to_str { - pure fn to_str() -> ~str; -} - -impl purity: purity_to_str { +impl InferTy: ToStr { pure fn to_str() -> ~str { - purity_to_str(self) + match self { + TyVar(ref v) => v.to_str(), + IntVar(ref v) => v.to_str(), + FloatVar(ref v) => v.to_str() + } } } @@ -988,11 +1026,12 @@ fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) } // Interns a type/name combination, stores the resulting box in cx.interner, // and returns the box as cast to an unsafe ptr (see comments for t above). fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { - let key = {sty: st, o_def_id: o_def_id}; + let key = {sty: to_unsafe_ptr(&st), o_def_id: o_def_id}; match cx.interner.find(key) { Some(t) => unsafe { return cast::reinterpret_cast(&t); }, _ => () } + let mut flags = 0u; fn rflags(r: Region) -> uint { (has_regions as uint) | { @@ -1008,42 +1047,46 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option) -> t { substs.self_r.iter(|r| f |= rflags(*r)); return f; } - match st { - ty_estr(vstore_slice(r)) => { + match &st { + &ty_estr(vstore_slice(r)) => { flags |= rflags(r); } - ty_evec(mt, vstore_slice(r)) => { + &ty_evec(ref mt, vstore_slice(r)) => { flags |= rflags(r); flags |= get(mt.ty).flags; } - ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | - ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | - ty_opaque_box | ty_err => (), - ty_param(_) => flags |= has_params as uint, - ty_infer(_) => flags |= needs_infer as uint, - ty_self => flags |= has_self as uint, - ty_enum(_, ref substs) | ty_struct(_, ref substs) - | ty_trait(_, ref substs, _) => { + &ty_nil | &ty_bot | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) | + &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) | + &ty_opaque_box | &ty_err => (), + &ty_param(_) => flags |= has_params as uint, + &ty_infer(_) => flags |= needs_infer as uint, + &ty_self => flags |= has_self as uint, + &ty_enum(_, ref substs) | &ty_struct(_, ref substs) | + &ty_trait(_, ref substs, _) => { flags |= sflags(substs); } - ty_box(m) | ty_uniq(m) | ty_evec(m, _) | - ty_ptr(m) | ty_unboxed_vec(m) => { + &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) | + &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => { flags |= get(m.ty).flags; } - ty_rptr(r, m) => { + &ty_rptr(r, ref m) => { flags |= rflags(r); flags |= get(m.ty).flags; } - ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; }, - ty_tup(ts) => for ts.each |tt| { flags |= get(*tt).flags; }, - ty_fn(ref f) => { + &ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; }, + &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; }, + &ty_fn(ref f) => { flags |= rflags(f.meta.region); for f.sig.inputs.each |a| { flags |= get(a.ty).flags; } flags |= get(f.sig.output).flags; } } - let t = @{sty: st, id: cx.next_id, flags: flags, o_def_id: o_def_id}; - cx.interner.insert(key, t); + + let t = @{sty: move st, id: cx.next_id, flags: flags, o_def_id: o_def_id}; + + let key = {sty: to_unsafe_ptr(&t.sty), o_def_id: o_def_id}; + cx.interner.insert(move key, t); + cx.next_id += 1u; unsafe { cast::reinterpret_cast(&t) } } @@ -1142,9 +1185,9 @@ fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t { mk_t(cx, ty_unboxed_vec({ty: ty, mutbl: ast::m_imm})) } -fn mk_rec(cx: ctxt, fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) } +fn mk_rec(cx: ctxt, +fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) } -fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) } +fn mk_tup(cx: ctxt, +ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) } // take a copy because we want to own the various vectors inside fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) } @@ -1166,7 +1209,7 @@ fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) } fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) } -fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) } +fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) } fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) } @@ -1183,7 +1226,7 @@ fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t { fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) } fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t { - mk_t_with_id(cx, get(base).sty, Some(def_id)) + mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id)) } // Converts s to its machine type equivalent @@ -1192,7 +1235,7 @@ pure fn mach_sty(cfg: @session::config, t: t) -> sty { ty_int(ast::ty_i) => ty_int(cfg.int_type), ty_uint(ast::ty_u) => ty_uint(cfg.uint_type), ty_float(ast::ty_f) => ty_float(cfg.float_type), - ref s => (*s) + ref s => (/*bad*/copy *s) } } @@ -1256,7 +1299,7 @@ fn walk_ty(ty: t, f: fn(t)) { fn maybe_walk_ty(ty: t, f: fn(t) -> bool) { if !f(ty) { return; } - match get(ty).sty { + match /*bad*/copy get(ty).sty { ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_estr(_) | ty_type | ty_opaque_box | ty_self | ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => { @@ -1285,6 +1328,17 @@ fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: fn(t) -> t) -> t { mk_t(tcx, fold_sty(sty, foldop)) } +fn fold_sig(sig: &FnSig, fldop: fn(t) -> t) -> FnSig { + let args = do sig.inputs.map |arg| { + { mode: arg.mode, ty: fldop(arg.ty) } + }; + + FnSig { + inputs: move args, + output: fldop(sig.output) + } +} + fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { fn fold_substs(substs: &substs, fldop: fn(t) -> t) -> substs { {self_r: substs.self_r, @@ -1292,7 +1346,7 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { tps: substs.tps.map(|t| fldop(*t))} } - match *sty { + match /*bad*/copy *sty { ty_box(tm) => { ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl}) } @@ -1327,15 +1381,8 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { ty_tup(new_ts) } ty_fn(ref f) => { - let new_args = f.sig.inputs.map(|a| { - let new_ty = fldop(a.ty); - {mode: a.mode, ty: new_ty} - }); - let new_output = fldop(f.sig.output); - ty_fn(FnTyBase { - meta: f.meta, - sig: FnSig {inputs: new_args, output: new_output} - }) + let sig = fold_sig(&f.sig, fldop); + ty_fn(FnTyBase {meta: f.meta, sig: sig}) } ty_rptr(r, tm) => { ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl}) @@ -1346,7 +1393,7 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty { ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err | ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => { - *sty + /*bad*/copy *sty } } } @@ -1382,8 +1429,8 @@ fn fold_regions_and_ty( fn fold_substs( substs: &substs, fldr: fn(r: Region) -> Region, - fldt: fn(t: t) -> t) -> substs { - + fldt: fn(t: t) -> t) -> substs + { {self_r: substs.self_r.map(|r| fldr(*r)), self_ty: substs.self_ty.map(|t| fldt(*t)), tps: substs.tps.map(|t| fldt(*t))} @@ -1415,18 +1462,9 @@ fn fold_regions_and_ty( ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst) } ty_fn(ref f) => { - let new_region = fldr(f.meta.region); - let new_args = vec::map(f.sig.inputs, |a| { - let new_ty = fldfnt(a.ty); - {mode: a.mode, ty: new_ty} - }); - let new_output = fldfnt(f.sig.output); - ty::mk_fn(cx, FnTyBase { - meta: FnMeta {region: new_region, - ..f.meta}, - sig: FnSig {inputs: new_args, - output: new_output} - }) + ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region), + ..f.meta}, + sig: fold_sig(&f.sig, fldfnt)}) } ref sty => { fold_sty_to_ty(cx, sty, |t| fldt(t)) @@ -1446,7 +1484,7 @@ fn apply_op_on_t_to_ty_fn( f: &FnTy, t_op: fn(t) -> t) -> FnTy { - let t0 = ty::mk_fn(cx, *f); + let t0 = ty::mk_fn(cx, /*bad*/copy *f); let t1 = t_op(t0); match ty::get(t1).sty { ty::ty_fn(copy f) => { @@ -1463,10 +1501,11 @@ fn apply_op_on_t_to_ty_fn( 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 { + debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn); if !type_has_regions(ty) { return ty; } fold_regions_and_ty( cx, ty, @@ -1542,7 +1581,8 @@ fn substs_is_noop(substs: &substs) -> bool { fn substs_to_str(cx: ctxt, substs: &substs) -> ~str { fmt!("substs(self_r=%s, self_ty=%s, tps=%?)", substs.self_r.map_default(~"none", |r| region_to_str(cx, *r)), - substs.self_ty.map_default(~"none", |t| ty_to_str(cx, *t)), + substs.self_ty.map_default(~"none", + |t| ::util::ppaux::ty_to_str(cx, *t)), tys_to_str(cx, substs.tps)) } @@ -1552,7 +1592,7 @@ fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str { bound_durable => ~"durable", bound_owned => ~"owned", bound_const => ~"const", - bound_trait(t) => ty_to_str(cx, t) + bound_trait(t) => ::util::ppaux::ty_to_str(cx, t) } } @@ -1566,11 +1606,11 @@ fn subst(cx: ctxt, debug!("subst(substs=%s, typ=%s)", substs_to_str(cx, substs), - ty_to_str(cx, typ)); + ::util::ppaux::ty_to_str(cx, typ)); if substs_is_noop(substs) { return typ; } let r = do_subst(cx, substs, typ); - debug!(" r = %s", ty_to_str(cx, r)); + debug!(" r = %s", ::util::ppaux::ty_to_str(cx, r)); return r; fn do_subst(cx: ctxt, @@ -1585,10 +1625,18 @@ fn subst(cx: ctxt, fold_regions_and_ty( cx, typ, |r| match r { - 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))), + re_bound(br_self) => { + match substs.self_r { + None => { + cx.sess.bug( + fmt!("ty::subst: \ + Reference to self region when given substs \ + with no self region, ty = %s", + ::util::ppaux::ty_to_str(cx, typ))) + } + Some(self_r) => self_r + } + } _ => r }, |t| do_subst(cx, substs, t), @@ -1662,7 +1710,7 @@ fn sequence_element_type(cx: ctxt, ty: t) -> t { } fn get_element_type(ty: t, i: uint) -> t { - match get(ty).sty { + match /*bad*/copy get(ty).sty { ty_rec(flds) => return flds[i].mt.ty, ty_tup(ts) => return ts[i], _ => fail ~"get_element_type called on invalid type" @@ -1755,7 +1803,7 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { } let mut accum = false; - let result = match get(ty).sty { + let result = match /*bad*/copy get(ty).sty { // scalar types ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | ty_type | ty_ptr(_) | ty_rptr(_, _) | @@ -2115,7 +2163,7 @@ fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind { // Insert a default in case we loop back on self recursively. cx.kind_cache.insert(ty, kind_top()); - let mut result = match get(ty).sty { + let mut result = match /*bad*/copy get(ty).sty { // Scalar and unique types are sendable, constant, and owned ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_ptr(_) => { @@ -2287,7 +2335,7 @@ fn type_implicitly_moves(cx: ctxt, ty: t) -> bool { /// gives a rough estimate of how much space it takes to represent /// an instance of `ty`. Used for the mode transition. fn type_size(cx: ctxt, ty: t) -> uint { - match get(ty).sty { + match /*bad*/copy get(ty).sty { ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_ptr(_) | ty_box(_) | ty_uniq(_) | ty_estr(vstore_uniq) | ty_trait(*) | ty_rptr(*) | ty_evec(_, vstore_uniq) | @@ -2351,8 +2399,8 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { fn type_requires(cx: ctxt, seen: @mut ~[def_id], r_ty: t, ty: t) -> bool { debug!("type_requires(%s, %s)?", - ty_to_str(cx, r_ty), - ty_to_str(cx, ty)); + ::util::ppaux::ty_to_str(cx, r_ty), + ::util::ppaux::ty_to_str(cx, ty)); let r = { get(r_ty).sty == get(ty).sty || @@ -2360,8 +2408,8 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { }; debug!("type_requires(%s, %s)? %b", - ty_to_str(cx, r_ty), - ty_to_str(cx, ty), + ::util::ppaux::ty_to_str(cx, r_ty), + ::util::ppaux::ty_to_str(cx, ty), r); return r; } @@ -2369,10 +2417,10 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { fn subtypes_require(cx: ctxt, seen: @mut ~[def_id], r_ty: t, ty: t) -> bool { debug!("subtypes_require(%s, %s)?", - ty_to_str(cx, r_ty), - ty_to_str(cx, ty)); + ::util::ppaux::ty_to_str(cx, r_ty), + ::util::ppaux::ty_to_str(cx, ty)); - let r = match get(ty).sty { + let r = match /*bad*/copy get(ty).sty { ty_nil | ty_bot | ty_bool | @@ -2447,8 +2495,8 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { }; debug!("subtypes_require(%s, %s)? %b", - ty_to_str(cx, r_ty), - ty_to_str(cx, ty), + ::util::ppaux::ty_to_str(cx, r_ty), + ::util::ppaux::ty_to_str(cx, ty), r); return r; @@ -2461,9 +2509,10 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { fn type_structurally_contains(cx: ctxt, ty: t, test: fn(x: &sty) -> bool) -> bool { let sty = &get(ty).sty; - debug!("type_structurally_contains: %s", ty_to_str(cx, ty)); + debug!("type_structurally_contains: %s", + ::util::ppaux::ty_to_str(cx, ty)); if test(sty) { return true; } - match *sty { + match /*bad*/copy *sty { ty_enum(did, ref substs) => { for vec::each(*enum_variants(cx, did)) |variant| { for variant.args.each |aty| { @@ -2520,6 +2569,13 @@ fn type_is_integral(ty: t) -> bool { } } +fn type_is_char(ty: t) -> bool { + match get(ty).sty { + ty_int(ty_char) => true, + _ => false + } +} + fn type_is_fp(ty: t) -> bool { match get(ty).sty { ty_infer(FloatVar(_)) | ty_float(_) => true, @@ -2542,7 +2598,7 @@ fn type_is_signed(ty: t) -> bool { // that the cycle collector might care about. fn type_is_pod(cx: ctxt, ty: t) -> bool { let mut result = true; - match get(ty).sty { + match /*bad*/copy get(ty).sty { // Scalar types ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | ty_type | ty_ptr(_) => result = true, @@ -2555,7 +2611,7 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool { ty_enum(did, ref substs) => { let variants = enum_variants(cx, did); for vec::each(*variants) |variant| { - let tup_ty = mk_tup(cx, variant.args); + let tup_ty = mk_tup(cx, /*bad*/copy variant.args); // Perform any type parameter substitutions. let tup_ty = subst(cx, substs, tup_ty); @@ -2701,7 +2757,10 @@ impl bound_region : to_bytes::IterBytes { to_bytes::iter_bytes_2(&2u8, ident, lsb0, f), ty::br_cap_avoid(ref id, ref br) => - to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f) + to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f), + + ty::br_fresh(ref x) => + to_bytes::iter_bytes_2(&4u8, x, lsb0, f) } } } @@ -2774,9 +2833,9 @@ impl FnMeta : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { to_bytes::iter_bytes_5(&self.purity, &self.proto, + &self.onceness, &self.region, &self.bounds, - &self.ret_style, lsb0, f); } } @@ -2826,10 +2885,7 @@ impl sty : to_bytes::IterBytes { to_bytes::iter_bytes_2(&11u8, fs, lsb0, f), ty_fn(ref ft) => - to_bytes::iter_bytes_3(&12u8, - &ft.meta, - &ft.sig, - lsb0, f), + to_bytes::iter_bytes_2(&12u8, ft, lsb0, f), ty_self => 13u8.iter_bytes(lsb0, f), @@ -2896,7 +2952,7 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool { // Type accessors for substructures of types fn ty_fn_args(fty: t) -> ~[arg] { match get(fty).sty { - ty_fn(ref f) => f.sig.inputs, + ty_fn(ref f) => /*bad*/copy f.sig.inputs, _ => fail ~"ty_fn_args() called on non-fn type" } } @@ -2917,15 +2973,8 @@ fn ty_fn_purity(fty: t) -> ast::purity { pure fn ty_fn_ret(fty: t) -> t { match get(fty).sty { - ty_fn(ref f) => f.sig.output, - _ => fail ~"ty_fn_ret() called on non-fn type" - } -} - -fn ty_fn_ret_style(fty: t) -> ast::ret_style { - match get(fty).sty { - ty_fn(ref f) => f.meta.ret_style, - _ => fail ~"ty_fn_ret_style() called on non-fn type" + ty_fn(ref f) => f.sig.output, + _ => fail ~"ty_fn_ret() called on non-fn type" } } @@ -2943,9 +2992,30 @@ fn ty_region(ty: t) -> Region { } } +fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t { + /*! + * + * Returns a new function type based on `fn_type` but returning a value of + * type `ret_type` instead. */ + + match ty::get(fn_type).sty { + ty::ty_fn(ref fty) => { + ty::mk_fn(tcx, FnTyBase { + meta: fty.meta, + sig: FnSig {output: ret_type, ..copy fty.sig} + }) + } + _ => { + tcx.sess.bug(fmt!( + "replace_fn_ret() invoked with non-fn-type: %s", + ty_to_str(tcx, fn_type))); + } + } +} + // Returns a vec of all the input and output types of fty. -fn tys_in_fn_ty(fty: &FnTy) -> ~[t] { - vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output) +fn tys_in_fn_sig(sig: &FnSig) -> ~[t] { + vec::append_one(sig.inputs.map(|a| a.ty), sig.output) } // Just checks whether it's a fn that returns bool, @@ -3007,8 +3077,8 @@ fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, // trait itself. This ought to be harmonized. let trt_bounds = ty::lookup_item_type(tcx, trt_id).bounds; - let mth = ty::trait_methods(tcx, trt_id)[n_mth]; - @(vec::append(*trt_bounds, *mth.tps)) + let mth = /*bad*/copy ty::trait_methods(tcx, trt_id)[n_mth]; + @(vec::append(/*bad*/copy *trt_bounds, *mth.tps)) } } } @@ -3205,7 +3275,7 @@ fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field { } fn get_fields(rec_ty:t) -> ~[field] { - match get(rec_ty).sty { + match /*bad*/copy get(rec_ty).sty { ty_rec(fields) => fields, // Can we check at the caller? _ => fail ~"get_fields: not a record type" @@ -3260,8 +3330,8 @@ fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) { tcx.sess.span_fatal (sp, ~"type inference failed because I \ could not find a type\n that's both of the form " - + ty_to_str(tcx, mk_var(tcx, vid)) + - ~" and of the form " + ty_to_str(tcx, rt) + + + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) + + ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) + ~" - such a type would have to be infinitely large."); } } @@ -3343,7 +3413,7 @@ fn ty_sort_str(cx: ctxt, t: t) -> ~str { ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_estr(_) | ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => { - ty_to_str(cx, t) + ::util::ppaux::ty_to_str(cx, t) } ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)), @@ -3388,31 +3458,18 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { match *err { terr_mismatch => ~"types differ", - terr_ret_style_mismatch(values) => { - fn to_str(s: ast::ret_style) -> ~str { - match s { - ast::noreturn => ~"non-returning", - ast::return_val => ~"return-by-value" - } - } - fmt!("expected %s function, found %s function", - to_str(values.expected), - to_str(values.expected)) - } terr_purity_mismatch(values) => { fmt!("expected %s fn but found %s fn", - purity_to_str(values.expected), - purity_to_str(values.found)) + values.expected.to_str(), values.found.to_str()) } terr_onceness_mismatch(values) => { fmt!("expected %s fn but found %s fn", - onceness_to_str(values.expected), - onceness_to_str(values.found)) + values.expected.to_str(), values.found.to_str()) } terr_proto_mismatch(values) => { fmt!("expected %s closure, found %s closure", - proto_ty_to_str(cx, values.expected), - proto_ty_to_str(cx, values.found)) + proto_ty_to_str(cx, values.expected, false), + proto_ty_to_str(cx, values.found, false)) } terr_mutability => ~"values differ in mutability", terr_box_mutability => ~"boxed values differ in mutability", @@ -3446,7 +3503,8 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { terr_arg_count => ~"incorrect number of function parameters", terr_mode_mismatch(values) => { fmt!("expected argument mode %s, but found %s", - mode_to_str(values.expected), mode_to_str(values.found)) + pprust::mode_to_str(values.expected), + pprust::mode_to_str(values.found)) } terr_regions_does_not_outlive(*) => { fmt!("lifetime mismatch") @@ -3489,6 +3547,10 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str { ~"couldn't determine an appropriate integral type for integer \ literal" } + terr_integer_as_char => { + ~"integer literals can't be inferred to char type \ + (try an explicit cast)" + } terr_no_floating_point_type => { ~"couldn't determine an appropriate floating point type for \ floating point literal" @@ -3546,7 +3608,7 @@ fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] { node: item_trait(_, _, ref ms), _ }, _)) => - match ast_util::split_trait_methods((*ms)) { + match ast_util::split_trait_methods((/*bad*/copy *ms)) { (_, p) => p.map(|method| method.ident) }, _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait", @@ -3576,7 +3638,7 @@ fn trait_supertraits(cx: ctxt, id: ast::def_id) -> @~[InstantiatedTraitRef] { ty_trait(def_id, ref substs, _) => { result.push(InstantiatedTraitRef { def_id: def_id, - tpt: { substs: (*substs), ty: *trait_type } + tpt: { substs: (/*bad*/copy *substs), ty: *trait_type } }); } _ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait") @@ -3614,7 +3676,7 @@ fn impl_traits(cx: ctxt, id: ast::def_id, vstore: vstore) -> ~[t] { match ty::get(ty).sty { ty::ty_trait(_, _, trait_vstore) if vstore == trait_vstore => ty, ty::ty_trait(did, ref substs, _) => { - mk_trait(cx, did, (*substs), vstore) + mk_trait(cx, did, (/*bad*/copy *substs), vstore) } _ => cx.sess.bug(~"impl_traits: not a trait") } @@ -3694,7 +3756,7 @@ fn substd_enum_variants(cx: ctxt, let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty); @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty, - ..**variant_info} + ../*bad*/copy **variant_info} } } @@ -3766,19 +3828,22 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { ast_map::path_name(item.ident) } }; - vec::append_one(*path, item_elt) + vec::append_one(/*bad*/copy *path, item_elt) } ast_map::node_foreign_item(nitem, _, path) => { - vec::append_one(*path, ast_map::path_name(nitem.ident)) + vec::append_one(/*bad*/copy *path, + ast_map::path_name(nitem.ident)) } ast_map::node_method(method, _, path) => { - vec::append_one(*path, ast_map::path_name(method.ident)) + vec::append_one(/*bad*/copy *path, + ast_map::path_name(method.ident)) } ast_map::node_trait_method(trait_method, _, path) => { let method = ast_util::trait_method_to_ty_method(*trait_method); - vec::append_one(*path, ast_map::path_name(method.ident)) + vec::append_one(/*bad*/copy *path, + ast_map::path_name(method.ident)) } ast_map::node_variant(ref variant, _, path) => { @@ -3787,12 +3852,12 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path { } ast_map::node_dtor(_, _, _, path) => { - vec::append_one(*path, ast_map::path_name( + vec::append_one(/*bad*/copy *path, ast_map::path_name( syntax::parse::token::special_idents::literally_dtor)) } ast_map::node_struct_ctor(_, item, path) => { - vec::append_one(*path, ast_map::path_name(item.ident)) + vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident)) } ast_map::node_stmt(*) | ast_map::node_expr(*) | @@ -3834,7 +3899,7 @@ fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] { node: ast::item_enum(ref enum_definition, _), _ }, _) => { - let variants = (*enum_definition).variants; + let variants = /*bad*/copy (*enum_definition).variants; let mut disr_val = -1; @vec::map(variants, |variant| { match variant.node.kind { @@ -3943,7 +4008,7 @@ fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] { Some(ast_map::node_item(i,_)) => { match i.node { ast::item_struct(struct_def, _) => { - struct_field_tys(struct_def.fields) + struct_field_tys(/*bad*/copy struct_def.fields) } _ => cx.sess.bug(~"struct ID bound to non-struct") } @@ -3951,7 +4016,7 @@ fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] { Some(ast_map::node_variant(ref variant, _, _)) => { match (*variant).node.kind { ast::struct_variant_kind(struct_def) => { - struct_field_tys(struct_def.fields) + struct_field_tys(/*bad*/copy struct_def.fields) } _ => { cx.sess.bug(~"struct ID bound to enum variant that isn't \ @@ -4160,7 +4225,7 @@ fn normalize_ty(cx: ctxt, t: t) -> t { region: ty::re_static, ..fn_ty.meta }, - sig: fn_ty.sig + sig: /*bad*/copy fn_ty.sig }) } @@ -4171,7 +4236,7 @@ fn normalize_ty(cx: ctxt, t: t) -> t { mk_enum(cx, did, {self_r: Some(ty::re_static), self_ty: None, - tps: (*r).tps}), + tps: /*bad*/copy (*r).tps}), None => t }, @@ -4182,7 +4247,7 @@ fn normalize_ty(cx: ctxt, t: t) -> t { // Ditto. mk_struct(cx, did, {self_r: Some(ty::re_static), self_ty: None, - tps: (*r).tps}), + tps: /*bad*/copy (*r).tps}), None => t }, @@ -4348,31 +4413,6 @@ impl vstore : cmp::Eq { pure fn ne(&self, other: &vstore) -> bool { !(*self).eq(other) } } -impl FnMeta : cmp::Eq { - pure fn eq(&self, other: &FnMeta) -> bool { - (*self).purity == (*other).purity && - (*self).proto == (*other).proto && - (*self).bounds == (*other).bounds && - (*self).ret_style == (*other).ret_style - } - pure fn ne(&self, other: &FnMeta) -> bool { !(*self).eq(other) } -} - -impl FnSig : cmp::Eq { - pure fn eq(&self, other: &FnSig) -> bool { - (*self).inputs == (*other).inputs && - (*self).output == (*other).output - } - pure fn ne(&self, other: &FnSig) -> bool { !(*self).eq(other) } -} - -impl FnTyBase : cmp::Eq { - pure fn eq(&self, other: &FnTyBase) -> bool { - (*self).meta == (*other).meta && (*self).sig == (*other).sig - } - pure fn ne(&self, other: &FnTyBase) -> bool { !(*self).eq(other) } -} - impl TyVid : cmp::Eq { pure fn eq(&self, other: &TyVid) -> bool { *(*self) == *(*other) } pure fn ne(&self, other: &TyVid) -> bool { *(*self) != *(*other) } @@ -4463,6 +4503,12 @@ impl bound_region : cmp::Eq { _ => false } } + br_fresh(e0a) => { + match (*other) { + br_fresh(e0b) => e0a == e0b, + _ => false + } + } } } pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) } @@ -4477,16 +4523,9 @@ impl substs : cmp::Eq { pure fn ne(&self, other: &substs) -> bool { !(*self).eq(other) } } -impl InferTy : cmp::Eq { - pure fn eq(&self, other: &InferTy) -> bool { - (*self).to_hash() == (*other).to_hash() - } - pure fn ne(&self, other: &InferTy) -> bool { !(*self).eq(other) } -} - impl sty : cmp::Eq { pure fn eq(&self, other: &sty) -> bool { - match (*self) { + match (/*bad*/copy *self) { ty_nil => { match (*other) { ty_nil => true, @@ -4566,7 +4605,7 @@ impl sty : cmp::Eq { } } ty_rec(e0a) => { - match (*other) { + match (/*bad*/copy *other) { ty_rec(e0b) => e0a == e0b, _ => false } @@ -4591,14 +4630,14 @@ impl sty : cmp::Eq { } } ty_tup(e0a) => { - match (*other) { + match (/*bad*/copy *other) { ty_tup(e0b) => e0a == e0b, _ => false } } - ty_infer(e0a) => { + ty_infer(ref e0a) => { match (*other) { - ty_infer(e0b) => e0a == e0b, + ty_infer(ref e0b) => *e0a == *e0b, _ => false } } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 4c44642b325a1..b290f6c1742ac 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -52,12 +52,19 @@ * an rptr (`&r.T`) use the region `r` that appears in the rptr. */ + use middle::ty::{FnTyBase, FnMeta, FnSig}; +use middle::ty; use middle::typeck::check::fn_ctxt; +use middle::typeck::collect; use middle::typeck::rscope::{anon_rscope, binding_rscope, empty_rscope}; use middle::typeck::rscope::{in_anon_rscope, in_binding_rscope}; use middle::typeck::rscope::{region_scope, type_rscope}; +use core::result; +use core::vec; +use syntax::ast; + pub trait ast_conv { fn tcx() -> ty::ctxt; fn ccx() -> @crate_ctxt; @@ -74,7 +81,7 @@ fn get_region_reporting_err(tcx: ty::ctxt, match res { result::Ok(r) => r, result::Err(ref e) => { - tcx.sess.span_err(span, (*e)); + tcx.sess.span_err(span, (/*bad*/copy *e)); ty::re_static } } @@ -139,7 +146,8 @@ fn ast_path_to_substs_and_ty( let tps = path.types.map(|a_t| ast_ty_to_ty(self, rscope, *a_t)); let substs = {self_r:self_r, self_ty:None, tps:tps}; - {substs: substs, ty: ty::subst(tcx, &substs, decl_ty)} + let ty = ty::subst(tcx, &substs, decl_ty); + {substs: substs, ty: ty} } pub fn ast_path_to_ty( @@ -155,7 +163,7 @@ pub fn ast_path_to_ty( let {substs: substs, ty: ty} = ast_path_to_substs_and_ty(self, rscope, did, path); write_ty_to_tcx(tcx, path_id, ty); - write_substs_to_tcx(tcx, path_id, substs.tps); + write_substs_to_tcx(tcx, path_id, /*bad*/copy substs.tps); return {substs: substs, ty: ty}; } @@ -219,7 +227,7 @@ fn ast_ty_to_ty( } } return ty::mk_trait(tcx, trait_def_id, - (*substs), vst); + /*bad*/copy *substs, vst); } _ => {} @@ -268,7 +276,7 @@ fn ast_ty_to_ty( } tcx.ast_ty_to_ty_cache.insert(ast_ty, ty::atttce_unresolved); - let typ = match ast_ty.node { + let typ = match /*bad*/copy ast_ty.node { ast::ty_nil => ty::mk_nil(tcx), ast::ty_bot => ty::mk_bot(tcx), ast::ty_box(mt) => { @@ -499,8 +507,7 @@ fn ty_of_fn_decl( proto: ast_proto, onceness: onceness, region: bound_region, - bounds: bounds, - ret_style: decl.cf}, + bounds: bounds}, sig: FnSig {inputs: input_tys, output: output_ty} } diff --git a/src/librustc/middle/typeck/check/alt.rs b/src/librustc/middle/typeck/check/_match.rs similarity index 95% rename from src/librustc/middle/typeck/check/alt.rs rename to src/librustc/middle/typeck/check/_match.rs index 95f44af48e171..7ff3dfcb07387 100644 --- a/src/librustc/middle/typeck/check/alt.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -8,16 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + use middle::pat_util::{pat_is_binding, pat_is_const}; use middle::pat_util::{pat_is_variant_or_struct}; +use middle::ty; +use middle::typeck::check::demand; +use core::vec; +use std::map::HashMap; +use syntax::ast; use syntax::ast_util::walk_pat; +use syntax::ast_util; use syntax::print::pprust; -fn check_alt(fcx: @fn_ctxt, - expr: @ast::expr, - discrim: @ast::expr, - arms: ~[ast::arm]) -> bool { +fn check_match(fcx: @fn_ctxt, + expr: @ast::expr, + discrim: @ast::expr, + arms: ~[ast::arm]) -> bool { let tcx = fcx.ccx.tcx; let mut bot; @@ -27,10 +34,10 @@ fn check_alt(fcx: @fn_ctxt, // Typecheck the patterns first, so that we get types for all the // bindings. for arms.each |arm| { - let pcx = { + let pcx = pat_ctxt { fcx: fcx, map: pat_id_map(tcx.def_map, arm.pats[0]), - alt_region: ty::re_scope(expr.id), + match_region: ty::re_scope(expr.id), block_region: ty::re_scope(arm.body.node.id) }; @@ -55,15 +62,15 @@ fn check_alt(fcx: @fn_ctxt, return bot; } -type pat_ctxt = { +struct pat_ctxt { fcx: @fn_ctxt, map: PatIdMap, - alt_region: ty::Region, // Region for the alt as a whole + match_region: ty::Region, // Region for the match 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, - subpats: Option<~[@ast::pat]>, expected: ty::t) { + +subpats: Option<~[@ast::pat]>, expected: ty::t) { // Typecheck the path. let fcx = pcx.fcx; @@ -144,7 +151,7 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path, let subpats_len; match subpats { None => subpats_len = arg_len, - Some(subpats) => subpats_len = subpats.len() + Some(ref subpats) => subpats_len = subpats.len() } if arg_len > 0u { @@ -195,13 +202,13 @@ fn check_struct_pat_fields(pcx: pat_ctxt, let tcx = pcx.fcx.ccx.tcx; // Index the class fields. - let field_map = std::map::HashMap(); + let field_map = HashMap(); for class_fields.eachi |i, class_field| { field_map.insert(class_field.ident, i); } // Typecheck each field. - let found_fields = std::map::HashMap(); + let found_fields = HashMap(); for fields.each |field| { match field_map.find(field.ident) { Some(index) => { @@ -238,7 +245,7 @@ fn check_struct_pat_fields(pcx: pat_ctxt, fn check_struct_pat(pcx: pat_ctxt, pat_id: ast::node_id, span: span, expected: ty::t, path: @ast::path, - fields: ~[ast::field_pat], etc: bool, + +fields: ~[ast::field_pat], etc: bool, class_id: ast::def_id, substitutions: &ty::substs) { let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; @@ -279,7 +286,7 @@ fn check_struct_like_enum_variant_pat(pcx: pat_ctxt, span: span, expected: ty::t, path: @ast::path, - fields: ~[ast::field_pat], + +fields: ~[ast::field_pat], etc: bool, enum_id: ast::def_id, substitutions: &ty::substs) { @@ -316,7 +323,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { let fcx = pcx.fcx; let tcx = pcx.fcx.ccx.tcx; - match pat.node { + match /*bad*/copy pat.node { ast::pat_wild => { fcx.write_ty(pat.id, expected); } @@ -382,7 +389,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { } fcx.write_ty(pat.id, typ); - debug!("(checking alt) writing type for pat id %d", pat.id); + debug!("(checking match) writing type for pat id %d", pat.id); match sub { Some(p) => check_pat(pcx, p, expected), diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs index 89726e22283d9..954608540f5cb 100644 --- a/src/librustc/middle/typeck/check/demand.rs +++ b/src/librustc/middle/typeck/check/demand.rs @@ -8,7 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::ty; use middle::typeck::check::fn_ctxt; +use middle::typeck::infer; + +use core::result; +use syntax::ast; // Requires that the two types unify, and prints an error message if they // don't. diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 765bf0cfdff4d..b683770822dd9 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -79,15 +79,24 @@ obtained the type `Foo`, we would never match this method. */ + use middle::resolve::{Impl, MethodInfo}; +use middle::resolve; use middle::ty::*; +use middle::ty; use middle::typeck::check; +use middle::typeck::check::vtable; use middle::typeck::coherence::get_base_type_def_id; +use middle::typeck::infer; use core::dvec::DVec; +use core::result; +use core::uint; +use core::vec; use syntax::ast::{def_id, sty_by_ref, sty_value, sty_region, sty_box}; use syntax::ast::{sty_uniq, sty_static, node_id, by_copy, by_ref}; use syntax::ast::{m_const, m_mutbl, m_imm}; +use syntax::ast; use syntax::ast_map; use syntax::ast_map::node_id_to_str; use syntax::ast_util::dummy_sp; @@ -273,8 +282,9 @@ impl LookupContext { ty_self => { // Call is of the form "self.foo()" and appears in one // of a trait's default method implementations. - let self_did = self.fcx.self_impl_def_id.expect( - ~"unexpected `none` for self_impl_def_id"); + let self_did = self.fcx.self_info.expect( + ~"self_impl_def_id is undefined (`self` may not \ + be in scope here").def_id; let substs = {self_r: None, self_ty: None, tps: ~[]}; self.push_inherent_candidates_from_self( self_ty, self_did, &substs); @@ -350,7 +360,7 @@ impl LookupContext { let bound_substs = match ty::get(bound_trait_ty).sty { - ty::ty_trait(_, ref substs, _) => (*substs), + ty::ty_trait(_, ref substs, _) => (/*bad*/copy *substs), _ => { self.bug(fmt!("add_candidates_from_param: \ non-trait bound %s", @@ -378,7 +388,7 @@ impl LookupContext { let mut i = 0; while i < worklist.len() { - let (init_trait_ty, init_substs) = worklist[i]; + let (init_trait_ty, init_substs) = /*bad*/copy worklist[i]; i += 1; let init_trait_id = ty::ty_to_def_id(init_trait_ty).get(); @@ -483,7 +493,7 @@ impl LookupContext { // `trait_ty` for `self` here, because it allows the compiler // to soldier on. An error will be reported should this // candidate be selected if the method refers to `self`. - let rcvr_substs = {self_ty: Some(self_ty), ..*substs}; + let rcvr_substs = {self_ty: Some(self_ty), ../*bad*/copy *substs}; let (rcvr_ty, rcvr_substs) = self.create_rcvr_ty_and_substs_for_method(method.self_ty, @@ -514,7 +524,7 @@ impl LookupContext { } let method = &methods[index]; - let rcvr_substs = { self_ty: Some(self_ty), ..*substs }; + let rcvr_substs = { self_ty: Some(self_ty), ../*bad*/copy *substs }; let (rcvr_ty, rcvr_substs) = self.create_rcvr_ty_and_substs_for_method( method.self_ty, @@ -885,13 +895,13 @@ impl LookupContext { let mut merged = ~[]; let mut i = 0; while i < candidates.len() { - let candidate_a = candidates[i]; + let candidate_a = /*bad*/copy candidates[i]; let mut skip = false; let mut j = i + 1; while j < candidates.len() { - let candidate_b = candidates[j]; + let candidate_b = /*bad*/copy candidates[j]; debug!("attempting to merge %? and %?", candidate_a, candidate_b); let candidates_same = match (&candidate_a.origin, @@ -977,9 +987,11 @@ impl LookupContext { // Construct the full set of type parameters for the method, // which is equal to the class tps + the method tps. - let all_substs = {tps: vec::append(candidate.rcvr_substs.tps, - m_substs), - ..candidate.rcvr_substs}; + let all_substs = { + tps: vec::append(/*bad*/copy candidate.rcvr_substs.tps, + m_substs), + ../*bad*/copy candidate.rcvr_substs + }; self.fcx.write_ty_substs(self.callee_id, fty, all_substs); return {self_arg: {mode: ast::expl(candidate.self_mode), @@ -1064,7 +1076,7 @@ impl LookupContext { trait_did: def_id, method_num: uint) -> ty::t { let trait_methods = ty::trait_methods(tcx, trait_did); - ty::mk_fn(tcx, trait_methods[method_num].fty) + ty::mk_fn(tcx, /*bad*/copy trait_methods[method_num].fty) } } @@ -1115,7 +1127,7 @@ impl LookupContext { ty::item_path_str(self.tcx(), did))); } - fn infcx(&self) -> infer::infer_ctxt { + fn infcx(&self) -> @infer::InferCtxt { self.fcx.inh.infcx } @@ -1139,7 +1151,7 @@ impl LookupContext { ty::item_path_str(self.tcx(), did) } - fn bug(&self, s: ~str) -> ! { + fn bug(&self, +s: ~str) -> ! { self.tcx().sess.bug(s) } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 93bdfd5ccda63..9bbfc5dd7d2b8 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -76,26 +76,50 @@ type parameter). */ -use middle::ty::{TyVid, vid, FnTyBase, FnMeta, FnSig, VariantInfo_}; + +use middle::capture; +use middle::const_eval; +use middle::pat_util; +use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_}; +use middle::ty::{re_bound, br_cap_avoid}; +use middle::ty; use middle::typeck::astconv::{ast_conv, ast_path_to_ty}; use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty}; +use middle::typeck::astconv; +use middle::typeck::check::_match::pat_ctxt; use middle::typeck::check::method::TransformTypeNormally; use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_ty; +use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use middle::typeck::check::vtable::{LocationInfo, VtableContext}; use middle::typeck::infer::{resolve_type, force_tvar}; +use middle::typeck::infer; use middle::typeck::rscope::{anon_rscope, binding_rscope, bound_self_region}; use middle::typeck::rscope::{empty_rscope, in_anon_rscope}; use middle::typeck::rscope::{in_binding_rscope, region_scope, type_rscope}; +use middle::typeck::rscope; use util::ppaux; +use core::either; +use core::option; +use core::ptr; use core::result::{Result, Ok, Err}; +use core::result; +use core::str; +use core::vec; use std::map::HashMap; +use std::map; use syntax::ast::ty_i; +use syntax::ast; +use syntax::ast_map; use syntax::ast_util::{is_local, visibility_to_privacy, Private, Public}; +use syntax::ast_util; +use syntax::codemap; use syntax::parse::token::special_idents; use syntax::print::pprust; +use syntax::visit; +use syntax; -export alt; +export _match; export vtable; export writeback; export regionmanip; @@ -111,7 +135,7 @@ export DoDerefArgs; export check_item_types; #[legacy_exports] -pub mod alt; +pub mod _match; #[legacy_exports] pub mod vtable; #[legacy_exports] @@ -143,7 +167,7 @@ type self_info = { /// `bar()` will each have their own `fn_ctxt`, but they will /// share the inherited fields. struct inherited { - infcx: infer::infer_ctxt, + infcx: @infer::InferCtxt, locals: HashMap, node_types: HashMap, node_type_substs: HashMap, @@ -156,7 +180,10 @@ pub struct fn_ctxt { // var_bindings, locals and next_var_id are shared // with any nested functions that capture the environment // (and with any functions whose environment is being captured). - self_impl_def_id: Option, + + // Refers to whichever `self` is in scope, even this fn_ctxt is + // for a nested closure that captures `self` + self_info: Option, ret_ty: ty::t, // Used by loop bodies that return from the outer function indirect_ret_ty: Option, @@ -205,7 +232,7 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t, // It's kind of a kludge to manufacture a fake function context // and statement context, but we might as well do write the code only once @fn_ctxt { - self_impl_def_id: None, + self_info: None, ret_ty: rty, indirect_ret_ty: None, purity: ast::pure_fn, @@ -218,7 +245,7 @@ fn blank_fn_ctxt(ccx: @crate_ctxt, rty: ty::t, } fn check_item_types(ccx: @crate_ctxt, crate: @ast::crate) { - let visit = visit::mk_simple_visitor(@{ + let visit = visit::mk_simple_visitor(@visit::SimpleVisitor { visit_item: |a| check_item(ccx, a), .. *visit::default_simple_visitor() }); @@ -226,7 +253,7 @@ fn check_item_types(ccx: @crate_ctxt, crate: @ast::crate) { } fn check_bare_fn(ccx: @crate_ctxt, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, id: ast::node_id, self_info: Option) { @@ -243,7 +270,7 @@ fn check_bare_fn(ccx: @crate_ctxt, fn check_fn(ccx: @crate_ctxt, self_info: Option, fn_ty: &ty::FnTy, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, fn_kind: FnKind, old_fcx: Option<@fn_ctxt>) { @@ -258,15 +285,15 @@ fn check_fn(ccx: @crate_ctxt, // types with free ones. The free region references will be bound // the node_id of the body block. - let {isr: isr, self_info: self_info, fn_ty: fn_ty} = { + let {isr, self_info, fn_sig} = { let old_isr = option::map_default(&old_fcx, @Nil, - |fcx| fcx.in_scope_regions); - replace_bound_regions_in_fn_ty(tcx, old_isr, self_info, fn_ty, - |br| ty::re_free(body.node.id, br)) + |fcx| fcx.in_scope_regions); + replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, &fn_ty.sig, + |br| ty::re_free(body.node.id, br)) }; - let arg_tys = fn_ty.sig.inputs.map(|a| a.ty); - let ret_ty = fn_ty.sig.output; + let arg_tys = fn_sig.inputs.map(|a| a.ty); + let ret_ty = fn_sig.output; debug!("check_fn(arg_tys=%?, ret_ty=%?, self_info.self_ty=%?)", arg_tys.map(|a| ppaux::ty_to_str(tcx, *a)), @@ -298,7 +325,7 @@ fn check_fn(ccx: @crate_ctxt, } else { None }; @fn_ctxt { - self_impl_def_id: self_info.map(|self_info| self_info.def_id), + self_info: self_info, ret_ty: ret_ty, indirect_ret_ty: indirect_ret_ty, purity: purity, @@ -328,7 +355,8 @@ fn check_fn(ccx: @crate_ctxt, } }; - gather_locals(fcx, decl, body, arg_tys, self_info); + // XXX: Bad copy. + gather_locals(fcx, decl, body, copy arg_tys, self_info); check_block(fcx, body); // We unify the tail expr's type with the @@ -358,12 +386,12 @@ fn check_fn(ccx: @crate_ctxt, // resolved when the enclosing scope finishes up. if old_fcx.is_none() { vtable::resolve_in_block(fcx, body); - regionck::regionck_fn(fcx, decl, body); + regionck::regionck_fn(fcx, body); writeback::resolve_type_vars_in_fn(fcx, decl, body, self_info); } fn gather_locals(fcx: @fn_ctxt, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, arg_tys: ~[ty::t], self_info: Option) { @@ -401,13 +429,13 @@ fn check_fn(ccx: @crate_ctxt, // Check the pattern. let region = fcx.block_region(); - let pcx = { + let pcx = pat_ctxt { fcx: fcx, map: pat_id_map(tcx.def_map, input.pat), - alt_region: region, + match_region: region, block_region: region, }; - alt::check_pat(pcx, input.pat, *arg_ty); + _match::check_pat(pcx, input.pat, *arg_ty); } // Add explicitly-declared locals. @@ -455,12 +483,13 @@ fn check_fn(ccx: @crate_ctxt, } fn visit_item(_i: @ast::item, &&_e: (), _v: visit::vt<()>) { } - let visit = visit::mk_vt(@{visit_local: visit_local, - visit_pat: visit_pat, - visit_fn: visit_fn, - visit_item: visit_item, - visit_block: visit_block, - .. *visit::default_visitor()}); + let visit = visit::mk_vt( + @visit::Visitor {visit_local: visit_local, + visit_pat: visit_pat, + visit_fn: visit_fn, + visit_item: visit_item, + visit_block: visit_block, + ..*visit::default_visitor()}); (visit.visit_block)(body, (), visit); } @@ -472,7 +501,7 @@ fn check_method(ccx: @crate_ctxt, method: @ast::method, self_id: method.self_id, def_id: self_impl_def_id, explicit_self: method.self_ty }; - check_bare_fn(ccx, method.decl, method.body, method.id, Some(self_info)); + check_bare_fn(ccx, &method.decl, method.body, method.id, Some(self_info)); } fn check_no_duplicate_fields(tcx: ty::ctxt, fields: @@ -510,7 +539,8 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def, explicit_self: {node: ast::sty_by_ref, span: ast_util::dummy_sp()}}; // typecheck the dtor - check_bare_fn(ccx, ast_util::dtor_dec(), + let dtor_dec = ast_util::dtor_dec(); + check_bare_fn(ccx, &dtor_dec, dtor.node.body, dtor.node.id, Some(class_t)); }; @@ -525,12 +555,15 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) { ty::item_path_str(ccx.tcx, local_def(it.id))); let _indenter = indenter(); - match it.node { + match /*bad*/copy it.node { ast::item_const(_, e) => check_const(ccx, it.span, e, it.id), ast::item_enum(ref enum_definition, _) => { - check_enum_variants(ccx, it.span, (*enum_definition).variants, it.id); + check_enum_variants(ccx, + it.span, + /*bad*/copy (*enum_definition).variants, + it.id); } - ast::item_fn(decl, _, _, ref body) => { + ast::item_fn(ref decl, _, _, ref body) => { check_bare_fn(ccx, decl, (*body), it.id, None); } ast::item_impl(_, _, ty, ms) => { @@ -605,7 +638,7 @@ impl @fn_ctxt: ast_conv { } impl @fn_ctxt { - fn infcx() -> infer::infer_ctxt { self.inh.infcx } + fn infcx() -> @infer::InferCtxt { self.inh.infcx } fn search_in_scope_regions(br: ty::bound_region) -> Result { @@ -722,7 +755,7 @@ impl @fn_ctxt { } fn node_ty_substs(id: ast::node_id) -> ty::substs { match self.inh.node_type_substs.find(id) { - Some(ref ts) => (*ts), + Some(ref ts) => (/*bad*/copy *ts), None => { self.tcx().sess.bug( fmt!("no type substs for node %d: %s in fcx %s", @@ -952,13 +985,13 @@ pub fn impl_self_ty(vcx: &VtableContext, let {n_tps, region_param, raw_ty} = if did.crate == ast::local_crate { let region_param = tcx.region_paramd_items.find(did.node); match tcx.items.find(did.node) { - Some(ast_map::node_item(@{node: ast::item_impl(ts, _, st, _), + Some(ast_map::node_item(@{node: ast::item_impl(ref ts, _, st, _), _}, _)) => { {n_tps: ts.len(), region_param: region_param, raw_ty: vcx.ccx.to_ty(rscope::type_rscope(region_param), st)} } - Some(ast_map::node_item(@{node: ast::item_struct(_, ts), + Some(ast_map::node_item(@{node: ast::item_struct(_, ref ts), id: class_id, _},_)) => { /* If the impl is a class, the self ty is just the class ty (doing a no-op subst for the ty params; in the next step, @@ -969,7 +1002,7 @@ pub fn impl_self_ty(vcx: &VtableContext, raw_ty: ty::mk_struct(tcx, local_def(class_id), {self_r: rscope::bound_self_region(region_param), self_ty: None, - tps: ty::ty_params_to_tys(tcx, ts)})} + tps: ty::ty_params_to_tys(tcx, /*bad*/copy *ts)})} } _ => { tcx.sess.bug(~"impl_self_ty: unbound item or item that \ doesn't have a self_ty"); } @@ -1015,6 +1048,10 @@ pub enum DerefArgs { DoDerefArgs } +fn break_here() { + debug!("break here!"); +} + fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, expected: Option, @@ -1051,12 +1088,15 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let fty = match structure_of(fcx, sp, in_fty) { ty::ty_fn(ref fn_ty) => { - let fn_ty = replace_bound_regions_in_fn_ty(tcx, @Nil, + let fn_ty = + /*bad*/copy replace_bound_regions_in_fn_ty(tcx, @Nil, None, fn_ty, |_br| fcx.infcx().next_region_var(sp, call_expr_id)).fn_ty; let supplied_arg_count = args.len(); + bot |= ty::type_is_bot(fn_ty.sig.output); + // Grab the argument types, supplying fresh type variables // if the wrong number of arguments were supplied let expected_arg_count = fn_ty.sig.inputs.len(); @@ -1168,7 +1208,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, call_expr_id: ast::node_id, fn_ty: ty::t, expr: @ast::expr, - args: ~[@ast::expr], + +args: ~[@ast::expr], bot: bool) -> bool { let mut bot = bot; @@ -1184,7 +1224,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // Pull the return type out of the type of the function. match structure_of(fcx, sp, fty) { ty::ty_fn(ref f) => { - bot |= (f.meta.ret_style == ast::noreturn); fcx.write_ty(call_expr_id, f.sig.output); return bot; } @@ -1199,11 +1238,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, // A generic function for doing all of the checking for call expressions fn check_call(fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id, - f: @ast::expr, args: ~[@ast::expr]) -> bool { - + f: @ast::expr, +args: ~[@ast::expr]) -> bool { // Index expressions need to be handled separately, to inform them // that they appear in call position. - let mut bot = match f.node { + let mut bot = match /*bad*/copy f.node { ast::expr_field(base, field, tys) => { check_field(fcx, f, true, base, field, tys) } @@ -1224,7 +1262,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, rcvr: @ast::expr, method_name: ast::ident, - args: ~[@ast::expr], + +args: ~[@ast::expr], tps: ~[@ast::Ty]) -> bool { let bot = check_expr(fcx, rcvr, None); @@ -1310,7 +1348,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn lookup_op_method(fcx: @fn_ctxt, op_ex: @ast::expr, self_ex: @ast::expr, self_t: ty::t, - opname: ast::ident, args: ~[@ast::expr], + opname: ast::ident, +args: ~[@ast::expr], +deref_args: DerefArgs) -> Option<(ty::t, bool)> { @@ -1462,7 +1500,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn check_expr_fn(fcx: @fn_ctxt, expr: @ast::expr, ast_proto_opt: Option, - decl: ast::fn_decl, + decl: &ast::fn_decl, body: ast::blk, fn_kind: FnKind, expected: Option) { @@ -1488,7 +1526,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, replace_bound_regions_in_fn_ty( tcx, @Nil, None, fn_ty, |br| ty::re_bound(ty::br_cap_avoid(id, @br))); - (Some({inputs: fn_ty.sig.inputs, + (Some({inputs: /*bad*/copy fn_ty.sig.inputs, output: fn_ty.sig.output}), fn_ty.meta.purity, fn_ty.meta.proto, @@ -1512,9 +1550,10 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fcx, fcx, proto, purity, expected_onceness, /*bounds:*/ @~[], /*opt_region:*/ None, - decl, expected_tys, expr.span); + *decl, expected_tys, expr.span); - let fty = ty::mk_fn(tcx, fn_ty); + // XXX: Bad copy. + let fty = ty::mk_fn(tcx, copy fn_ty); debug!("check_expr_fn_with_unifier %s fty=%s", expr_to_str(expr, tcx.sess.intr()), @@ -1522,7 +1561,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fcx.write_ty(expr.id, fty); - check_fn(fcx.ccx, None, &fn_ty, decl, body, + // We inherit the same self info as the enclosing scope, + // since the function we're checking might capture `self` + check_fn(fcx.ccx, fcx.self_info, &fn_ty, decl, body, fn_kind, Some(fcx)); } @@ -1648,9 +1689,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let expected_field_type = ty::lookup_field_type( tcx, class_id, field_id, substitutions); - bot |= check_expr(fcx, - field.node.expr, - Some(expected_field_type)); + bot |= + check_expr_with_assignability( + fcx, + field.node.expr, + expected_field_type); class_field_map.insert( field.node.ident, (field_id, true)); fields_found += 1; @@ -1688,7 +1731,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn check_struct_constructor(fcx: @fn_ctxt, id: ast::node_id, - span: syntax::codemap::span, + span: codemap::span, class_id: ast::def_id, fields: ~[ast::field], base_expr: Option<@ast::expr>) -> bool { @@ -1703,7 +1746,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, tcx.region_paramd_items.find(class_id.node); match tcx.items.find(class_id.node) { Some(ast_map::node_item(@{ - node: ast::item_struct(_, type_parameters), + node: ast::item_struct(_, ref type_parameters), _ }, _)) => { @@ -1715,7 +1758,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, raw_type = ty::mk_struct(tcx, class_id, { self_r: self_region, self_ty: None, - tps: ty::ty_params_to_tys(tcx, type_parameters) + tps: ty::ty_params_to_tys( + tcx, + /*bad*/copy *type_parameters) }); } _ => { @@ -1769,7 +1814,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, fn check_struct_enum_variant(fcx: @fn_ctxt, id: ast::node_id, - span: syntax::codemap::span, + span: codemap::span, enum_id: ast::def_id, variant_id: ast::def_id, fields: ~[ast::field]) -> bool { @@ -1784,7 +1829,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, tcx.region_paramd_items.find(enum_id.node); match tcx.items.find(enum_id.node) { Some(ast_map::node_item(@{ - node: ast::item_enum(_, type_parameters), + node: ast::item_enum(_, ref type_parameters), _ }, _)) => { @@ -1796,7 +1841,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, raw_type = ty::mk_enum(tcx, enum_id, { self_r: self_region, self_ty: None, - tps: ty::ty_params_to_tys(tcx, type_parameters) + tps: ty::ty_params_to_tys( + tcx, + /*bad*/copy *type_parameters) }); } _ => { @@ -1843,9 +1890,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let tcx = fcx.ccx.tcx; let id = expr.id; let mut bot = false; - match expr.node { + match /*bad*/copy expr.node { ast::expr_vstore(ev, vst) => { - let typ = match ev.node { + let typ = match /*bad*/copy ev.node { ast::expr_lit(@{node: ast::lit_str(s), span:_}) => { let tt = ast_expr_vstore_to_vstore(fcx, ev, str::len(*s), vst); ty::mk_estr(tcx, tt) @@ -2087,14 +2134,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, bot = !may_break(tcx, expr.id, (*body)); } ast::expr_match(discrim, ref arms) => { - bot = alt::check_alt(fcx, expr, discrim, (*arms)); + bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms)); } - ast::expr_fn(proto, decl, ref body, cap_clause) => { + ast::expr_fn(proto, ref decl, ref body, cap_clause) => { check_expr_fn(fcx, expr, Some(proto), decl, (*body), Vanilla, expected); capture::check_capture_clause(tcx, expr.id, cap_clause); } - ast::expr_fn_block(decl, ref body, cap_clause) => { + ast::expr_fn_block(ref decl, ref body, cap_clause) => { check_expr_fn(fcx, expr, None, decl, (*body), Vanilla, expected); capture::check_capture_clause(tcx, expr.id, cap_clause); @@ -2127,7 +2174,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, ty::mk_fn(tcx, FnTyBase { meta: (*fty).meta, sig: FnSig {output: ty::mk_nil(tcx), - ..(*fty).sig} + ../*bad*/copy (*fty).sig} }) } _ => @@ -2150,9 +2197,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } }; match b.node { - ast::expr_fn_block(decl, ref body, cap_clause) => { + ast::expr_fn_block(ref decl, ref body, cap_clause) => { check_expr_fn(fcx, b, None, - decl, (*body), ForLoop, Some(inner_ty)); + decl, *body, ForLoop, Some(inner_ty)); demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); capture::check_capture_clause(tcx, b.id, cap_clause); } @@ -2161,27 +2208,19 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } let block_ty = structurally_resolved_type( fcx, expr.span, fcx.node_ty(b.id)); - match ty::get(block_ty).sty { - ty::ty_fn(ref fty) => { - if !err_happened { - fcx.write_ty(expr.id, ty::mk_fn(tcx, FnTyBase { - meta: (*fty).meta, - sig: FnSig {output: ty::mk_bool(tcx), - ..(*fty).sig} - })); - } - else { - fcx.write_ty(expr.id, ty::mk_err(fcx.tcx())); - } - } - _ => fail ~"expected fn type" + if err_happened { + fcx.write_ty(expr.id, ty::mk_err(fcx.tcx())); + } else { + let loop_body_ty = ty::replace_fn_return_type(tcx, block_ty, + ty::mk_bool(tcx)); + fcx.write_ty(expr.id, loop_body_ty); } } ast::expr_do_body(b) => { let expected_sty = unpack_expected(fcx, expected, |x| Some(x)); let inner_ty = match expected_sty { Some(ty::ty_fn(ref fty)) => { - ty::mk_fn(tcx, (*fty)) + ty::mk_fn(tcx, (/*bad*/copy *fty)) } _ => match expected { Some(expected_t) => { @@ -2199,23 +2238,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } }; match b.node { - ast::expr_fn_block(decl, ref body, cap_clause) => { + ast::expr_fn_block(ref decl, ref body, cap_clause) => { check_expr_fn(fcx, b, None, - decl, (*body), DoBlock, Some(inner_ty)); + decl, *body, DoBlock, Some(inner_ty)); demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b)); capture::check_capture_clause(tcx, b.id, cap_clause); } // argh _ => fail ~"expected fn ty" } - let block_ty = structurally_resolved_type( - fcx, expr.span, fcx.node_ty(b.id)); - match ty::get(block_ty).sty { - ty::ty_fn(ref fty) => { - fcx.write_ty(expr.id, ty::mk_fn(tcx, (*fty))); - } - _ => fail ~"expected fn ty" - } + fcx.write_ty(expr.id, fcx.node_ty(b.id)); } ast::expr_block(ref b) => { // If this is an unchecked block, turn off purity-checking @@ -2294,7 +2326,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } ast::expr_tup(elts) => { let flds = unpack_expected(fcx, expected, |sty| { - match sty { ty::ty_tup(flds) => Some(flds), _ => None } + // XXX: Beware! If you remove `copy` below, the borrow checker + // will NOT complain, but you will get a segfault at runtime! This + // is because the mode computation is currently unaware of + // argument modes. + match copy sty { ty::ty_tup(flds) => Some(flds), _ => None } }); let elt_ts = do elts.mapi |i, e| { check_expr(fcx, *e, flds.map(|fs| fs[i])); @@ -2309,7 +2345,14 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, Some(fcx.expr_ty(base.get())) } else { expected }; let flds = unpack_expected(fcx, expected, |sty| - match sty { ty::ty_rec(flds) => Some(flds), _ => None } + // XXX: Beware! If you remove `copy` below, the borrow checker + // will NOT complain, but you will get a segfault at runtime! This + // is because the mode computation is currently unaware of + // argument modes. + match copy sty { + ty::ty_rec(flds) => Some(flds), + _ => None + } ); let fields_t = vec::map((*fields), |f| { bot |= check_expr(fcx, f.node.expr, flds.chain_ref(|flds| @@ -2371,11 +2414,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, match tcx.def_map.find(id) { Some(ast::def_struct(type_def_id)) => { check_struct_constructor(fcx, id, expr.span, type_def_id, - (*fields), base_expr); + (/*bad*/copy *fields), base_expr); } Some(ast::def_variant(enum_id, variant_id)) => { check_struct_enum_variant(fcx, id, expr.span, enum_id, - variant_id, (*fields)); + variant_id, (/*bad*/copy *fields)); } _ => { tcx.sess.span_bug(path.span, ~"structure constructor does \ @@ -2420,8 +2463,9 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, } if bot { fcx.write_bot(expr.id); } - debug!("type of expr %s is %s, expected is %s", - syntax::print::pprust::expr_to_str(expr, tcx.sess.intr()), + debug!("type of expr %s is...", + syntax::print::pprust::expr_to_str(expr, tcx.sess.intr())); + debug!("... %s, expected is %s", ppaux::ty_to_str(tcx, fcx.expr_ty(expr)), match expected { Some(t) => ppaux::ty_to_str(tcx, t), @@ -2465,13 +2509,13 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool { let region = ty::re_scope(tcx.region_map.get(local.node.id)); - let pcx = { + let pcx = pat_ctxt { fcx: fcx, map: pat_id_map(tcx.def_map, local.node.pat), - alt_region: region, + match_region: region, block_region: region, }; - alt::check_pat(pcx, local.node.pat, t); + _match::check_pat(pcx, local.node.pat, t); return bot; } @@ -2481,7 +2525,7 @@ fn check_stmt(fcx: @fn_ctxt, stmt: @ast::stmt) -> bool { match stmt.node { ast::stmt_decl(decl, id) => { node_id = id; - match decl.node { + match /*bad*/copy decl.node { ast::decl_local(ls) => for ls.each |l| { bot |= check_decl_local(fcx, *l); }, @@ -2593,7 +2637,7 @@ fn check_instantiable(tcx: ty::ctxt, fn check_enum_variants(ccx: @crate_ctxt, sp: span, - vs: ~[ast::variant], + +vs: ~[ast::variant], id: ast::node_id) { fn do_check(ccx: @crate_ctxt, sp: span, vs: ~[ast::variant], id: ast::node_id, disr_vals: &mut ~[int], disr_val: &mut int, @@ -2638,7 +2682,7 @@ fn check_enum_variants(ccx: @crate_ctxt, *disr_val += 1; match v.node.kind { - ast::tuple_variant_kind(args) if args.len() > 0u => { + ast::tuple_variant_kind(ref args) if args.len() > 0u => { arg_tys = Some(ty::ty_fn_args(ctor_ty).map(|a| a.ty)); } ast::tuple_variant_kind(_) => { @@ -2651,7 +2695,13 @@ fn check_enum_variants(ccx: @crate_ctxt, } ast::enum_variant_kind(_) => { arg_tys = None; - do_check(ccx, sp, vs, id, disr_vals, disr_val, variants); + do_check(ccx, + sp, + /*bad*/copy vs, + id, + disr_vals, + disr_val, + variants); } } @@ -2788,6 +2838,8 @@ fn instantiate_path(fcx: @fn_ctxt, span: span, node_id: ast::node_id, region_lb: ty::Region) { + debug!(">>> instantiate_path"); + let ty_param_count = vec::len(*tpt.bounds); let ty_substs_len = vec::len(pth.types); @@ -2834,6 +2886,8 @@ fn instantiate_path(fcx: @fn_ctxt, let substs = {self_r: self_r, self_ty: None, tps: tps}; fcx.write_ty_substs(node_id, tpt.ty, substs); + + debug!("<<<"); } // Resolves `typ` by a single level if `typ` is a type variable. If no @@ -2852,7 +2906,7 @@ fn structurally_resolved_type(fcx: @fn_ctxt, sp: span, tp: ty::t) -> ty::t { // Returns the one-level-deep structure of the given type. fn structure_of(fcx: @fn_ctxt, sp: span, typ: ty::t) -> ty::sty { - ty::get(structurally_resolved_type(fcx, sp, typ)).sty + /*bad*/copy ty::get(structurally_resolved_type(fcx, sp, typ)).sty } fn type_is_integral(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool { @@ -2997,7 +3051,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { (1u, ~[], ty::mk_nil_ptr(tcx)) } ~"visit_tydesc" => { - let tydesc_name = syntax::parse::token::special_idents::tydesc; + let tydesc_name = special_idents::tydesc; let ty_visitor_name = tcx.sess.ident_of(~"TyVisitor"); assert tcx.intrinsic_defs.contains_key(tydesc_name); assert ccx.tcx.intrinsic_defs.contains_key(ty_visitor_name); @@ -3014,8 +3068,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { proto: ast::ProtoBorrowed, onceness: ast::Once, region: ty::re_bound(ty::br_anon(0)), - bounds: @~[], - ret_style: ast::return_val}, + bounds: @~[]}, sig: FnSig {inputs: ~[{mode: ast::expl(ast::by_val), ty: ty::mk_imm_ptr( ccx.tcx, @@ -3204,6 +3257,18 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], ty::mk_i64(tcx)) } + ~"bswap16" => { + (0u, ~[arg(ast::by_copy, ty::mk_i16(tcx))], + ty::mk_i16(tcx)) + } + ~"bswap32" => { + (0u, ~[arg(ast::by_copy, ty::mk_i32(tcx))], + ty::mk_i32(tcx)) + } + ~"bswap64" => { + (0u, ~[arg(ast::by_copy, ty::mk_i64(tcx))], + ty::mk_i64(tcx)) + } ref other => { tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" + (*other) + ~"`"); @@ -3215,8 +3280,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) { proto: ast::ProtoBare, onceness: ast::Many, region: ty::re_static, - bounds: @~[], - ret_style: ast::return_val}, + bounds: @~[]}, sig: FnSig {inputs: inputs, output: output} }); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 5467eae82662e..b9619d4f91a44 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -27,17 +27,22 @@ this point a bit better. */ + use middle::freevars::get_freevars; use middle::pat_util::pat_bindings; use middle::ty::{encl_region, re_scope}; use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice}; use middle::ty::{vstore_uniq}; +use middle::ty; use middle::typeck::infer::{resolve_and_force_all_but_regions, fres}; use util::ppaux::{note_and_explain_region, ty_to_str}; +use core::result; use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed}; use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar}; +use syntax::ast; use syntax::print::pprust; +use syntax::visit; enum rcx { rcx_({fcx: @fn_ctxt, mut errors_reported: uint}) } type rvt = visit::vt<@rcx>; @@ -104,7 +109,6 @@ fn regionck_expr(fcx: @fn_ctxt, e: @ast::expr) { } fn regionck_fn(fcx: @fn_ctxt, - _decl: ast::fn_decl, blk: ast::blk) { let rcx = rcx_({fcx:fcx, mut errors_reported: 0}); let v = regionck_visitor(); @@ -113,12 +117,12 @@ fn regionck_fn(fcx: @fn_ctxt, } fn regionck_visitor() -> rvt { - visit::mk_vt(@{visit_item: visit_item, - visit_stmt: visit_stmt, - visit_expr: visit_expr, - visit_block: visit_block, - visit_local: visit_local, - .. *visit::default_visitor()}) + visit::mk_vt(@visit::Visitor {visit_item: visit_item, + visit_stmt: visit_stmt, + visit_expr: visit_expr, + visit_block: visit_block, + visit_local: visit_local, + .. *visit::default_visitor()}) } fn visit_item(_item: @ast::item, &&_rcx: @rcx, _v: rvt) { @@ -164,7 +168,7 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) { debug!("visit_expr(e=%s)", pprust::expr_to_str(expr, rcx.fcx.tcx().sess.intr())); - match expr.node { + match /*bad*/copy expr.node { ast::expr_path(*) => { // Avoid checking the use of local variables, as we // already check their definitions. The def'n always diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index 0bcb032d8259c..33a9976f74c9b 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -9,30 +9,46 @@ // except according to those terms. // #[warn(deprecated_mode)]; -// #[warn(deprecated_pattern)]; +use middle::ty; use util::ppaux; +use syntax::ast; use syntax::print::pprust::{expr_to_str}; // Helper functions related to manipulating region types. -fn replace_bound_regions_in_fn_ty( +pub fn replace_bound_regions_in_fn_ty( tcx: ty::ctxt, isr: isr_alist, self_info: Option, fn_ty: &ty::FnTy, mapf: fn(ty::bound_region) -> ty::Region) -> - {isr: isr_alist, self_info: Option, fn_ty: ty::FnTy} { + {isr: isr_alist, self_info: Option, fn_ty: ty::FnTy} +{ + let {isr, self_info, fn_sig} = + replace_bound_regions_in_fn_sig( + tcx, isr, self_info, &fn_ty.sig, mapf); + {isr: isr, + self_info: self_info, + fn_ty: FnTyBase {meta: fn_ty.meta, + sig: fn_sig}} +} +pub fn replace_bound_regions_in_fn_sig( + tcx: ty::ctxt, + isr: isr_alist, + self_info: Option, + fn_sig: &ty::FnSig, + mapf: fn(ty::bound_region) -> ty::Region) -> + {isr: isr_alist, self_info: Option, fn_sig: ty::FnSig} +{ // Take self_info apart; the self_ty part is the only one we want // to update here. - let (self_ty, rebuild_self_info) = match self_info { - Some(copy s) => (Some(s.self_ty), |t| Some({self_ty: t,.. s})), - None => (None, |_t| None) - }; + let self_ty = self_info.map(|s| s.self_ty); + let rebuild_self_info = |t| self_info.map(|s| {self_ty: t, ..*s}); - let mut all_tys = ty::tys_in_fn_ty(fn_ty); + let mut all_tys = ty::tys_in_fn_sig(fn_sig); match self_info { Some({explicit_self: {node: ast::sty_region(m), _}, _}) => { @@ -47,10 +63,10 @@ fn replace_bound_regions_in_fn_ty( for self_ty.each |t| { all_tys.push(*t) } - debug!("replace_bound_regions_in_fn_ty(self_info.self_ty=%?, fn_ty=%s, \ - all_tys=%?)", + debug!("replace_bound_regions_in_fn_sig(self_info.self_ty=%?, fn_sig=%s, \ + all_tys=%?)", self_ty.map(|t| ppaux::ty_to_str(tcx, *t)), - ppaux::ty_to_str(tcx, ty::mk_fn(tcx, *fn_ty)), + ppaux::fn_sig_to_str(tcx, fn_sig), all_tys.map(|t| ppaux::ty_to_str(tcx, *t))); let _i = indenter(); @@ -58,17 +74,15 @@ fn replace_bound_regions_in_fn_ty( debug!("br=%?", br); mapf(br) }; - let ty_fn = ty::ty_fn(*fn_ty); - let t_fn = ty::fold_sty_to_ty(tcx, &ty_fn, |t| { + let new_fn_sig = ty::fold_sig(fn_sig, |t| { replace_bound_regions(tcx, isr, t) }); let t_self = self_ty.map(|t| replace_bound_regions(tcx, isr, *t)); - debug!("result of replace_bound_regions_in_fn_ty: self_info.self_ty=%?, \ - fn_ty=%s", + debug!("result of replace_bound_regions_in_fn_sig: self_info.self_ty=%?, \ + fn_sig=%s", t_self.map(|t| ppaux::ty_to_str(tcx, *t)), - ppaux::ty_to_str(tcx, t_fn)); - + ppaux::fn_sig_to_str(tcx, &new_fn_sig)); // Glue updated self_ty back together with its original def_id. let new_self_info: Option = match t_self { @@ -77,10 +91,8 @@ fn replace_bound_regions_in_fn_ty( }; return {isr: isr, - self_info: new_self_info, - fn_ty: match ty::get(t_fn).sty { ty::ty_fn(ref o) => (*o), - _ => tcx.sess.bug(~"replace_bound_regions_in_fn_ty: impossible")}}; - + self_info: new_self_info, + fn_sig: new_fn_sig}; // Takes `isr`, a (possibly empty) mapping from in-scope region // names ("isr"s) to their corresponding regions; `tys`, a list of @@ -149,7 +161,7 @@ fn replace_bound_regions_in_fn_ty( ty: ty::t) -> ty::t { do ty::fold_regions(tcx, ty) |r, in_fn| { - match r { + let r1 = match r { // As long as we are not within a fn() type, `&T` is // mapped to the free region anon_r. But within a fn // type, it remains bound. @@ -178,7 +190,8 @@ fn replace_bound_regions_in_fn_ty( ty::re_scope(_) | ty::re_free(_, _) | ty::re_infer(_) => r - } + }; + r1 } } } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 5751a46276064..4f1efed09af95 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -8,15 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::resolve; +use middle::ty; use middle::typeck::check::{fn_ctxt, impl_self_ty}; -use middle::typeck::infer::{fixup_err_to_str, infer_ctxt}; +use middle::typeck::infer::{fixup_err_to_str, InferCtxt}; use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type}; +use middle::typeck::infer; use util::common::indenter; use util::ppaux; +use core::result; +use core::uint; +use core::vec; use result::{Result, Ok, Err}; +use syntax::ast; +use syntax::ast_util; use syntax::codemap::span; use syntax::print::pprust; +use syntax::visit; // vtable resolution looks for places where trait bounds are // subsituted in and figures out which vtable is used. There is some @@ -46,7 +56,7 @@ struct LocationInfo { /// callback function to call in case of type error. struct VtableContext { ccx: @crate_ctxt, - infcx: infer::infer_ctxt + infcx: @infer::InferCtxt } impl VtableContext { @@ -86,7 +96,7 @@ fn lookup_vtables(vcx: &VtableContext, ppaux::ty_to_str(tcx, trait_ty), ty::substs_to_str(tcx, substs)); - let new_substs = {self_ty: Some(*ty), ..*substs}; + let new_substs = {self_ty: Some(*ty), ../*bad*/copy *substs}; let trait_ty = ty::subst(tcx, &new_substs, trait_ty); debug!("after subst: %?", @@ -120,14 +130,14 @@ fn lookup_vtables(vcx: &VtableContext, } fn fixup_substs(vcx: &VtableContext, location_info: &LocationInfo, - id: ast::def_id, substs: ty::substs, + id: ast::def_id, +substs: ty::substs, is_early: bool) -> Option { let tcx = vcx.tcx(); // use a dummy type just to package up the substs that need fixing up let t = ty::mk_trait(tcx, id, substs, ty::vstore_slice(ty::re_static)); do fixup_ty(vcx, location_info, t, is_early).map |t_f| { match ty::get(*t_f).sty { - ty::ty_trait(_, ref substs_f, _) => (*substs_f), + ty::ty_trait(_, ref substs_f, _) => (/*bad*/copy *substs_f), _ => fail ~"t_f should be a trait" } } @@ -153,7 +163,8 @@ fn lookup_vtable(vcx: &VtableContext, let tcx = vcx.tcx(); let (trait_id, trait_substs, trait_vstore) = match ty::get(trait_ty).sty { - ty::ty_trait(did, ref substs, vstore) => (did, (*substs), vstore), + ty::ty_trait(did, ref substs, vstore) => + (did, (/*bad*/copy *substs), vstore), _ => tcx.sess.impossible_case(location_info.span, "lookup_vtable: \ don't know how to handle a non-trait") @@ -212,7 +223,7 @@ fn lookup_vtable(vcx: &VtableContext, relate_trait_tys(vcx, location_info, trait_ty, ty); if !allow_unsafe && !is_early { for vec::each(*ty::trait_methods(tcx, did)) |m| { - if ty::type_has_self(ty::mk_fn(tcx, m.fty)) { + if ty::type_has_self(ty::mk_fn(tcx, /*bad*/copy m.fty)) { tcx.sess.span_err( location_info.span, ~"a boxed trait with self types may not be \ @@ -226,7 +237,7 @@ fn lookup_vtable(vcx: &VtableContext, } } } - return Some(vtable_trait(did, (*substs).tps)); + return Some(vtable_trait(did, /*bad*/copy (*substs).tps)); } _ => { @@ -340,7 +351,7 @@ fn lookup_vtable(vcx: &VtableContext, // trait_substs. Now we extract out the // types themselves from trait_substs. - let trait_tps = trait_substs.tps; + let trait_tps = /*bad*/copy trait_substs.tps; debug!("Casting to a trait ty whose substs \ (trait_tps) are %s", @@ -359,7 +370,7 @@ fn lookup_vtable(vcx: &VtableContext, trait_id, substs, is_early) { - Some(ref substs) => (*substs), + Some(ref substs) => (/*bad*/copy *substs), None => { assert is_early; // Bail out with a bogus answer @@ -384,7 +395,7 @@ fn lookup_vtable(vcx: &VtableContext, im.did).bounds; connect_trait_tps(vcx, location_info, - substs_f.tps, + /*bad*/copy substs_f.tps, trait_tps, im.did, trait_vstore); @@ -398,7 +409,8 @@ fn lookup_vtable(vcx: &VtableContext, // of type substitutions for the target // trait. found.push( - vtable_static(im.did, substs_f.tps, + vtable_static(im.did, + /*bad*/copy substs_f.tps, subres)); } } @@ -407,14 +419,14 @@ fn lookup_vtable(vcx: &VtableContext, match found.len() { 0 => { /* fallthrough */ } - 1 => { return Some(found[0]); } + 1 => { return Some(/*bad*/copy found[0]); } _ => { if !is_early { vcx.tcx().sess.span_err( location_info.span, ~"multiple applicable methods in scope"); } - return Some(found[0]); + return Some(/*bad*/copy found[0]); } } } @@ -509,7 +521,7 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) { let item_ty = ty::lookup_item_type(cx.tcx, did); debug!("early resolve expr: def %? %?, %?, %?", ex.id, did, def, fcx.infcx().ty_to_str(item_ty.ty)); - if has_trait_bounds(*item_ty.bounds) { + if has_trait_bounds(/*bad*/copy *item_ty.bounds) { for item_ty.bounds.each |bounds| { debug!("early_resolve_expr: looking up vtables for bound \ %s", @@ -536,7 +548,7 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) { ast::expr_index(*) | ast::expr_method_call(*) => { match ty::method_call_bounds(cx.tcx, cx.method_map, ex.id) { Some(bounds) => { - if has_trait_bounds(*bounds) { + if has_trait_bounds(/*bad*/copy *bounds) { let callee_id = match ex.node { ast::expr_field(_, _, _) => ex.id, _ => ex.callee_id @@ -666,8 +678,8 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) { ex.span, fmt!("failed to find an implementation of trait \ %s for %s", - ppaux::ty_to_str(fcx.tcx(), target_ty), - ppaux::ty_to_str(fcx.tcx(), ty))); + fcx.infcx().ty_to_str(target_ty), + fcx.infcx().ty_to_str(ty))); } } Some(vtable) => { @@ -695,7 +707,7 @@ fn resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, v: visit::vt<@fn_ctxt>) { // Detect points where a trait-bounded type parameter is // instantiated, resolve the impls for the parameters. fn resolve_in_block(fcx: @fn_ctxt, bl: ast::blk) { - visit::visit_block(bl, fcx, visit::mk_vt(@{ + visit::visit_block(bl, fcx, visit::mk_vt(@visit::Visitor { visit_expr: resolve_expr, visit_item: fn@(_i: @ast::item, &&_e: @fn_ctxt, _v: visit::vt<@fn_ctxt>) {}, diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index dd3f240f34343..128fd37d4003e 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -12,12 +12,19 @@ // unresolved type variables and replaces "ty_var" types with their // substitutions. + +use middle::pat_util; +use middle::ty; use middle::typeck::check::{fn_ctxt, lookup_local}; use middle::typeck::infer::{force_all, resolve_all, resolve_region}; use middle::typeck::infer::{resolve_type}; +use middle::typeck::infer; use util::ppaux; -use result::{Result, Ok, Err}; +use core::result::{Result, Ok, Err}; +use core::vec; +use syntax::ast; +use syntax::visit; export resolve_type_vars_in_fn; export resolve_type_vars_in_expr; @@ -149,8 +156,7 @@ fn visit_expr(e: @ast::expr, wbcx: wb_ctxt, v: wb_vt) { resolve_method_map_entry(wbcx.fcx, e.span, e.id); resolve_method_map_entry(wbcx.fcx, e.span, e.callee_id); match e.node { - ast::expr_fn(_, decl, _, _) | - ast::expr_fn_block(decl, _, _) => { + ast::expr_fn_block(ref decl, _, _) => { for vec::each(decl.inputs) |input| { let r_ty = resolve_type_vars_for_node(wbcx, e.span, input.id); @@ -224,13 +230,13 @@ fn visit_item(_item: @ast::item, _wbcx: wb_ctxt, _v: wb_vt) { } fn mk_visitor() -> visit::vt { - visit::mk_vt(@{visit_item: visit_item, - visit_stmt: visit_stmt, - visit_expr: visit_expr, - visit_block: visit_block, - visit_pat: visit_pat, - visit_local: visit_local, - .. *visit::default_visitor()}) + visit::mk_vt(@visit::Visitor {visit_item: visit_item, + visit_stmt: visit_stmt, + visit_expr: visit_expr, + visit_block: visit_block, + visit_pat: visit_pat, + visit_local: visit_local, + .. *visit::default_visitor()}) } fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool { @@ -241,7 +247,7 @@ fn resolve_type_vars_in_expr(fcx: @fn_ctxt, e: @ast::expr) -> bool { } fn resolve_type_vars_in_fn(fcx: @fn_ctxt, - decl: ast::fn_decl, + decl: &ast::fn_decl, blk: ast::blk, self_info: Option) -> bool { let wbcx = {fcx: fcx, mut success: true}; diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 15edea5213934..dab47bd25b857 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -14,8 +14,11 @@ // has at most one implementation for each type. Then we build a mapping from // each trait in the system to its implementations. + +use driver; use metadata::csearch::{ProvidedTraitMethodInfo, each_path, get_impl_traits}; use metadata::csearch::{get_impls_for_mod}; +use metadata::csearch; use metadata::cstore::{CStore, iter_crate_data}; use metadata::decoder::{dl_def, dl_field, dl_impl}; use middle::resolve::{Impl, MethodInfo}; @@ -27,7 +30,8 @@ use middle::ty::{ty_rec, ty_rptr, ty_struct, ty_trait, ty_tup, ty_uint}; use middle::ty::{ty_param, ty_self, ty_type, ty_opaque_box, ty_uniq}; use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext}; use middle::ty::{type_is_ty_var}; -use middle::typeck::infer::{infer_ctxt, can_mk_subty}; +use middle::ty; +use middle::typeck::infer::{InferCtxt, can_mk_subty}; use middle::typeck::infer::{new_infer_ctxt, resolve_ivar}; use middle::typeck::infer::{resolve_nested_tvar, resolve_type}; use syntax::ast::{crate, def_id, def_mod, def_ty}; @@ -35,20 +39,27 @@ use syntax::ast::{item, item_struct, 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}; use syntax::ast::{trait_ref}; +use syntax::ast; use syntax::ast_map::node_item; +use syntax::ast_map; use syntax::ast_util::{def_id_of_def, dummy_sp}; use syntax::attr; use syntax::codemap::span; +use syntax::parse; use syntax::visit::{default_simple_visitor, default_visitor}; use syntax::visit::{mk_simple_visitor, mk_vt, visit_crate, visit_item}; +use syntax::visit::{Visitor, SimpleVisitor}; use syntax::visit::{visit_mod}; use util::ppaux::ty_to_str; use core::dvec::DVec; use core::result::Ok; -use std::map::HashMap; +use core::send_map; use core::uint::range; +use core::uint; use core::vec::{len, push}; +use core::vec; +use std::map::HashMap; struct UniversalQuantificationResult { monotype: t, @@ -56,7 +67,7 @@ struct UniversalQuantificationResult { bounds: @~[param_bounds] } -fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t) +fn get_base_type(inference_context: @InferCtxt, span: span, original_type: t) -> Option { let resolved_type; @@ -103,7 +114,7 @@ fn get_base_type(inference_context: infer_ctxt, span: span, original_type: t) } // Returns the def ID of the base type, if there is one. -fn get_base_type_def_id(inference_context: infer_ctxt, +fn get_base_type_def_id(inference_context: @InferCtxt, span: span, original_type: t) -> Option { @@ -168,7 +179,7 @@ fn CoherenceChecker(crate_context: @crate_ctxt) -> CoherenceChecker { struct CoherenceChecker { crate_context: @crate_ctxt, - inference_context: infer_ctxt, + inference_context: @InferCtxt, // A mapping from implementations to the corresponding base type // definition ID. @@ -186,7 +197,7 @@ impl CoherenceChecker { // Check implementations and traits. This populates the tables // containing the inherent methods and extension methods. It also // builds up the trait inheritance table. - visit_crate(*crate, (), mk_simple_visitor(@{ + visit_crate(*crate, (), mk_simple_visitor(@SimpleVisitor { visit_item: |item| { debug!("(checking coherence) item '%s'", self.crate_context.tcx.sess.str_of(item.ident)); @@ -307,7 +318,7 @@ impl CoherenceChecker { 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_id = parse::next_node_id(tcx.sess.parse_sess); let new_did = local_def(new_id); // XXX: Perform substitutions. @@ -501,10 +512,13 @@ impl CoherenceChecker { self_ty: None, tps: type_parameters }; - let monotype = subst(self.crate_context.tcx, &substitutions, polytype.ty); + + // Get our type parameters back. + let { self_r: _, self_ty: _, tps: type_parameters } = substitutions; + UniversalQuantificationResult { monotype: monotype, type_variables: move type_parameters, @@ -572,9 +586,9 @@ impl CoherenceChecker { // Privileged scope checking fn check_privileged_scopes(crate: @crate) { - visit_crate(*crate, (), mk_vt(@{ + visit_crate(*crate, (), mk_vt(@Visitor { visit_item: |item, _context, visitor| { - match item.node { + match /*bad*/copy item.node { item_mod(module_) => { // Then visit the module items. visit_mod(module_, item.span, item.id, (), visitor); @@ -708,7 +722,7 @@ impl CoherenceChecker { } } - match item.node { + match /*bad*/copy item.node { item_impl(_, trait_refs, _, ast_methods) => { let mut methods = ~[]; for ast_methods.each |ast_method| { @@ -883,7 +897,7 @@ impl CoherenceChecker { // 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 new_did = local_def(parse::next_node_id(*parse_sess)); let provided_method_info = @ProvidedMethodInfo { @@ -947,7 +961,7 @@ impl CoherenceChecker { fn populate_destructor_table() { let coherence_info = &self.crate_context.coherence_info; let tcx = self.crate_context.tcx; - let drop_trait = tcx.lang_items.drop_trait.get(); + let drop_trait = tcx.lang_items.drop_trait(); let impls_opt = coherence_info.extension_methods.find(drop_trait); let impls; diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index b4ba9c3d65447..e17eafa7cfae7 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -30,15 +30,28 @@ are represented as `ty_param()` instances. */ +use metadata::csearch; use middle::ty::{FnMeta, FnSig, FnTyBase, InstantiatedTraitRef}; +use middle::ty; use middle::typeck::astconv::{ast_conv, ty_of_fn_decl, ty_of_arg}; use middle::typeck::astconv::{ast_ty_to_ty}; +use middle::typeck::astconv; +use middle::typeck::infer; use middle::typeck::rscope::*; +use middle::typeck::rscope; use util::common::pluralize; use util::ppaux; use util::ppaux::bound_to_str; +use core::dvec; +use core::option; +use core::vec; +use syntax::ast; +use syntax::ast_map; use syntax::ast_util::trait_method_to_ty_method; +use syntax::ast_util; +use syntax::codemap; +use syntax::visit; fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { @@ -47,9 +60,9 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { for crate.node.module.items.each |crate_item| { if crate_item.ident - == syntax::parse::token::special_idents::intrinsic { + == ::syntax::parse::token::special_idents::intrinsic { - match crate_item.node { + match /*bad*/copy crate_item.node { ast::item_mod(m) => { for m.items.each |intrinsic_item| { let def_id = { crate: ast::local_crate, @@ -80,11 +93,13 @@ fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) { } } - visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{ - visit_item: |a|convert(ccx, a), - visit_foreign_item: |a|convert_foreign(ccx, a), - .. *visit::default_simple_visitor() - })); + visit::visit_crate( + *crate, (), + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_item: |a|convert(ccx, a), + visit_foreign_item: |a|convert_foreign(ccx, a), + .. *visit::default_simple_visitor() + })); } impl @crate_ctxt { @@ -137,7 +152,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt, // constructors get turned into functions. let result_ty; match variant.node.kind { - ast::tuple_variant_kind(args) if args.len() > 0 => { + ast::tuple_variant_kind(ref args) if args.len() > 0 => { let rs = type_rscope(rp); let args = args.map(|va| { let arg_ty = ccx.to_ty(rs, va.ty); @@ -148,8 +163,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt, proto: ast::ProtoBare, onceness: ast::Many, bounds: @~[], - region: ty::re_static, - ret_style: ast::return_val}, + region: ty::re_static}, sig: FnSig {inputs: args, output: enum_ty} })); @@ -158,19 +172,38 @@ fn get_enum_variant_types(ccx: @crate_ctxt, result_ty = Some(enum_ty); } ast::struct_variant_kind(struct_def) => { - result_ty = Some(enum_ty); // XXX: Merge with computation of the the same value below? - let tpt = {bounds: ty_param_bounds(ccx, ty_params), - region_param: rp, - ty: enum_ty}; + let tpt = { + bounds: ty_param_bounds(ccx, /*bad*/copy ty_params), + region_param: rp, + ty: enum_ty + }; convert_struct( - ccx, rp, struct_def, ty_params, tpt, variant.node.id); + ccx, + rp, + struct_def, + /*bad*/copy ty_params, + tpt, + variant.node.id); + // Compute the ctor arg types from the struct fields + let struct_fields = do struct_def.fields.map |struct_field| { + {mode: ast::expl(ast::by_val), + ty: ty::node_id_to_type(ccx.tcx, (*struct_field).node.id) + } + }; + result_ty = Some(ty::mk_fn(tcx, FnTyBase { + meta: FnMeta {purity: ast::pure_fn, + proto: ast::ProtoBare, + onceness: ast::Many, + bounds: @~[], + region: ty::re_static}, + sig: FnSig {inputs: struct_fields, output: enum_ty }})); } ast::enum_variant_kind(ref enum_definition) => { get_enum_variant_types(ccx, enum_ty, - enum_definition.variants, - ty_params, + /*bad*/copy enum_definition.variants, + /*bad*/copy ty_params, rp); result_ty = None; } @@ -179,9 +212,11 @@ fn get_enum_variant_types(ccx: @crate_ctxt, match result_ty { None => {} Some(result_ty) => { - let tpt = {bounds: ty_param_bounds(ccx, ty_params), - region_param: rp, - ty: result_ty}; + let tpt = { + bounds: ty_param_bounds(ccx, /*bad*/copy ty_params), + region_param: rp, + ty: result_ty + }; tcx.tcache.insert(local_def(variant.node.id), tpt); write_ty_to_tcx(tcx, variant.node.id, result_ty); } @@ -191,7 +226,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt, fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { fn store_methods(ccx: @crate_ctxt, id: ast::node_id, - stuff: ~[T], f: fn@(v: &T) -> ty::method) { + stuff: ~[T], f: &fn(v: &T) -> ty::method) { ty::store_trait_methods(ccx.tcx, id, @vec::map(stuff, f)); } @@ -224,7 +259,9 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { let substs = { self_r: None, self_ty: Some(self_param), tps: non_shifted_trait_tps + shifted_method_tps }; - let ty = ty::subst(ccx.tcx, &substs, ty::mk_fn(ccx.tcx, m.fty)); + let ty = ty::subst(ccx.tcx, + &substs, + ty::mk_fn(ccx.tcx, /*bad*/copy m.fty)); let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]] + *m.tps); ccx.tcx.tcache.insert(local_def(am.id), @@ -238,10 +275,10 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { let region_paramd = tcx.region_paramd_items.find(id); match tcx.items.get(id) { ast_map::node_item(@{ - node: ast::item_trait(params, _, ref ms), + node: ast::item_trait(ref params, _, ref ms), _ }, _) => { - store_methods::(ccx, id, (*ms), |m| { + store_methods::(ccx, id, (/*bad*/copy *ms), |m| { let def_id; match *m { ast::required(ref ty_method) => { @@ -250,7 +287,7 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { ast::provided(method) => def_id = local_def(method.id) } - let trait_bounds = ty_param_bounds(ccx, params); + let trait_bounds = ty_param_bounds(ccx, copy *params); let ty_m = trait_method_to_ty_method(*m); let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id); if ty_m.self_ty.node == ast::sty_static { @@ -404,7 +441,7 @@ fn compare_impl_method(tcx: ty::ctxt, // that correspond to the parameters we will find on the impl // - replace self region with a fresh, dummy region let impl_fty = { - let impl_fty = ty::mk_fn(tcx, impl_m.fty); + let impl_fty = ty::mk_fn(tcx, /*bad*/copy impl_m.fty); debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty)); replace_bound_self(tcx, impl_fty, dummy_self_r) }; @@ -422,7 +459,7 @@ fn compare_impl_method(tcx: ty::ctxt, self_ty: Some(self_ty), tps: vec::append(trait_tps, dummy_tps) }; - let trait_fty = ty::mk_fn(tcx, trait_m.fty); + let trait_fty = ty::mk_fn(tcx, /*bad*/copy trait_m.fty); debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty)); ty::subst(tcx, &substs, trait_fty) }; @@ -528,15 +565,15 @@ fn convert_methods(ccx: @crate_ctxt, let tcx = ccx.tcx; do vec::map(ms) |m| { - let bounds = ty_param_bounds(ccx, m.tps); + let bounds = ty_param_bounds(ccx, /*bad*/copy m.tps); let mty = ty_of_method(ccx, *m, rp); - let fty = ty::mk_fn(tcx, mty.fty); + let fty = ty::mk_fn(tcx, /*bad*/copy mty.fty); tcx.tcache.insert( local_def(m.id), // n.b.: the type of a method is parameterized by both // the tps on the receiver and those on the method itself - {bounds: @(vec::append(*rcvr_bounds, *bounds)), + {bounds: @(vec::append(/*bad*/copy *rcvr_bounds, *bounds)), region_param: rp, ty: fty}); write_ty_to_tcx(tcx, m.id, fty); @@ -550,17 +587,19 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { let rp = tcx.region_paramd_items.find(it.id); debug!("convert: item %s with id %d rp %?", tcx.sess.str_of(it.ident), it.id, rp); - match it.node { + match /*bad*/copy it.node { // These don't define types. ast::item_foreign_mod(_) | ast::item_mod(_) => {} - ast::item_enum(ref enum_definition, ty_params) => { + ast::item_enum(ref enum_definition, ref ty_params) => { let tpt = ty_of_item(ccx, it); write_ty_to_tcx(tcx, it.id, tpt.ty); - get_enum_variant_types(ccx, tpt.ty, (*enum_definition).variants, - ty_params, rp); + get_enum_variant_types(ccx, + tpt.ty, + /*bad*/copy (*enum_definition).variants, + /*bad*/copy *ty_params, rp); } - ast::item_impl(tps, trait_ref, selfty, ms) => { - let i_bounds = ty_param_bounds(ccx, tps); + ast::item_impl(ref tps, trait_ref, selfty, ref ms) => { + let i_bounds = ty_param_bounds(ccx, /*bad*/copy *tps); let selfty = ccx.to_ty(type_rscope(rp), selfty); write_ty_to_tcx(tcx, it.id, selfty); tcx.tcache.insert(local_def(it.id), @@ -568,21 +607,24 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { region_param: rp, ty: selfty}); - let cms = convert_methods(ccx, ms, rp, i_bounds); + // XXX: Bad copy of `ms` below. + let cms = convert_methods(ccx, /*bad*/copy *ms, rp, i_bounds); for trait_ref.each |t| { - check_methods_against_trait(ccx, tps, rp, selfty, *t, cms); + check_methods_against_trait(ccx, /*bad*/copy *tps, rp, selfty, + *t, /*bad*/copy cms); } } - ast::item_trait(tps, supertraits, ref trait_methods) => { + ast::item_trait(ref tps, ref supertraits, ref trait_methods) => { let tpt = ty_of_item(ccx, it); debug!("item_trait(it.id=%d, tpt.ty=%s)", it.id, ppaux::ty_to_str(tcx, tpt.ty)); write_ty_to_tcx(tcx, it.id, tpt.ty); ensure_trait_methods(ccx, it.id, tpt.ty); - ensure_supertraits(ccx, it.id, it.span, rp, supertraits); + ensure_supertraits(ccx, it.id, it.span, rp, *supertraits); - let (_, provided_methods) = split_trait_methods((*trait_methods)); - let {bounds, _} = mk_substs(ccx, tps, rp); + let (_, provided_methods) = + split_trait_methods(/*bad*/copy *trait_methods); + let {bounds, _} = mk_substs(ccx, /*bad*/copy *tps, rp); let _cms = convert_methods(ccx, provided_methods, rp, bounds); // FIXME (#2616): something like this, when we start having // trait inheritance? @@ -611,7 +653,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { fn convert_struct(ccx: @crate_ctxt, rp: Option, struct_def: @ast::struct_def, - tps: ~[ast::ty_param], + +tps: ~[ast::ty_param], tpt: ty::ty_param_bounds_and_ty, id: ast::node_id) { let tcx = ccx.tcx; @@ -656,8 +698,7 @@ fn convert_struct(ccx: @crate_ctxt, proto: ast::ProtoBare, onceness: ast::Many, bounds: @~[], - region: ty::re_static, - ret_style: ast::return_val, + region: ty::re_static }, sig: FnSig { inputs: do struct_def.fields.map |field| { @@ -694,7 +735,7 @@ fn ty_of_method(ccx: @crate_ctxt, m: @ast::method, rp: Option) -> ty::method { {ident: m.ident, - tps: ty_param_bounds(ccx, m.tps), + tps: ty_param_bounds(ccx, /*bad*/copy m.tps), fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare, m.purity, ast::Many, /*bounds:*/ @~[], /*opt_region:*/ None, @@ -709,7 +750,7 @@ fn ty_of_ty_method(self: @crate_ctxt, rp: Option, id: ast::def_id) -> ty::method { {ident: m.ident, - tps: ty_param_bounds(self, m.tps), + tps: ty_param_bounds(self, /*bad*/copy m.tps), fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare, m.purity, ast::Many, /*bounds:*/ @~[], /*opt_region:*/ None, @@ -759,7 +800,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item) _ => {} } let rp = tcx.region_paramd_items.find(it.id); - match it.node { + match /*bad*/copy it.node { ast::item_const(t, _) => { let typ = ccx.to_ty(empty_rscope, t); let tpt = no_params(typ); @@ -844,7 +885,7 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item) fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item) -> ty::ty_param_bounds_and_ty { - match it.node { + match /*bad*/copy it.node { ast::foreign_item_fn(fn_decl, purity, params) => { return ty_of_foreign_fn_decl(ccx, fn_decl, purity, params, local_def(it.id)); @@ -871,20 +912,15 @@ fn compute_bounds(ccx: @crate_ctxt, 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.owned_trait { + if did == li.owned_trait() { ~[ty::bound_owned] - } - else if d == li.copy_trait { + } else if did == li.copy_trait() { ~[ty::bound_copy] - } - else if d == li.const_trait { + } else if did == li.const_trait() { ~[ty::bound_const] - } - else if d == li.durable_trait { + } else if did == li.durable_trait() { ~[ty::bound_durable] - } - else { + } else { // Must be a user-defined trait ~[ty::bound_trait(ity)] } @@ -918,9 +954,8 @@ fn ty_param_bounds(ccx: @crate_ctxt, fn ty_of_foreign_fn_decl(ccx: @crate_ctxt, decl: ast::fn_decl, purity: ast::purity, - ty_params: ~[ast::ty_param], + +ty_params: ~[ast::ty_param], def_id: ast::def_id) -> ty::ty_param_bounds_and_ty { - let bounds = ty_param_bounds(ccx, ty_params); let rb = in_binding_rscope(empty_rscope); let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, *a, None) ); @@ -931,8 +966,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt, onceness: ast::Many, proto: ast::ProtoBare, bounds: @~[], - region: ty::re_static, - ret_style: ast::return_val}, + region: ty::re_static}, sig: FnSig {inputs: input_tys, output: output_ty} }); @@ -945,7 +979,8 @@ fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param]) -> {bounds: @~[ty::param_bounds], params: ~[ty::t]} { let mut i = 0u; - let bounds = ty_param_bounds(ccx, atps); + // XXX: Bad copy. + let bounds = ty_param_bounds(ccx, copy atps); {bounds: bounds, params: vec::map(atps, |atp| { let t = ty::mk_param(ccx.tcx, i, local_def(atp.id)); @@ -954,10 +989,10 @@ fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param]) })} } -fn mk_substs(ccx: @crate_ctxt, atps: ~[ast::ty_param], +fn mk_substs(ccx: @crate_ctxt, + +atps: ~[ast::ty_param], rp: Option) - -> {bounds: @~[ty::param_bounds], substs: ty::substs} { - + -> {bounds: @~[ty::param_bounds], substs: ty::substs} { let {bounds, params} = mk_ty_params(ccx, atps); let self_r = rscope::bound_self_region(rp); {bounds: bounds, substs: {self_r: self_r, self_ty: None, tps: params}} diff --git a/src/librustc/middle/typeck/infer/assignment.rs b/src/librustc/middle/typeck/infer/assignment.rs index 1abe2156a1ebb..a26079c6f959a 100644 --- a/src/librustc/middle/typeck/infer/assignment.rs +++ b/src/librustc/middle/typeck/infer/assignment.rs @@ -58,10 +58,15 @@ // A. But this upper-bound might be stricter than what is truly // needed. -use middle::typeck::infer::combine::combine_fields; -use middle::typeck::infer::to_str::ToStr; -fn to_ares(+c: cres) -> ares { +use middle::ty; +use middle::typeck::infer::combine::CombineFields; +use middle::typeck::infer::to_str::InferStr; + +use core::option; +use syntax::ast; + +fn to_ares(+c: cres) -> ares { match c { Ok(_) => Ok(None), Err(ref e) => Err((*e)) @@ -71,16 +76,22 @@ fn to_ares(+c: cres) -> ares { // Note: Assign is not actually a combiner, in that it does not // conform to the same interface, though it performs a similar // function. -enum Assign = combine_fields; +enum Assign = CombineFields; impl Assign { fn tys(a: ty::t, b: ty::t) -> ares { - debug!("Assign.tys(%s -> %s)", - a.to_str(self.infcx), - b.to_str(self.infcx)); + debug!("Assign.tys(%s => %s)", + a.inf_str(self.infcx), + b.inf_str(self.infcx)); let _r = indenter(); - match (ty::get(a).sty, ty::get(b).sty) { + debug!("Assign.tys: copying first type"); + let copy_a = copy ty::get(a).sty; + debug!("Assign.tys: copying second type"); + let copy_b = copy ty::get(b).sty; + debug!("Assign.tys: performing match"); + + let r = match (copy_a, copy_b) { (ty::ty_bot, _) => { Ok(None) } @@ -115,7 +126,11 @@ impl Assign { (_, _) => { self.assign_tys_or_sub(a, b, Some(a), Some(b)) } - } + }; + + debug!("Assign.tys end"); + + move r } } @@ -124,9 +139,9 @@ priv impl Assign { a: ty::t, b: ty::t, +a_bnd: Option, +b_bnd: Option) -> ares { - debug!("Assign.assign_tys_or_sub(%s -> %s, %s -> %s)", - a.to_str(self.infcx), b.to_str(self.infcx), - a_bnd.to_str(self.infcx), b_bnd.to_str(self.infcx)); + debug!("Assign.assign_tys_or_sub(%s => %s, %s => %s)", + a.inf_str(self.infcx), b.inf_str(self.infcx), + a_bnd.inf_str(self.infcx), b_bnd.inf_str(self.infcx)); let _r = indenter(); fn is_borrowable(v: ty::vstore) -> bool { @@ -146,7 +161,8 @@ priv impl Assign { match (a_bnd, b_bnd) { (Some(a_bnd), Some(b_bnd)) => { - match (ty::get(a_bnd).sty, ty::get(b_bnd).sty) { + match (/*bad*/copy ty::get(a_bnd).sty, + /*bad*/copy ty::get(b_bnd).sty) { // check for a case where a non-region pointer (@, ~) is // being assigned to a region pointer: (ty::ty_box(_), ty::ty_rptr(r_b, mt_b)) => { @@ -188,18 +204,28 @@ priv impl Assign { let nr_b = ty::mk_fn(self.infcx.tcx, ty::FnTyBase { meta: ty::FnMeta {proto: a_f.meta.proto, ..b_f.meta}, - sig: b_f.sig + sig: copy b_f.sig }); self.try_assign(0, ty::AutoBorrowFn, a, nr_b, m_imm, b_f.meta.region) } + (ty::ty_fn(ref a_f), ty::ty_fn(ref b_f)) + if a_f.meta.proto == ast::ProtoBare => { + let b1_f = ty::FnTyBase { + meta: ty::FnMeta {proto: ast::ProtoBare, + ..b_f.meta}, + sig: copy b_f.sig + }; + // Eventually we will need to add some sort of + // adjustment here so that trans can add an + // extra NULL env pointer: + to_ares(Sub(*self).fns(a_f, &b1_f)) + } + // check for &T being assigned to *T: (ty::ty_rptr(_, ref a_t), ty::ty_ptr(ref b_t)) => { - match Sub(*self).mts(*a_t, *b_t) { - Ok(_) => Ok(None), - Err(ref e) => Err((*e)) - } + to_ares(Sub(*self).mts(*a_t, *b_t)) } // otherwise, assignment follows normal subtype rules: @@ -230,10 +256,10 @@ priv impl Assign { r_b: ty::Region) -> ares { debug!("try_assign(a=%s, nr_b=%s, m=%?, r_b=%s)", - a.to_str(self.infcx), - nr_b.to_str(self.infcx), + a.inf_str(self.infcx), + nr_b.inf_str(self.infcx), m, - r_b.to_str(self.infcx)); + r_b.inf_str(self.infcx)); do indent { let sub = Sub(*self); diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index da66ecd922b68..ec6205c9d680c 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -54,17 +54,22 @@ // terms of error reporting, although we do not do that properly right // now. +use middle::ty; use middle::ty::{FnTyBase, FnMeta, FnSig}; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::sub::Sub; +use middle::typeck::infer::to_str::InferStr; +use core::vec; use syntax::ast::Onceness; +use syntax::ast; fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. -trait combine { - fn infcx() -> infer_ctxt; +trait Combine { + fn infcx() -> @InferCtxt; fn tag() -> ~str; fn a_is_expected() -> bool; + fn span() -> span; fn sub() -> Sub; fn lub() -> Lub; @@ -84,7 +89,6 @@ trait combine { fn modes(a: ast::mode, b: ast::mode) -> cres; fn args(a: ty::arg, b: ty::arg) -> cres; fn protos(p1: ast::Proto, p2: ast::Proto) -> cres; - fn ret_styles(r1: ret_style, r2: ret_style) -> cres; fn purities(a: purity, b: purity) -> cres; fn oncenesses(a: Onceness, b: Onceness) -> cres; fn contraregions(a: ty::Region, b: ty::Region) -> cres; @@ -93,13 +97,13 @@ trait combine { a: ty::vstore, b: ty::vstore) -> cres; } -pub struct combine_fields { - infcx: infer_ctxt, +pub struct CombineFields { + infcx: @InferCtxt, a_is_expected: bool, span: span, } -fn expected_found( +fn expected_found( self: &C, +a: T, +b: T) -> ty::expected_found { if self.a_is_expected() { @@ -109,7 +113,7 @@ fn expected_found( } } -pub fn eq_tys(self: &C, a: ty::t, b: ty::t) -> ures { +pub fn eq_tys(self: &C, a: ty::t, b: ty::t) -> ures { let suber = self.sub(); do self.infcx().try { do suber.tys(a, b).chain |_ok| { @@ -118,10 +122,10 @@ pub 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())); + a.inf_str(self.infcx()), + b.inf_str(self.infcx())); let sub = self.sub(); do indent { self.infcx().try(|| { @@ -140,7 +144,7 @@ fn eq_regions(self: &C, a: ty::Region, b: ty::Region) -> ures { } } -fn eq_opt_regions( +fn eq_opt_regions( self: &C, a: Option, b: Option) -> cres> { @@ -162,17 +166,17 @@ fn eq_opt_regions( self.infcx().tcx.sess.bug( fmt!("substitution a had opt_region %s and \ b had opt_region %s", - a.to_str(self.infcx()), - b.to_str(self.infcx()))); + a.inf_str(self.infcx()), + b.inf_str(self.infcx()))); } } } -fn super_substs( +fn super_substs( self: &C, did: ast::def_id, a: &ty::substs, b: &ty::substs) -> cres { - fn relate_region_param( + fn relate_region_param( self: &C, did: ast::def_id, a: Option, @@ -208,8 +212,8 @@ fn super_substs( self.infcx().tcx.sess.bug( fmt!("substitution a had opt_region %s and \ b had opt_region %s with variance %?", - a.to_str(self.infcx()), - b.to_str(self.infcx()), + a.inf_str(self.infcx()), + b.inf_str(self.infcx()), polyty.region_param)); } } @@ -220,13 +224,13 @@ fn super_substs( do relate_region_param(self, did, a.self_r, b.self_r).chain |self_r| { - Ok({self_r: self_r, self_ty: self_ty, tps: tps}) + Ok({self_r: self_r, self_ty: self_ty, tps: /*bad*/copy tps}) } } } } -fn super_tps( +fn super_tps( self: &C, as_: &[ty::t], bs: &[ty::t]) -> cres<~[ty::t]> { // Note: type parameters are always treated as *invariant* @@ -244,7 +248,7 @@ fn super_tps( } } -fn super_self_tys( +fn super_self_tys( self: &C, a: Option, b: Option) -> cres> { // Note: the self type parameter is (currently) always treated as @@ -267,7 +271,17 @@ fn super_self_tys( } } -fn super_flds( +fn super_protos( + self: &C, p1: ast::Proto, p2: ast::Proto) -> cres +{ + if p1 == p2 { + Ok(p1) + } else { + Err(ty::terr_proto_mismatch(expected_found(self, p1, p2))) + } +} + +fn super_flds( self: &C, a: ty::field, b: ty::field) -> cres { if a.ident == b.ident { @@ -280,7 +294,7 @@ fn super_flds( } } -fn super_modes( +fn super_modes( self: &C, a: ast::mode, b: ast::mode) -> cres { @@ -288,7 +302,7 @@ fn super_modes( ty::unify_mode(tcx, expected_found(self, a, b)) } -fn super_args( +fn super_args( self: &C, a: ty::arg, b: ty::arg) -> cres { @@ -299,7 +313,7 @@ fn super_args( } } -fn super_vstores( +fn super_vstores( self: &C, vk: ty::terr_vstore_kind, a: ty::vstore, b: ty::vstore) -> cres { @@ -322,28 +336,27 @@ fn super_vstores( } } -fn super_fn_metas( +fn super_fn_metas( self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres { let p = if_ok!(self.protos(a_f.proto, b_f.proto)); let r = if_ok!(self.contraregions(a_f.region, b_f.region)); - let rs = if_ok!(self.ret_styles(a_f.ret_style, b_f.ret_style)); let purity = if_ok!(self.purities(a_f.purity, b_f.purity)); let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness)); Ok(FnMeta {purity: purity, proto: p, - region: r, onceness: onceness, - bounds: a_f.bounds, // XXX: This is wrong! - ret_style: rs}) + region: r, + bounds: a_f.bounds}) // XXX: This is wrong! } -fn super_fn_sigs( +fn super_fn_sigs( self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres { - fn argvecs(self: &C, a_args: ~[ty::arg], - b_args: ~[ty::arg]) -> cres<~[ty::arg]> { - + fn argvecs(self: &C, + +a_args: ~[ty::arg], + +b_args: ~[ty::arg]) -> cres<~[ty::arg]> + { if vec::same_length(a_args, b_args) { map_vec2(a_args, b_args, |a, b| self.args(*a, *b)) } else { @@ -351,28 +364,27 @@ fn super_fn_sigs( } } - do argvecs(self, a_f.inputs, b_f.inputs).chain |inputs| { + do argvecs(self, /*bad*/copy a_f.inputs, /*bad*/copy b_f.inputs) + .chain |inputs| { do self.tys(a_f.output, b_f.output).chain |output| { - Ok(FnSig {inputs: inputs, output: output}) + Ok(FnSig {inputs: /*bad*/copy inputs, output: output}) } } } -fn super_fns( +fn super_fns( self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres { - do self.fn_metas(&a_f.meta, &b_f.meta).chain |m| { - do self.fn_sigs(&a_f.sig, &b_f.sig).chain |s| { - Ok(FnTyBase {meta: m, sig: s}) - } - } + let m = if_ok!(self.fn_metas(&a_f.meta, &b_f.meta)); + let s = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig)); + Ok(FnTyBase {meta: m, sig: s}) } -fn super_tys( - self: &C, a: ty::t, b: ty::t) -> cres { - +fn super_tys( + self: &C, a: ty::t, b: ty::t) -> cres +{ let tcx = self.infcx().tcx; - match (ty::get(a).sty, ty::get(b).sty) { + match (/*bad*/copy ty::get(a).sty, /*bad*/copy ty::get(b).sty) { // The "subtype" ought to be handling cases involving bot or var: (ty::ty_bot, _) | (_, ty::ty_bot) | @@ -381,39 +393,56 @@ fn super_tys( tcx.sess.bug( fmt!("%s: bot and var types should have been handled (%s,%s)", self.tag(), - a.to_str(self.infcx()), - b.to_str(self.infcx()))); + a.inf_str(self.infcx()), + b.inf_str(self.infcx()))); } // Relate integral variables to other types (ty::ty_infer(IntVar(a_id)), ty::ty_infer(IntVar(b_id))) => { - self.infcx().int_vars(a_id, b_id).then(|| Ok(a) ) + if_ok!(self.infcx().simple_vars(&self.infcx().int_var_bindings, + ty::terr_no_integral_type, + a_id, b_id)); + Ok(a) } - (ty::ty_infer(IntVar(a_id)), ty::ty_int(_)) | - (ty::ty_infer(IntVar(a_id)), ty::ty_uint(_)) => { - self.infcx().int_var_sub_t(a_id, b).then(|| Ok(a) ) + (ty::ty_infer(IntVar(v_id)), ty::ty_int(v)) | + (ty::ty_int(v), ty::ty_infer(IntVar(v_id))) => { + if v == ast::ty_char { + Err(ty::terr_integer_as_char) + } else { + if_ok!(self.infcx().simple_var_t(&self.infcx().int_var_bindings, + ty::terr_no_integral_type, + v_id, IntType(v))); + Ok(ty::mk_mach_int(tcx, v)) + } } - (ty::ty_int(_), ty::ty_infer(IntVar(b_id))) | - (ty::ty_uint(_), ty::ty_infer(IntVar(b_id))) => { - self.infcx().t_sub_int_var(a, b_id).then(|| Ok(a) ) + (ty::ty_infer(IntVar(v_id)), ty::ty_uint(v)) | + (ty::ty_uint(v), ty::ty_infer(IntVar(v_id))) => { + if_ok!(self.infcx().simple_var_t(&self.infcx().int_var_bindings, + ty::terr_no_integral_type, + v_id, UintType(v))); + Ok(ty::mk_mach_uint(tcx, v)) } // Relate floating-point variables to other types (ty::ty_infer(FloatVar(a_id)), ty::ty_infer(FloatVar(b_id))) => { - self.infcx().float_vars(a_id, b_id).then(|| Ok(a) ) - } - (ty::ty_infer(FloatVar(a_id)), ty::ty_float(_)) => { - self.infcx().float_var_sub_t(a_id, b).then(|| Ok(a) ) + if_ok!(self.infcx().simple_vars(&self.infcx().float_var_bindings, + ty::terr_no_floating_point_type, + a_id, b_id)); + Ok(a) } - (ty::ty_float(_), ty::ty_infer(FloatVar(b_id))) => { - self.infcx().t_sub_float_var(a, b_id).then(|| Ok(a) ) + (ty::ty_infer(FloatVar(v_id)), ty::ty_float(v)) | + (ty::ty_float(v), ty::ty_infer(FloatVar(v_id))) => { + if_ok!(self.infcx().simple_var_t(&self.infcx().float_var_bindings, + ty::terr_no_floating_point_type, + v_id, v)); + Ok(ty::mk_mach_float(tcx, v)) } (ty::ty_int(_), _) | (ty::ty_uint(_), _) | (ty::ty_float(_), _) => { - let as_ = ty::get(a).sty; - let bs = ty::get(b).sty; + let as_ = /*bad*/copy ty::get(a).sty; + let bs = /*bad*/copy ty::get(b).sty; if as_ == bs { Ok(a) } else { @@ -448,7 +477,7 @@ fn super_tys( if a_id == b_id => { do self.substs(a_id, a_substs, b_substs).chain |substs| { do self.vstores(ty::terr_trait, a_vstore, b_vstore).chain |vs| { - Ok(ty::mk_trait(tcx, a_id, substs, vs)) + Ok(ty::mk_trait(tcx, a_id, /*bad*/copy substs, vs)) } } } diff --git a/src/librustc/middle/typeck/infer/floating.rs b/src/librustc/middle/typeck/infer/floating.rs deleted file mode 100644 index 9537325c097f8..0000000000000 --- a/src/librustc/middle/typeck/infer/floating.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -Code related to floating-point type inference. - -*/ - -use middle::ty::ty_float; -use middle::typeck::infer::to_str::ToStr; - -// Bitvector to represent sets of floating-point types. -pub enum float_ty_set = uint; - -// Constants representing singleton sets containing each of the floating-point -// types. -pub const FLOAT_TY_SET_EMPTY: uint = 0b000u; -pub const FLOAT_TY_SET_FLOAT: uint = 0b001u; -pub const FLOAT_TY_SET_F32: uint = 0b010u; -pub const FLOAT_TY_SET_F64: uint = 0b100u; - -pub fn float_ty_set_all() -> float_ty_set { - float_ty_set(FLOAT_TY_SET_FLOAT | FLOAT_TY_SET_F32 | FLOAT_TY_SET_F64) -} - -pub fn intersection(a: float_ty_set, b: float_ty_set) -> float_ty_set { - float_ty_set(*a & *b) -} - -pub fn single_type_contained_in(tcx: ty::ctxt, a: float_ty_set) - -> Option { - debug!("single_type_contained_in(a=%s)", uint::to_str(*a, 10)); - - if *a == FLOAT_TY_SET_FLOAT { return Some(ty::mk_float(tcx)); } - if *a == FLOAT_TY_SET_F32 { return Some(ty::mk_f32(tcx)); } - if *a == FLOAT_TY_SET_F64 { return Some(ty::mk_f64(tcx)); } - return None; -} - -pub fn convert_floating_point_ty_to_float_ty_set(tcx: ty::ctxt, t: ty::t) - -> float_ty_set { - match get(t).sty { - ty::ty_float(ast::ty_f) => float_ty_set(FLOAT_TY_SET_FLOAT), - ty::ty_float(ast::ty_f32) => float_ty_set(FLOAT_TY_SET_F32), - ty::ty_float(ast::ty_f64) => float_ty_set(FLOAT_TY_SET_F64), - _ => tcx.sess.bug(~"non-floating-point type passed to \ - convert_floating_point_ty_to_float_ty_set()") - } -} - diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index b6e179d27a91b..f53d9c3a4093c 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -8,18 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::ty; use middle::typeck::infer::combine::*; use middle::typeck::infer::lattice::*; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::sub::Sub; +use middle::typeck::infer::to_str::InferStr; + +use std::list; use syntax::ast::{Many, Once}; -enum Glb = combine_fields; // "greatest lower bound" (common subtype) +enum Glb = CombineFields; // "greatest lower bound" (common subtype) -impl Glb: combine { - fn infcx() -> infer_ctxt { self.infcx } +impl Glb: Combine { + fn infcx() -> @InferCtxt { self.infcx } fn tag() -> ~str { ~"glb" } fn a_is_expected() -> bool { self.a_is_expected } + fn span() -> span { self.span } fn sub() -> Sub { Sub(*self) } fn lub() -> Lub { Lub(*self) } @@ -82,10 +88,6 @@ impl Glb: combine { Lub(*self).tys(a, b) } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { - if p1 == p2 {Ok(p1)} else {Ok(ast::ProtoBare)} - } - fn purities(a: purity, b: purity) -> cres { match (a, b) { (pure_fn, _) | (_, pure_fn) => Ok(pure_fn), @@ -102,23 +104,11 @@ impl Glb: combine { } } - fn ret_styles(r1: ret_style, r2: ret_style) -> cres { - match (r1, r2) { - (ast::return_val, ast::return_val) => { - Ok(ast::return_val) - } - (ast::noreturn, _) | - (_, ast::noreturn) => { - Ok(ast::noreturn) - } - } - } - fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%?, %?)", self.tag(), - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); do indent { self.infcx.region_vars.glb_regions(self.span, a, b) @@ -130,7 +120,7 @@ impl Glb: combine { } fn tys(a: ty::t, b: ty::t) -> cres { - lattice_tys(&self, a, b) + super_lattice_tys(&self, a, b) } // Traits please (FIXME: #2794): @@ -152,6 +142,129 @@ impl Glb: combine { super_args(&self, a, b) } + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { + // Note: this is a subtle algorithm. For a full explanation, + // please see the large comment in `region_inference.rs`. + + debug!("%s.fn_sigs(%?, %?)", + self.tag(), a.inf_str(self.infcx), b.inf_str(self.infcx)); + let _indenter = indenter(); + + // Take a snapshot. We'll never roll this back, but in later + // phases we do want to be able to examine "all bindings that + // were created as part of this type comparison", and making a + // snapshot is a convenient way to do that. + let snapshot = self.infcx.region_vars.start_snapshot(); + + // Instantiate each bound region with a fresh region variable. + let (a_with_fresh, a_isr) = + self.infcx.replace_bound_regions_with_fresh_regions( + self.span, a); + let a_vars = var_ids(&self, a_isr); + let (b_with_fresh, b_isr) = + self.infcx.replace_bound_regions_with_fresh_regions( + self.span, b); + let b_vars = var_ids(&self, b_isr); + + // Collect constraints. + let sig0 = if_ok!(super_fn_sigs(&self, &a_with_fresh, &b_with_fresh)); + debug!("sig0 = %s", sig0.inf_str(self.infcx)); + + // Generalize the regions appearing in fn_ty0 if possible + let new_vars = + self.infcx.region_vars.vars_created_since_snapshot(snapshot); + let sig1 = + self.infcx.fold_regions_in_sig( + &sig0, + |r, _in_fn| generalize_region(&self, snapshot, + new_vars, a_isr, a_vars, b_vars, + r)); + debug!("sig1 = %s", sig1.inf_str(self.infcx)); + return Ok(move sig1); + + fn generalize_region(self: &Glb, + snapshot: uint, + new_vars: &[RegionVid], + a_isr: isr_alist, + a_vars: &[RegionVid], + b_vars: &[RegionVid], + r0: ty::Region) -> ty::Region { + if !is_var_in_set(new_vars, r0) { + return r0; + } + + let tainted = self.infcx.region_vars.tainted(snapshot, r0); + + let mut a_r = None, b_r = None, only_new_vars = true; + for tainted.each |r| { + if is_var_in_set(a_vars, *r) { + if a_r.is_some() { + return fresh_bound_variable(self); + } else { + a_r = Some(*r); + } + } else if is_var_in_set(b_vars, *r) { + if b_r.is_some() { + return fresh_bound_variable(self); + } else { + b_r = Some(*r); + } + } else if !is_var_in_set(new_vars, *r) { + only_new_vars = false; + } + } + + // NB---I do not believe this algorithm computes + // (necessarily) the GLB. As written it can + // spuriously fail. In particular, if there is a case + // like: fn(fn(&a)) and fn(fn(&b)), where a and b are + // free, it will return fn(&c) where c = GLB(a,b). If + // however this GLB is not defined, then the result is + // an error, even though something like + // "fn(fn(&X))" where X is bound would be a + // subtype of both of those. + // + // The problem is that if we were to return a bound + // variable, we'd be computing a lower-bound, but not + // necessarily the *greatest* lower-bound. + + if a_r.is_some() && b_r.is_some() && only_new_vars { + // Related to exactly one bound variable from each fn: + return rev_lookup(self, a_isr, a_r.get()); + } else if a_r.is_none() && b_r.is_none() { + // Not related to bound variables from either fn: + return r0; + } else { + // Other: + return fresh_bound_variable(self); + } + } + + fn rev_lookup(self: &Glb, + a_isr: isr_alist, + r: ty::Region) -> ty::Region + { + for list::each(a_isr) |pair| { + let (a_br, a_r) = *pair; + if a_r == r { + return ty::re_bound(a_br); + } + } + + self.infcx.tcx.sess.span_bug( + self.span, + fmt!("could not find original bound region for %?", r)); + } + + fn fresh_bound_variable(self: &Glb) -> ty::Region { + self.infcx.region_vars.new_bound() + } + } + + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + super_protos(&self, p1, p2) + } + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { super_fns(&self, a, b) } @@ -160,10 +273,6 @@ impl Glb: combine { super_fn_metas(&self, a, b) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) - } - fn substs(did: ast::def_id, as_: &ty::substs, bs: &ty::substs) -> cres { diff --git a/src/librustc/middle/typeck/infer/integral.rs b/src/librustc/middle/typeck/infer/integral.rs deleted file mode 100644 index f3e5e1ac73e62..0000000000000 --- a/src/librustc/middle/typeck/infer/integral.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/*! - -Code related to integral type inference. - -*/ - -use middle::typeck::infer::to_str::ToStr; - -// Bitvector to represent sets of integral types -enum int_ty_set = uint; - -// Constants representing singleton sets containing each of the -// integral types -const INT_TY_SET_EMPTY : uint = 0b00_0000_0000u; -const INT_TY_SET_i8 : uint = 0b00_0000_0001u; -const INT_TY_SET_u8 : uint = 0b00_0000_0010u; -const INT_TY_SET_i16 : uint = 0b00_0000_0100u; -const INT_TY_SET_u16 : uint = 0b00_0000_1000u; -const INT_TY_SET_i32 : uint = 0b00_0001_0000u; -const INT_TY_SET_u32 : uint = 0b00_0010_0000u; -const INT_TY_SET_i64 : uint = 0b00_0100_0000u; -const INT_TY_SET_u64 : uint = 0b00_1000_0000u; -const INT_TY_SET_i : uint = 0b01_0000_0000u; -const INT_TY_SET_u : uint = 0b10_0000_0000u; - -fn int_ty_set_all() -> int_ty_set { - int_ty_set(INT_TY_SET_i8 | INT_TY_SET_u8 | - INT_TY_SET_i16 | INT_TY_SET_u16 | - INT_TY_SET_i32 | INT_TY_SET_u32 | - INT_TY_SET_i64 | INT_TY_SET_u64 | - INT_TY_SET_i | INT_TY_SET_u) -} - -fn intersection(a: int_ty_set, b: int_ty_set) -> int_ty_set { - int_ty_set(*a & *b) -} - -fn single_type_contained_in(tcx: ty::ctxt, a: int_ty_set) -> - Option { - debug!("single_type_contained_in(a=%s)", uint::to_str(*a, 10u)); - - if *a == INT_TY_SET_i8 { return Some(ty::mk_i8(tcx)); } - if *a == INT_TY_SET_u8 { return Some(ty::mk_u8(tcx)); } - if *a == INT_TY_SET_i16 { return Some(ty::mk_i16(tcx)); } - if *a == INT_TY_SET_u16 { return Some(ty::mk_u16(tcx)); } - if *a == INT_TY_SET_i32 { return Some(ty::mk_i32(tcx)); } - if *a == INT_TY_SET_u32 { return Some(ty::mk_u32(tcx)); } - if *a == INT_TY_SET_i64 { return Some(ty::mk_i64(tcx)); } - if *a == INT_TY_SET_u64 { return Some(ty::mk_u64(tcx)); } - if *a == INT_TY_SET_i { return Some(ty::mk_int(tcx)); } - if *a == INT_TY_SET_u { return Some(ty::mk_uint(tcx)); } - return None; -} - -fn convert_integral_ty_to_int_ty_set(tcx: ty::ctxt, t: ty::t) - -> int_ty_set { - - match get(t).sty { - ty_int(int_ty) => match int_ty { - ast::ty_i8 => int_ty_set(INT_TY_SET_i8), - ast::ty_i16 => int_ty_set(INT_TY_SET_i16), - ast::ty_i32 => int_ty_set(INT_TY_SET_i32), - ast::ty_i64 => int_ty_set(INT_TY_SET_i64), - ast::ty_i => int_ty_set(INT_TY_SET_i), - ast::ty_char => tcx.sess.bug( - ~"char type passed to convert_integral_ty_to_int_ty_set()") - }, - ty_uint(uint_ty) => match uint_ty { - ast::ty_u8 => int_ty_set(INT_TY_SET_u8), - ast::ty_u16 => int_ty_set(INT_TY_SET_u16), - ast::ty_u32 => int_ty_set(INT_TY_SET_u32), - ast::ty_u64 => int_ty_set(INT_TY_SET_u64), - ast::ty_u => int_ty_set(INT_TY_SET_u) - }, - _ => tcx.sess.bug(~"non-integral type passed to \ - convert_integral_ty_to_int_ty_set()") - } -} diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index b47dd2064522e..f02e3328afaf9 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -8,9 +8,295 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! + * + * # Lattice Variables + * + * This file contains generic code for operating on inference variables + * that are characterized by an upper- and lower-bound. The logic and + * reasoning is explained in detail in the large comment in `infer.rs`. + * + * The code in here is defined quite generically so that it can be + * applied both to type variables, which represent types being inferred, + * and fn variables, which represent function types being inferred. + * It may eventually be applied to ther types as well, who knows. + * In some cases, the functions are also generic with respect to the + * operation on the lattice (GLB vs LUB). + * + * Although all the functions are generic, we generally write the + * comments in a way that is specific to type variables and the LUB + * operation. It's just easier that way. + * + * In general all of the functions are defined parametrically + * over a `LatticeValue`, which is a value defined with respect to + * a lattice. + */ + +use middle::ty; use middle::typeck::infer::combine::*; use middle::typeck::infer::unify::*; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::sub::Sub; +use middle::typeck::infer::lub::Lub; +use middle::typeck::infer::glb::Glb; +use middle::typeck::infer::to_str::InferStr; +use core::either::{Either, Left, Right}; + +use std::list; + +trait LatticeValue { + static fn sub(cf: &CombineFields, a: &self, b: &self) -> ures; + static fn lub(cf: &CombineFields, a: &self, b: &self) -> cres; + static fn glb(cf: &CombineFields, a: &self, b: &self) -> cres; +} + +type LatticeOp = &fn(cf: &CombineFields, a: &T, b: &T) -> cres; + +impl ty::t: LatticeValue { + static fn sub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> ures { + Sub(*cf).tys(*a, *b).to_ures() + } + + static fn lub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres { + Lub(*cf).tys(*a, *b) + } + + static fn glb(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres { + Glb(*cf).tys(*a, *b) + } +} + +impl FnMeta: LatticeValue { + static fn sub(cf: &CombineFields, + a: &FnMeta, b: &FnMeta) -> ures { + Sub(*cf).fn_metas(a, b).to_ures() + } + + static fn lub(cf: &CombineFields, + a: &FnMeta, b: &FnMeta) -> cres { + Lub(*cf).fn_metas(a, b) + } + + static fn glb(cf: &CombineFields, + a: &FnMeta, b: &FnMeta) -> cres { + Glb(*cf).fn_metas(a, b) + } +} + +impl CombineFields { + fn var_sub_var( + &self, + vb: &ValsAndBindings>, + +a_id: V, + +b_id: V) -> ures + { + /*! + * + * Make one variable a subtype of another variable. This is a + * subtle and tricky process, as described in detail at the + * top of infer.rs*/ + + // Need to make sub_id a subtype of sup_id. + let node_a = self.infcx.get(vb, a_id); + let node_b = self.infcx.get(vb, b_id); + let a_id = node_a.root; + let b_id = node_b.root; + let a_bounds = node_a.possible_types; + let b_bounds = node_b.possible_types; + + debug!("vars(%s=%s <: %s=%s)", + a_id.to_str(), a_bounds.inf_str(self.infcx), + b_id.to_str(), b_bounds.inf_str(self.infcx)); + + if a_id == b_id { return uok(); } + + // If both A's UB and B's LB have already been bound to types, + // see if we can make those types subtypes. + match (a_bounds.ub, b_bounds.lb) { + (Some(ref a_ub), Some(ref b_lb)) => { + let r = self.infcx.try( + || LatticeValue::sub(self, a_ub, b_lb)); + match r { + Ok(()) => { + return Ok(()); + } + Err(_) => { /*fallthrough */ } + } + } + _ => { /*fallthrough*/ } + } + + // Otherwise, we need to merge A and B so as to guarantee that + // A remains a subtype of B. Actually, there are other options, + // but that's the route we choose to take. + + self.infcx.unify(vb, &node_a, &node_b, |new_root, new_rank| { + self.set_var_to_merged_bounds(vb, new_root, + &a_bounds, &b_bounds, + new_rank) + }) + } + + /// make variable a subtype of T + fn var_sub_t( + &self, + vb: &ValsAndBindings>, + +a_id: V, + +b: T) -> ures + { + /*! + * + * Make a variable (`a_id`) a subtype of the concrete type `b` */ + + let node_a = self.infcx.get(vb, a_id); + let a_id = node_a.root; + let a_bounds = &node_a.possible_types; + let b_bounds = &{lb: None, ub: Some(b)}; + + debug!("var_sub_t(%s=%s <: %s)", + a_id.to_str(), + a_bounds.inf_str(self.infcx), + b.inf_str(self.infcx)); + + self.set_var_to_merged_bounds( + vb, a_id, a_bounds, b_bounds, node_a.rank) + } + + fn t_sub_var( + &self, + vb: &ValsAndBindings>, + +a: T, + +b_id: V) -> ures + { + /*! + * + * Make a concrete type (`a`) a subtype of the variable `b_id` */ + + let a_bounds = &{lb: Some(a), ub: None}; + let node_b = self.infcx.get(vb, b_id); + let b_id = node_b.root; + let b_bounds = &node_b.possible_types; + + debug!("t_sub_var(%s <: %s=%s)", + a.inf_str(self.infcx), + b_id.to_str(), + b_bounds.inf_str(self.infcx)); + + self.set_var_to_merged_bounds( + vb, b_id, a_bounds, b_bounds, node_b.rank) + } + + fn merge_bnd( + &self, + a: &Bound, + b: &Bound, + lattice_op: LatticeOp) + -> cres> + { + /*! + * + * Combines two bounds into a more general bound. */ + + debug!("merge_bnd(%s,%s)", + a.inf_str(self.infcx), + b.inf_str(self.infcx)); + let _r = indenter(); + + match (*a, *b) { + (None, None) => Ok(None), + (Some(_), None) => Ok(*a), + (None, Some(_)) => Ok(*b), + (Some(ref v_a), Some(ref v_b)) => { + do lattice_op(self, v_a, v_b).chain |v| { + Ok(Some(v)) + } + } + } + } + + fn set_var_to_merged_bounds( + &self, + vb: &ValsAndBindings>, + +v_id: V, + a: &Bounds, + b: &Bounds, + rank: uint) -> ures + { + /*! + * + * Updates the bounds for the variable `v_id` to be the intersection + * of `a` and `b`. That is, the new bounds for `v_id` will be + * a bounds c such that: + * c.ub <: a.ub + * c.ub <: b.ub + * a.lb <: c.lb + * b.lb <: c.lb + * If this cannot be achieved, the result is failure. */ + + // Think of the two diamonds, we want to find the + // intersection. There are basically four possibilities (you + // can swap A/B in these pictures): + // + // A A + // / \ / \ + // / B \ / B \ + // / / \ \ / / \ \ + // * * * * * / * * + // \ \ / / \ / / + // \ B / / \ / / + // \ / * \ / + // A \ / A + // B + + debug!("merge(%s,%s,%s)", + v_id.to_str(), + a.inf_str(self.infcx), + b.inf_str(self.infcx)); + let _indent = indenter(); + + // First, relate the lower/upper bounds of A and B. + // Note that these relations *must* hold for us to + // to be able to merge A and B at all, and relating + // them explicitly gives the type inferencer more + // information and helps to produce tighter bounds + // when necessary. + let () = if_ok!(self.bnds(&a.lb, &b.ub)); + let () = if_ok!(self.bnds(&b.lb, &a.ub)); + let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb)); + let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub)); + let bounds = {lb: lb, ub: ub}; + debug!("merge(%s): bounds=%s", + v_id.to_str(), + bounds.inf_str(self.infcx)); + + // the new bounds must themselves + // be relatable: + let () = if_ok!(self.bnds(&bounds.lb, &bounds.ub)); + self.infcx.set(vb, v_id, Root(bounds, rank)); + uok() + } + + fn bnds( + &self, + a: &Bound, + b: &Bound) -> ures + { + debug!("bnds(%s <: %s)", a.inf_str(self.infcx), + b.inf_str(self.infcx)); + let _r = indenter(); + + match (*a, *b) { + (None, None) | + (Some(_), None) | + (None, Some(_)) => { + uok() + } + (Some(ref t_a), Some(ref t_b)) => { + LatticeValue::sub(self, t_a, t_b) + } + } + } +} // ______________________________________________________________________ // Lattice operations on variables @@ -18,141 +304,210 @@ use middle::typeck::infer::to_str::ToStr; // This is common code used by both LUB and GLB to compute the LUB/GLB // for pairs of variables or for variables and values. -trait lattice_ops { - fn bnd(b: bounds) -> Option; - fn with_bnd(b: bounds, t: ty::t) -> bounds; +trait LatticeDir { + fn combine_fields() -> CombineFields; + fn bnd(b: &Bounds) -> Option; + fn with_bnd(b: &Bounds, +t: T) -> Bounds; +} + +trait TyLatticeDir { fn ty_bot(t: ty::t) -> cres; } -impl Lub: lattice_ops { - fn bnd(b: bounds) -> Option { b.ub } - fn with_bnd(b: bounds, t: ty::t) -> bounds { - {ub: Some(t),.. b} +impl Lub: LatticeDir { + fn combine_fields() -> CombineFields { *self } + fn bnd(b: &Bounds) -> Option { b.ub } + fn with_bnd(b: &Bounds, +t: T) -> Bounds { + {ub: Some(t), ..*b} } +} + +impl Lub: TyLatticeDir { fn ty_bot(t: ty::t) -> cres { Ok(t) } } -impl Glb: lattice_ops { - fn bnd(b: bounds) -> Option { b.lb } - fn with_bnd(b: bounds, t: ty::t) -> bounds { - {lb: Some(t),.. b} +impl Glb: LatticeDir { + fn combine_fields() -> CombineFields { *self } + fn bnd(b: &Bounds) -> Option { b.lb } + fn with_bnd(b: &Bounds, +t: T) -> Bounds { + {lb: Some(t), ..*b} } +} + +impl Glb: TyLatticeDir { fn ty_bot(_t: ty::t) -> cres { Ok(ty::mk_bot(self.infcx.tcx)) } } -fn lattice_tys( - self: &L, a: ty::t, b: ty::t) -> cres { - +fn super_lattice_tys( + self: &L, + a: ty::t, + b: ty::t) -> cres +{ debug!("%s.lattice_tys(%s, %s)", self.tag(), - a.to_str(self.infcx()), - b.to_str(self.infcx())); - if a == b { return Ok(a); } - do indent { - match (ty::get(a).sty, ty::get(b).sty) { - (ty::ty_bot, _) => self.ty_bot(b), - (_, ty::ty_bot) => self.ty_bot(a), - - (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { - lattice_vars(self, a, a_id, b_id, - |x, y| self.tys(x, y) ) - } - - (ty::ty_infer(TyVar(a_id)), _) => { - lattice_var_and_t(self, a_id, b, - |x, y| self.tys(x, y) ) - } - - (_, ty::ty_infer(TyVar(b_id))) => { - lattice_var_and_t(self, b_id, a, - |x, y| self.tys(x, y) ) - } - _ => { - super_tys(self, a, b) - } + a.inf_str(self.infcx()), + b.inf_str(self.infcx())); + let _r = indenter(); + + if a == b { + return Ok(a); + } + + let tcx = self.infcx().tcx; + + match (ty::get(a).sty, ty::get(b).sty) { + (ty::ty_bot, _) => { return self.ty_bot(b); } + (_, ty::ty_bot) => { return self.ty_bot(a); } + + (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { + let r = if_ok!(lattice_vars(self, &self.infcx().ty_var_bindings, + a_id, b_id, + |x, y| self.tys(*x, *y))); + return match r { + Left(v) => Ok(ty::mk_var(tcx, v)), + Right(t) => Ok(t) + }; + } + + (ty::ty_infer(TyVar(a_id)), _) => { + return lattice_var_and_t(self, &self.infcx().ty_var_bindings, + a_id, &b, + |x, y| self.tys(*x, *y)); + } + + (_, ty::ty_infer(TyVar(b_id))) => { + return lattice_var_and_t(self, &self.infcx().ty_var_bindings, + b_id, &a, + |x, y| self.tys(*x, *y)); + } + + _ => { + return super_tys(self, a, b); } } } -fn lattice_vars( - self: &L, +a_t: ty::t, +a_vid: ty::TyVid, +b_vid: ty::TyVid, - c_ts: fn(ty::t, ty::t) -> cres) -> cres { +type LatticeDirOp = &fn(a: &T, b: &T) -> cres; +fn lattice_vars( + self: &L, + vb: &ValsAndBindings>, + +a_vid: V, + +b_vid: V, + lattice_dir_op: LatticeDirOp) + -> cres> +{ // The comments in this function are written for LUB and types, // but they apply equally well to GLB and regions if you inverse // upper/lower/sub/super/etc. // Need to find a type that is a supertype of both a and b: - let vb = &self.infcx().ty_var_bindings; let nde_a = self.infcx().get(vb, a_vid); let nde_b = self.infcx().get(vb, b_vid); let a_vid = nde_a.root; let b_vid = nde_b.root; - let a_bounds = nde_a.possible_types; - let b_bounds = nde_b.possible_types; + let a_bounds = &nde_a.possible_types; + let b_bounds = &nde_b.possible_types; debug!("%s.lattice_vars(%s=%s <: %s=%s)", self.tag(), - a_vid.to_str(), a_bounds.to_str(self.infcx()), - b_vid.to_str(), b_bounds.to_str(self.infcx())); + a_vid.to_str(), a_bounds.inf_str(self.infcx()), + b_vid.to_str(), b_bounds.inf_str(self.infcx())); if a_vid == b_vid { - return Ok(a_t); + return Ok(Left(a_vid)); } // If both A and B have an UB type, then we can just compute the // LUB of those types: let a_bnd = self.bnd(a_bounds), b_bnd = self.bnd(b_bounds); match (a_bnd, b_bnd) { - (Some(a_ty), Some(b_ty)) => { - match self.infcx().try(|| c_ts(a_ty, b_ty) ) { - Ok(t) => return Ok(t), - Err(_) => { /*fallthrough */ } + (Some(ref a_ty), Some(ref b_ty)) => { + match self.infcx().try(|| lattice_dir_op(a_ty, b_ty) ) { + Ok(t) => return Ok(Right(t)), + Err(_) => { /*fallthrough */ } + } } - } - _ => {/*fallthrough*/} + _ => {/*fallthrough*/} } // Otherwise, we need to merge A and B into one variable. We can // then use either variable as an upper bound: - var_sub_var(self, a_vid, b_vid).then(|| Ok(a_t) ) + let cf = self.combine_fields(); + do cf.var_sub_var(vb, a_vid, b_vid).then { + Ok(Left(a_vid)) + } } -fn lattice_var_and_t( - self: &L, a_id: ty::TyVid, b: ty::t, - c_ts: fn(ty::t, ty::t) -> cres) -> cres { - - let vb = &self.infcx().ty_var_bindings; +fn lattice_var_and_t( + self: &L, + vb: &ValsAndBindings>, + +a_id: V, + b: &T, + lattice_dir_op: LatticeDirOp) + -> cres +{ let nde_a = self.infcx().get(vb, a_id); let a_id = nde_a.root; - let a_bounds = nde_a.possible_types; + let a_bounds = &nde_a.possible_types; // The comments in this function are written for LUB, but they // apply equally well to GLB if you inverse upper/lower/sub/super/etc. debug!("%s.lattice_var_and_t(%s=%s <: %s)", self.tag(), - a_id.to_str(), a_bounds.to_str(self.infcx()), - b.to_str(self.infcx())); + a_id.to_str(), + a_bounds.inf_str(self.infcx()), + b.inf_str(self.infcx())); match self.bnd(a_bounds) { - Some(a_bnd) => { - // If a has an upper bound, return the LUB(a.ub, b) - debug!("bnd=some(%s)", a_bnd.to_str(self.infcx())); - return c_ts(a_bnd, b); - } - None => { - // If a does not have an upper bound, make b the upper bound of a - // and then return b. - debug!("bnd=none"); - let a_bounds = self.with_bnd(a_bounds, b); - do bnds(self, a_bounds.lb, a_bounds.ub).then { - self.infcx().set(vb, a_id, root(a_bounds, nde_a.rank)); - Ok(b) + Some(ref a_bnd) => { + // If a has an upper bound, return the LUB(a.ub, b) + debug!("bnd=some(%s)", a_bnd.inf_str(self.infcx())); + lattice_dir_op(a_bnd, b) + } + None => { + // If a does not have an upper bound, make b the upper bound of a + // and then return b. + debug!("bnd=none"); + let a_bounds = self.with_bnd(a_bounds, *b); + do self.combine_fields().bnds(&a_bounds.lb, &a_bounds.ub).then { + self.infcx().set(vb, a_id, Root(a_bounds, nde_a.rank)); + Ok(*b) + } + } + } +} + +// ___________________________________________________________________________ +// Random utility functions used by LUB/GLB when computing LUB/GLB of +// fn types + +fn var_ids(self: &T, isr: isr_alist) -> ~[RegionVid] { + let mut result = ~[]; + for list::each(isr) |pair| { + match pair.second() { + ty::re_infer(ty::ReVar(r)) => { result.push(r); } + r => { + self.infcx().tcx.sess.span_bug( + self.span(), + fmt!("Found non-region-vid: %?", r)); + } } - } + } + return result; +} + +fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool { + match r { + ty::re_infer(ty::ReVar(ref v)) => new_vars.contains(v), + _ => false } } diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index cfb93e93a65ba..f9e8c9d370c4f 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -8,25 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::ty; use middle::typeck::infer::combine::*; use middle::typeck::infer::lattice::*; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::sub::Sub; +use middle::typeck::infer::to_str::InferStr; +use std::list; use syntax::ast::{Many, Once}; fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. -enum Lub = combine_fields; // "subtype", "subregion" etc +enum Lub = CombineFields; // least-upper-bound: common supertype impl Lub { fn bot_ty(b: ty::t) -> cres { Ok(b) } fn ty_bot(b: ty::t) -> cres { self.bot_ty(b) } // commutative } -impl Lub: combine { - fn infcx() -> infer_ctxt { self.infcx } +impl Lub: Combine { + fn infcx() -> @InferCtxt { self.infcx } fn tag() -> ~str { ~"lub" } fn a_is_expected() -> bool { self.a_is_expected } + fn span() -> span { self.span } fn sub() -> Sub { Sub(*self) } fn lub() -> Lub { Lub(*self) } @@ -69,15 +74,6 @@ impl Lub: combine { Glb(*self).tys(a, b) } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { - match (p1, p2) { - (ast::ProtoBare, _) => Ok(p2), - (_, ast::ProtoBare) => Ok(p1), - _ if p1 == p2 => Ok(p1), - _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) - } - } - fn purities(a: purity, b: purity) -> cres { match (a, b) { (unsafe_fn, _) | (_, unsafe_fn) => Ok(unsafe_fn), @@ -94,14 +90,6 @@ impl Lub: combine { } } - fn ret_styles(r1: ret_style, r2: ret_style) -> cres { - match (r1, r2) { - (ast::return_val, _) | - (_, ast::return_val) => Ok(ast::return_val), - (ast::noreturn, ast::noreturn) => Ok(ast::noreturn) - } - } - fn contraregions(a: ty::Region, b: ty::Region) -> cres { return Glb(*self).regions(a, b); } @@ -109,15 +97,15 @@ impl Lub: combine { fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%?, %?)", self.tag(), - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); do indent { self.infcx.region_vars.lub_regions(self.span, a, b) } } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { // Note: this is a subtle algorithm. For a full explanation, // please see the large comment in `region_inference.rs`. @@ -136,20 +124,18 @@ impl Lub: combine { self.span, b); // Collect constraints. - let fn_ty0 = if_ok!(super_fns(&self, &a_with_fresh, &b_with_fresh)); - debug!("fn_ty0 = %s", fn_ty0.to_str(self.infcx)); + let sig0 = if_ok!(super_fn_sigs(&self, &a_with_fresh, &b_with_fresh)); + debug!("sig0 = %s", sig0.inf_str(self.infcx)); - // Generalize the regions appearing in fn_ty0 if possible + // Generalize the regions appearing in sig0 if possible let new_vars = self.infcx.region_vars.vars_created_since_snapshot(snapshot); - let fn_ty1 = - ty::apply_op_on_t_to_ty_fn( - self.infcx.tcx, &fn_ty0, - |t| ty::fold_regions( - self.infcx.tcx, t, - |r, _in_fn| generalize_region(&self, snapshot, - new_vars, a_isr, r))); - return Ok(move fn_ty1); + let sig1 = + self.infcx.fold_regions_in_sig( + &sig0, + |r, _in_fn| generalize_region(&self, snapshot, new_vars, + a_isr, r)); + return Ok(move sig1); fn generalize_region(self: &Lub, snapshot: uint, @@ -157,7 +143,7 @@ impl Lub: combine { a_isr: isr_alist, r0: ty::Region) -> ty::Region { // Regions that pre-dated the LUB computation stay as they are. - if !is_new_var(new_vars, r0) { + if !is_var_in_set(new_vars, r0) { debug!("generalize_region(r0=%?): not new variable", r0); return r0; } @@ -167,7 +153,7 @@ impl Lub: combine { // Variables created during LUB computation which are // *related* to regions that pre-date the LUB computation // stay as they are. - if !tainted.all(|r| is_new_var(new_vars, *r)) { + if !tainted.all(|r| is_var_in_set(new_vars, *r)) { debug!("generalize_region(r0=%?): \ non-new-variables found in %?", r0, tainted); @@ -194,27 +180,24 @@ impl Lub: combine { fmt!("Region %? is not associated with \ any bound region from A!", r0)); } + } - fn is_new_var(new_vars: &[RegionVid], r: ty::Region) -> bool { - match r { - ty::re_infer(ty::ReVar(ref v)) => new_vars.contains(v), - _ => false - } - } + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + super_fns(&self, a, b) } fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { super_fn_metas(&self, a, b) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) - } - // Traits please (FIXME: #2794): + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + super_protos(&self, p1, p2) + } + fn tys(a: ty::t, b: ty::t) -> cres { - lattice_tys(&self, a, b) + super_lattice_tys(&self, a, b) } fn flds(a: ty::field, b: ty::field) -> cres { diff --git a/src/librustc/middle/typeck/infer/macros.rs b/src/librustc/middle/typeck/infer/macros.rs index 616df1e72c5b1..8cccf75d6dc4e 100644 --- a/src/librustc/middle/typeck/infer/macros.rs +++ b/src/librustc/middle/typeck/infer/macros.rs @@ -19,4 +19,4 @@ macro_rules! if_ok( ) ); -} \ No newline at end of file +} diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index fb8ca5632910e..fd31b6aff39bf 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -197,29 +197,16 @@ is valid. This basically corresponds to the block nesting structure: the regions for outer block scopes are superregions of those for inner block scopes. -## Integral type variables +## Integral and floating-point type variables There is a third variety of type variable that we use only for inferring the types of unsuffixed integer literals. Integral type variables differ from general-purpose type variables in that there's no subtyping relationship among the various integral types, so instead -of associating each variable with an upper and lower bound, we -represent the set of possible integral types it can take on with an -`int_ty_set`, which is a bitvector with one bit for each integral -type. Because intersecting these sets with each other is simpler than -merging bounds, we don't need to do so transactionally as we do for -general-purpose type variables. - -We could conceivably define a subtyping relationship among integral -types based on their ranges, but we choose not to open that particular -can of worms. Our strategy is to treat integral type variables as -unknown until the typing context constrains them to a unique integral -type, at which point they take on that type. If the typing context -overconstrains the type, it's a type error; if we reach the point at -which type variables must be resolved and an integral type variable is -still underconstrained, it defaults to `int` as a last resort. - -Floating point types are handled similarly to integral types. +of associating each variable with an upper and lower bound, we just +use simple unification. Each integer variable is associated with at +most one integer type. Floating point types are handled similarly to +integral types. ## GLB/LUB @@ -259,16 +246,14 @@ section on "Type Combining" below for details. #[warn(deprecated_mode)]; #[warn(deprecated_pattern)]; -use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, vid}; +use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, Vid}; use middle::ty::{mk_fn, type_is_bot}; use middle::ty::{ty_int, ty_uint, get, terr_fn, TyVar, IntVar, FloatVar}; use middle::ty; -use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_ty}; +use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig}; use middle::typeck::infer::assignment::Assign; -use middle::typeck::infer::combine::{combine_fields, eq_tys}; -use middle::typeck::infer::floating::{float_ty_set, float_ty_set_all}; +use middle::typeck::infer::combine::{CombineFields, eq_tys}; use middle::typeck::infer::glb::Glb; -use middle::typeck::infer::integral::{int_ty_set, int_ty_set_all}; use middle::typeck::infer::lub::Lub; use middle::typeck::infer::region_inference::{RegionVarBindings}; use middle::typeck::infer::resolve::{force_all, not_regions}; @@ -278,14 +263,16 @@ use middle::typeck::infer::resolve::{resolve_ivar, resolve_all}; use middle::typeck::infer::resolve::{resolve_nested_tvar, resolve_rvar}; use middle::typeck::infer::resolve::{resolver}; use middle::typeck::infer::sub::Sub; -use middle::typeck::infer::to_str::ToStr; -use middle::typeck::infer::unify::{vals_and_bindings, root}; +use middle::typeck::infer::to_str::InferStr; +use middle::typeck::infer::unify::{ValsAndBindings, Root}; use util::common::{indent, indenter}; use util::ppaux::{ty_to_str, mt_to_str}; use core::cmp::Eq; use core::dvec::DVec; use core::result::{Result, Ok, Err, map_vec, map_vec2, iter_vec2}; +use core::result; +use core::vec; use std::map::HashMap; use std::smallintmap; use syntax::ast::{ret_style, purity}; @@ -294,7 +281,7 @@ use syntax::ast::{unsafe_fn, impure_fn, pure_fn, extern_fn}; use syntax::ast_util::dummy_sp; use syntax::{ast, ast_util}; -export infer_ctxt; +export InferCtxt; export new_infer_ctxt; export mk_subty, can_mk_subty; export mk_subr; @@ -305,15 +292,12 @@ export force_tvar, force_rvar, force_ivar, force_all; export resolve_and_force_all_but_regions, not_regions; export resolve_type, resolve_region; export resolve_borrowings; -export methods; // for infer_ctxt -export unify_methods; // for infer_ctxt export cres, fres, fixup_err, fixup_err_to_str; export assignment; export root, to_str; export int_ty_set_all; export assignment; export combine; -export floating; export glb; export integral; export lattice; @@ -331,9 +315,6 @@ mod combine; #[legacy_exports] mod glb; #[legacy_exports] -mod integral; -mod floating; -#[legacy_exports] mod lattice; #[legacy_exports] mod lub; @@ -348,39 +329,48 @@ mod to_str; #[legacy_exports] mod unify; -type bound = Option; -type bounds = {lb: bound, ub: bound}; +type Bound = Option; +type Bounds = {lb: Bound, ub: Bound}; type cres = Result; // "combine result" type ures = cres<()>; // "unify result" type fres = Result; // "fixup result" type ares = cres>; // "assignment result" -enum infer_ctxt = @{ +#[deriving_eq] +enum IntVarValue { + IntType(ast::int_ty), + UintType(ast::uint_ty), +} + +struct InferCtxt { tcx: ty::ctxt, - // We instantiate vals_and_bindings with bounds because the + // We instantiate ValsAndBindings with bounds because the // types that might instantiate a general type variable have an // order, represented by its upper and lower bounds. - ty_var_bindings: vals_and_bindings>, + ty_var_bindings: ValsAndBindings>, + + // Number of type variables created thus far. + mut ty_var_counter: uint, // The types that might instantiate an integral type variable are // represented by an int_ty_set. - int_var_bindings: vals_and_bindings, + int_var_bindings: ValsAndBindings>, + + // Number of integral variables created thus far. + mut int_var_counter: uint, // The types that might instantiate a floating-point type variable are // represented by an float_ty_set. - float_var_bindings: vals_and_bindings, + float_var_bindings: ValsAndBindings>, + + // Number of floating-point variables created thus far. + mut float_var_counter: uint, // For region variables. region_vars: RegionVarBindings, - - // For keeping track of existing type and region variables. - ty_var_counter: @mut uint, - int_var_counter: @mut uint, - float_var_counter: @mut uint, - region_var_counter: @mut uint -}; +} enum fixup_err { unresolved_int_ty(IntVid), @@ -403,27 +393,33 @@ fn fixup_err_to_str(f: fixup_err) -> ~str { } } -fn new_vals_and_bindings() -> vals_and_bindings { - vals_and_bindings { +fn new_ValsAndBindings() -> ValsAndBindings { + ValsAndBindings { vals: smallintmap::mk(), mut bindings: ~[] } } -fn new_infer_ctxt(tcx: ty::ctxt) -> infer_ctxt { - infer_ctxt(@{tcx: tcx, - ty_var_bindings: new_vals_and_bindings(), - int_var_bindings: new_vals_and_bindings(), - float_var_bindings: new_vals_and_bindings(), - region_vars: RegionVarBindings(tcx), - ty_var_counter: @mut 0u, - int_var_counter: @mut 0u, - float_var_counter: @mut 0u, - region_var_counter: @mut 0u})} - -fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span, +fn new_infer_ctxt(tcx: ty::ctxt) -> @InferCtxt { + @InferCtxt { + tcx: tcx, + + ty_var_bindings: new_ValsAndBindings(), + ty_var_counter: 0, + + int_var_bindings: new_ValsAndBindings(), + int_var_counter: 0, + + float_var_bindings: new_ValsAndBindings(), + float_var_counter: 0, + + region_vars: RegionVarBindings(tcx), + } +} + +fn mk_subty(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::t, b: ty::t) -> ures { - debug!("mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_subty(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { cx.sub(a_is_expected, span).tys(a, b) @@ -431,8 +427,8 @@ fn mk_subty(cx: infer_ctxt, a_is_expected: bool, span: span, }.to_ures() } -fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { - debug!("can_mk_subty(%s <: %s)", a.to_str(cx), b.to_str(cx)); +fn can_mk_subty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures { + debug!("can_mk_subty(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.probe { cx.sub(true, ast_util::dummy_sp()).tys(a, b) @@ -440,9 +436,9 @@ fn can_mk_subty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { }.to_ures() } -fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span, +fn mk_subr(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::Region, b: ty::Region) -> ures { - debug!("mk_subr(%s <: %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_subr(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { cx.sub(a_is_expected, span).regions(a, b) @@ -450,9 +446,9 @@ fn mk_subr(cx: infer_ctxt, a_is_expected: bool, span: span, }.to_ures() } -fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span, +fn mk_eqty(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::t, b: ty::t) -> ures { - debug!("mk_eqty(%s <: %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_eqty(%s <: %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { let suber = cx.sub(a_is_expected, span); @@ -461,9 +457,9 @@ fn mk_eqty(cx: infer_ctxt, a_is_expected: bool, span: span, }.to_ures() } -fn mk_assignty(cx: infer_ctxt, a_is_expected: bool, span: span, +fn mk_assignty(cx: @InferCtxt, a_is_expected: bool, span: span, a: ty::t, b: ty::t) -> ares { - debug!("mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx)); + debug!("mk_assignty(%s -> %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.commit { Assign(cx.combine_fields(a_is_expected, span)).tys(a, b) @@ -471,8 +467,8 @@ fn mk_assignty(cx: infer_ctxt, a_is_expected: bool, span: span, } } -fn can_mk_assignty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { - debug!("can_mk_assignty(%s -> %s)", a.to_str(cx), b.to_str(cx)); +fn can_mk_assignty(cx: @InferCtxt, a: ty::t, b: ty::t) -> ures { + debug!("can_mk_assignty(%s -> %s)", a.inf_str(cx), b.inf_str(cx)); do indent { do cx.probe { let span = ast_util::dummy_sp(); @@ -482,18 +478,18 @@ fn can_mk_assignty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures { } // See comment on the type `resolve_state` below -fn resolve_type(cx: infer_ctxt, a: ty::t, modes: uint) +fn resolve_type(cx: @InferCtxt, a: ty::t, modes: uint) -> fres { resolver(cx, modes).resolve_type_chk(a) } -fn resolve_region(cx: infer_ctxt, r: ty::Region, modes: uint) +fn resolve_region(cx: @InferCtxt, r: ty::Region, modes: uint) -> fres { resolver(cx, modes).resolve_region_chk(r) } /* -fn resolve_borrowings(cx: infer_ctxt) { +fn resolve_borrowings(cx: @InferCtxt) { for cx.borrowings.each |item| { match resolve_region(cx, item.scope, resolve_all|force_all) { Ok(region) => { @@ -559,9 +555,10 @@ fn uok() -> ures { Ok(()) } -fn rollback_to( - vb: &vals_and_bindings, len: uint) { - +fn rollback_to( + vb: &ValsAndBindings, + len: uint) +{ while vb.bindings.len() != len { let (vid, old_v) = vb.bindings.pop(); vb.vals.insert(vid.to_uint(), old_v); @@ -574,12 +571,12 @@ struct Snapshot { region_vars_snapshot: uint, } -impl infer_ctxt { +impl @InferCtxt { fn combine_fields(a_is_expected: bool, - span: span) -> combine_fields { - combine_fields {infcx: self, - a_is_expected: a_is_expected, - span: span} + span: span) -> CombineFields { + CombineFields {infcx: self, + a_is_expected: a_is_expected, + span: span} } fn sub(a_is_expected: bool, span: span) -> Sub { @@ -609,8 +606,7 @@ impl infer_ctxt { //rollback_to(&self.int_var_bindings, // snapshot.int_var_bindings_len); - self.region_vars.rollback_to( - snapshot.region_vars_snapshot); + self.region_vars.rollback_to(snapshot.region_vars_snapshot); } /// Execute `f` and commit the bindings if successful @@ -654,12 +650,12 @@ impl infer_ctxt { } } -impl infer_ctxt { +impl @InferCtxt { fn next_ty_var_id() -> TyVid { - let id = *self.ty_var_counter; - *self.ty_var_counter += 1u; + let id = self.ty_var_counter; + self.ty_var_counter += 1; self.ty_var_bindings.vals.insert(id, - root({lb: None, ub: None}, 0u)); + Root({lb: None, ub: None}, 0u)); return TyVid(id); } @@ -672,11 +668,10 @@ impl infer_ctxt { } fn next_int_var_id() -> IntVid { - let id = *self.int_var_counter; - *self.int_var_counter += 1u; + let id = self.int_var_counter; + self.int_var_counter += 1; - self.int_var_bindings.vals.insert(id, - root(int_ty_set_all(), 0u)); + self.int_var_bindings.vals.insert(id, Root(None, 0)); return IntVid(id); } @@ -685,10 +680,10 @@ impl infer_ctxt { } fn next_float_var_id() -> FloatVid { - let id = *self.float_var_counter; - *self.float_var_counter += 1; + let id = self.float_var_counter; + self.float_var_counter += 1; - self.float_var_bindings.vals.insert(id, root(float_ty_set_all(), 0)); + self.float_var_bindings.vals.insert(id, Root(None, 0)); return FloatVid(id); } @@ -735,10 +730,19 @@ impl infer_ctxt { fn type_error_message(sp: span, mk_msg: fn(~str) -> ~str, actual_ty: ty::t, err: Option<&ty::type_err>) { let actual_ty = self.resolve_type_vars_if_possible(actual_ty); + let mut actual_sty = ty::get(copy actual_ty); // Don't report an error if actual type is ty_err. - match ty::get(actual_ty).sty { + match actual_sty.sty { ty::ty_err => return, + // Should really not report an error if the type + // has ty_err anywhere as a component, but that's + // annoying since we haven't written a visitor for + // ty::t yet + ty::ty_fn(ref fty) => match ty::get(fty.sig.output).sty { + ty::ty_err => return, + _ => () + }, _ => () } let error_str = err.map_default(~"", |t_err| @@ -771,10 +775,10 @@ impl infer_ctxt { fn replace_bound_regions_with_fresh_regions( &self, span: span, - fty: &ty::FnTy) -> (ty::FnTy, isr_alist) + fsig: &ty::FnSig) -> (ty::FnSig, isr_alist) { - let {fn_ty: fn_ty, isr: isr, _} = - replace_bound_regions_in_fn_ty(self.tcx, @Nil, None, fty, |br| { + let {fn_sig: fn_sig, isr: isr, _} = + replace_bound_regions_in_fn_sig(self.tcx, @Nil, None, fsig, |br| { // N.B.: The name of the bound region doesn't have anything to // do with the region variable that's created for it. The // only thing we're doing with `br` here is using it in the @@ -785,7 +789,17 @@ impl infer_ctxt { rvar); rvar }); - (fn_ty, isr) + (fn_sig, isr) + } + + fn fold_regions_in_sig( + &self, + fn_sig: &ty::FnSig, + fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig + { + do ty::fold_sig(fn_sig) |t| { + ty::fold_regions(self.tcx, t, fldr) + } } } diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs index 99d636559dbc2..d45fd31ebae4b 100644 --- a/src/librustc/middle/typeck/infer/region_inference.rs +++ b/src/librustc/middle/typeck/infer/region_inference.rs @@ -337,6 +337,61 @@ therefore considering subtyping and in particular does not consider LUB or GLB computation. We have to consider this. Here is the algorithm I implemented. +First though, let's discuss what we are trying to compute in more +detail. The LUB is basically the "common supertype" and the GLB is +"common subtype"; one catch is that the LUB should be the +*most-specific* common supertype and the GLB should be *most general* +common subtype (as opposed to any common supertype or any common +subtype). + +Anyway, to help clarify, here is a table containing some +function pairs and their LUB/GLB: + +``` +Type 1 Type 2 LUB GLB +fn(&a) fn(&X) fn(&X) fn(&a) +fn(&A) fn(&X) -- fn(&a) +fn(&a, &b) fn(&x, &x) fn(&a, &a) fn(&a, &b) +fn(&a, &b, &a) fn(&x, &y, &y) fn(&a, &a, &a) fn(&a,&b,&c) +``` + +### Conventions + +I use lower-case letters (e.g., `&a`) for bound regions and upper-case +letters for free regions (`&A`). Region variables written with a +dollar-sign (e.g., `$a`). I will try to remember to enumerate the +bound-regions on the fn type as well (e.g., `fn(&a)`). + +### High-level summary + +Both the LUB and the GLB algorithms work in a similar fashion. They +begin by replacing all bound regions (on both sides) with fresh region +inference variables. Therefore, both functions are converted to types +that contain only free regions. We can then compute the LUB/GLB in a +straightforward way, as described in `combine.rs`. This results in an +interim type T. The algorithms then examine the regions that appear +in T and try to, in some cases, replace them with bound regions to +yield the final result. + +To decide whether to replace a region `R` that appears in `T` with a +bound region, the algorithms make use of two bits of information. +First is a set `V` that contains all region variables created as part +of the LUB/GLB computation. `V` will contain the region variables +created to replace the bound regions in the input types, but it also +contains 'intermediate' variables created to represent the LUB/GLB of +individual regions. Basically, when asked to compute the LUB/GLB of a +region variable with another region, the inferencer cannot oblige +immediately since the valuese of that variables are not known. +Therefore, it creates a new variable that is related to the two +regions. For example, the LUB of two variables `$x` and `$y` is a +fresh variable `$z` that is constrained such that `$x <= $z` and `$y +<= $z`. So `V` will contain these intermediate variables as well. + +The other important factor in deciding how to replace a region in T is +the function `Tainted($r)` which, for a region variable, identifies +all regions that the region variable is related to in some way +(`Tainted()` made an appearance in the subtype computation as well). + ### LUB The LUB algorithm proceeds in three steps: @@ -345,47 +400,28 @@ The LUB algorithm proceeds in three steps: inference variables. 2. Compute the LUB "as normal", meaning compute the GLB of each pair of argument types and the LUB of the return types and - so forth. Combine those to a new function type F. -3. Map the regions appearing in `F` using the procedure described below. - -For each region `R` that appears in `F`, we may need to replace it -with a bound region. Let `V` be the set of fresh variables created as -part of the LUB procedure (either in step 1 or step 2). You may be -wondering how variables can be created in step 2. The answer is that -when we are asked to compute the LUB or GLB of two region variables, -we do so by producing a new region variable that is related to those -two variables. i.e., The LUB of two variables `$x` and `$y` is a -fresh variable `$z` that is constrained such that `$x <= $z` and `$y -<= $z`. - -To decide how to replace a region `R`, we must examine `Tainted(R)`. -This function searches through the constraints which were generated -when computing the bounds of all the argument and return types and -produces a list of all regions to which `R` is related, directly or -indirectly. - -If `R` is not in `V` or `Tainted(R)` contains any region that is not -in `V`, then `R` is not replaced (that is, `R` is mapped to itself). -Otherwise, if `Tainted(R)` is a subset of `V`, then we select the -earliest variable in `Tainted(R)` that originates from the left-hand -side and replace `R` with a bound version of that variable. - -So, let's work through the simplest example: `fn(&A)` and `fn(&a)`. -In this case, `&a` will be replaced with `$a` (the $ indicates an -inference variable) which will be linked to the free region `&A`, and -hence `V = { $a }` and `Tainted($a) = { &A }`. Since `$a` is not a -member of `V`, we leave `$a` as is. When region inference happens, -`$a` will be resolved to `&A`, as we wanted. - -So, let's work through the simplest example: `fn(&A)` and `fn(&a)`. -In this case, `&a` will be replaced with `$a` (the $ indicates an -inference variable) which will be linked to the free region `&A`, and -hence `V = { $a }` and `Tainted($a) = { $a, &A }`. Since `&A` is not a -member of `V`, we leave `$a` as is. When region inference happens, -`$a` will be resolved to `&A`, as we wanted. - -Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`. -In this case, we'll end up with a graph that looks like: + so forth. Combine those to a new function type `F`. +3. Replace each region `R` that appears in `F` as follows: + - Let `V` be the set of variables created during the LUB + computational steps 1 and 2, as described in the previous section. + - If `R` is not in `V`, replace `R` with itself. + - If `Tainted(R)` contains a region that is not in `V`, + replace `R` with itself. + - Otherwise, select the earliest variable in `Tainted(R)` that originates + from the left-hand side and replace `R` with the bound region that + this variable was a replacement for. + +So, let's work through the simplest example: `fn(&A)` and `fn(&a)`. +In this case, `&a` will be replaced with `$a` and the interim LUB type +`fn($b)` will be computed, where `$b=GLB(&A,$a)`. Therefore, `V = +{$a, $b}` and `Tainted($b) = { $b, $a, &A }`. When we go to replace +`$b`, we find that since `&A \in Tainted($b)` is not a member of `V`, +we leave `$b` as is. When region inference happens, `$b` will be +resolved to `&A`, as we wanted. + +Let's look at a more complex one: `fn(&a, &b)` and `fn(&x, &x)`. In +this case, we'll end up with a (pre-replacement) LUB type of `fn(&g, +&h)` and a graph that looks like: ``` $a $b *--$x @@ -399,8 +435,8 @@ the LUB/GLB of things requiring inference. This means that `V` and `Tainted` will look like: ``` -V = {$a, $b, $x} -Tainted($g) = Tainted($h) = { $a, $b, $h, $x } +V = {$a, $b, $g, $h, $x} +Tainted($g) = Tainted($h) = { $a, $b, $h, $g, $x } ``` Therefore we replace both `$g` and `$h` with `$a`, and end up @@ -413,40 +449,90 @@ in computing the replacements for the various variables. For each region `R` that appears in the type `F`, we again compute `Tainted(R)` and examine the results: -1. If `Tainted(R) = {R}` is a singleton set, replace `R` with itself. +1. If `R` is not in `V`, it is not replaced. 2. Else, if `Tainted(R)` contains only variables in `V`, and it contains exactly one variable from the LHS and one variable from the RHS, then `R` can be mapped to the bound version of the variable from the LHS. -3. Else, `R` is mapped to a fresh bound variable. +3. Else, if `Tainted(R)` contains no variable from the LHS and no + variable from the RHS, then `R` can be mapped to itself. +4. Else, `R` is mapped to a fresh bound variable. These rules are pretty complex. Let's look at some examples to see how they play out. -Out first example was `fn(&a)` and `fn(&X)`---in -this case, the LUB will be a variable `$g`, and `Tainted($g) = -{$g,$a,$x}`. By these rules, we'll replace `$g` with a fresh bound -variable, so the result is `fn(&z)`, which is fine. - -The next example is `fn(&A)` and `fn(&Z)`. XXX - -The next example is `fn(&a, &b)` and `fn(&x, &x)`. In this case, as -before, we'll end up with `F=fn(&g, &h)` where `Tainted($g) = -Tainted($h) = {$g, $a, $b, $x}`. This means that we'll select fresh -bound varibales `g` and `h` and wind up with `fn(&g, &h)`. +Out first example was `fn(&a)` and `fn(&X)`. In this case, `&a` will +be replaced with `$a` and we will ultimately compute a +(pre-replacement) GLB type of `fn($g)` where `$g=LUB($a,&X)`. +Therefore, `V={$a,$g}` and `Tainted($g)={$g,$a,&X}. To find the +replacement for `$g` we consult the rules above: +- Rule (1) does not apply because `$g \in V` +- Rule (2) does not apply because `&X \in Tainted($g)` +- Rule (3) does not apply because `$a \in Tainted($g)` +- Hence, by rule (4), we replace `$g` with a fresh bound variable `&z`. +So our final result is `fn(&z)`, which is correct. + +The next example is `fn(&A)` and `fn(&Z)`. In this case, we will again +have a (pre-replacement) GLB of `fn(&g)`, where `$g = LUB(&A,&Z)`. +Therefore, `V={$g}` and `Tainted($g) = {$g, &A, &Z}`. In this case, +by rule (3), `$g` is mapped to itself, and hence the result is +`fn($g)`. This result is correct (in this case, at least), but it is +indicative of a case that *can* lead us into concluding that there is +no GLB when in fact a GLB does exist. See the section "Questionable +Results" below for more details. + +The next example is `fn(&a, &b)` and `fn(&c, &c)`. In this case, as +before, we'll end up with `F=fn($g, $h)` where `Tainted($g) = +Tainted($h) = {$g, $h, $a, $b, $c}`. Only rule (4) applies and hence +we'll select fresh bound variables `y` and `z` and wind up with +`fn(&y, &z)`. For the last example, let's consider what may seem trivial, but is -not: `fn(&a, &a)` and `fn(&x, &x)`. In this case, we'll get `F=fn(&g, -&h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a, +not: `fn(&a, &a)` and `fn(&b, &b)`. In this case, we'll get `F=fn($g, +$h)` where `Tainted($g) = {$g, $a, $x}` and `Tainted($h) = {$h, $a, $x}`. Both of these sets contain exactly one bound variable from each -side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`. -Horray! - -### Why are these correct? - -You may be wondering whether this algorithm is correct. So am I. But -I believe it is. (Justification forthcoming, haven't had time to -write it) +side, so we'll map them both to `&a`, resulting in `fn(&a, &a)`, which +is the desired result. + +### Shortcomings and correctness + +You may be wondering whether this algorithm is correct. The answer is +"sort of". There are definitely cases where they fail to compute a +result even though a correct result exists. I believe, though, that +if they succeed, then the result is valid, and I will attempt to +convince you. The basic argument is that the "pre-replacement" step +computes a set of constraints. The replacements, then, attempt to +satisfy those constraints, using bound identifiers where needed. + +For now I will briefly go over the cases for LUB/GLB and identify +their intent: + +- LUB: + - The region variables that are substituted in place of bound regions + are intended to collect constraints on those bound regions. + - If Tainted(R) contains only values in V, then this region is unconstrained + and can therefore be generalized, otherwise it cannot. +- GLB: + - The region variables that are substituted in place of bound regions + are intended to collect constraints on those bound regions. + - If Tainted(R) contains exactly one variable from each side, and + only variables in V, that indicates that those two bound regions + must be equated. + - Otherwise, if Tainted(R) references any variables from left or right + side, then it is trying to combine a bound region with a free one or + multiple bound regions, so we need to select fresh bound regions. + +Sorry this is more of a shorthand to myself. I will try to write up something +more convincing in the future. + +#### Where are the algorithms wrong? + +- The pre-replacement computation can fail even though using a + bound-region would have succeeded. +- We will compute GLB(fn(fn($a)), fn(fn($b))) as fn($c) where $c is the + GLB of $a and $b. But if inference finds that $a and $b must be mapped + to regions without a GLB, then this is effectively a failure to compute + the GLB. However, the result `fn<$c>(fn($c))` is a valid GLB. */ @@ -454,13 +540,19 @@ write it) #[warn(deprecated_pattern)]; use middle::region::is_subregion_of; +use middle::region; +use middle::ty; use middle::ty::{Region, RegionVid, re_static, re_infer, re_free, re_bound}; -use middle::ty::{re_scope, ReVar, ReSkolemized}; -use middle::typeck::infer::to_str::ToStr; +use middle::ty::{re_scope, ReVar, ReSkolemized, br_fresh}; +use middle::typeck::infer::to_str::InferStr; use syntax::codemap; use util::ppaux::note_and_explain_region; +use core::cmp; use core::dvec::DVec; +use core::to_bytes; +use core::uint; +use core::vec; use result::Result; use result::{Ok, Err}; use std::map::HashMap; @@ -547,6 +639,7 @@ struct RegionVarBindings { lubs: CombineMap, glbs: CombineMap, mut skolemization_count: uint, + mut bound_count: uint, // The undo log records actions that might later be undone. // @@ -573,6 +666,7 @@ fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings { lubs: CombineMap(), glbs: CombineMap(), skolemization_count: 0, + bound_count: 0, undo_log: ~[] } } @@ -649,6 +743,26 @@ impl RegionVarBindings { re_infer(ReSkolemized(sc, br)) } + fn new_bound(&self) -> Region { + // Creates a fresh bound variable for use in GLB computations. + // See discussion of GLB computation in the large comment at + // the top of this file for more details. + // + // This computation is mildly wrong in the face of rollover. + // It's conceivable, if unlikely, that one might wind up with + // accidental capture for nested functions in that case, if + // the outer function had bound regions created a very long + // time before and the inner function somehow wound up rolling + // over such that supposedly fresh identifiers were in fact + // shadowed. We should convert our bound_region + // representation to use deBruijn indices or something like + // that to eliminate that possibility. + + let sc = self.bound_count; + self.bound_count += 1; + re_bound(br_fresh(sc)) + } + fn add_constraint(&self, +constraint: Constraint, span: span) { // cannot add constraints once regions are resolved assert self.values.is_empty(); @@ -681,6 +795,16 @@ impl RegionVarBindings { self.add_constraint(ConstrainVarSubReg(sub_id, r), span); Ok(()) } + (re_bound(br), _) => { + self.tcx.sess.span_bug( + span, + fmt!("Cannot relate bound region as subregion: %?", br)); + } + (_, re_bound(br)) => { + self.tcx.sess.span_bug( + span, + fmt!("Cannot relate bound region as superregion: %?", br)); + } _ => { if self.is_subregion_of(sub, sup) { Ok(()) diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index 91689ff06ddc9..c02ee0055e641 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -46,50 +46,56 @@ // future). If you want to resolve everything but one type, you are // probably better off writing `resolve_all - resolve_ivar`. -use middle::typeck::infer::floating::*; -use middle::typeck::infer::integral::*; -use middle::typeck::infer::to_str::ToStr; +use middle::ty; +use middle::typeck::infer::to_str::InferStr; -const resolve_nested_tvar: uint = 0b00000001; -const resolve_rvar: uint = 0b00000010; -const resolve_ivar: uint = 0b00000100; -const resolve_fvar: uint = 0b00001000; -const resolve_all: uint = 0b00001111; -const force_tvar: uint = 0b00010000; -const force_rvar: uint = 0b00100000; -const force_ivar: uint = 0b01000000; -const force_fvar: uint = 0b11000000; -const force_all: uint = 0b11110000; +use syntax::ast; + +use core::uint; +use core::vec; + +const resolve_nested_tvar: uint = 0b0000000001; +const resolve_rvar: uint = 0b0000000010; +const resolve_ivar: uint = 0b0000000100; +const resolve_fvar: uint = 0b0000001000; +const resolve_fnvar: uint = 0b0000010000; +const resolve_all: uint = 0b0000011111; +const force_tvar: uint = 0b0000100000; +const force_rvar: uint = 0b0001000000; +const force_ivar: uint = 0b0010000000; +const force_fvar: uint = 0b0100000000; +const force_fnvar: uint = 0b1000000000; +const force_all: uint = 0b1111100000; const not_regions: uint = !(force_rvar | resolve_rvar); const resolve_and_force_all_but_regions: uint = (resolve_all | force_all) & not_regions; -type resolve_state_ = { - infcx: infer_ctxt, +struct ResolveState { + infcx: @InferCtxt, modes: uint, mut err: Option, - mut v_seen: ~[TyVid] -}; - -enum resolve_state { - resolve_state_(@resolve_state_) + mut v_seen: ~[TyVid], + mut type_depth: uint } -fn resolver(infcx: infer_ctxt, modes: uint) -> resolve_state { - resolve_state_(@{infcx: infcx, - modes: modes, - mut err: None, - mut v_seen: ~[]}) +fn resolver(infcx: @InferCtxt, modes: uint) -> ResolveState { + ResolveState { + infcx: infcx, + modes: modes, + err: None, + v_seen: ~[], + type_depth: 0 + } } -impl resolve_state { - fn should(mode: uint) -> bool { +impl ResolveState { + fn should(&self, mode: uint) -> bool { (self.modes & mode) == mode } - fn resolve_type_chk(typ: ty::t) -> fres { + fn resolve_type_chk(&self, typ: ty::t) -> fres { self.err = None; debug!("Resolving %s (modes=%x)", @@ -104,7 +110,8 @@ impl resolve_state { assert vec::is_empty(self.v_seen); match self.err { None => { - debug!("Resolved to %s (modes=%x)", + debug!("Resolved to %s + %s (modes=%x)", + ty_to_str(self.infcx.tcx, rty), ty_to_str(self.infcx.tcx, rty), self.modes); return Ok(rty); @@ -113,7 +120,7 @@ impl resolve_state { } } - fn resolve_region_chk(orig: ty::Region) -> fres { + fn resolve_region_chk(&self, orig: ty::Region) -> fres { self.err = None; let resolved = indent(|| self.resolve_region(orig) ); match self.err { @@ -122,63 +129,64 @@ impl resolve_state { } } - fn resolve_type(typ: ty::t) -> ty::t { - debug!("resolve_type(%s)", typ.to_str(self.infcx)); - indent(fn&() -> ty::t { - if !ty::type_needs_infer(typ) { return typ; } + fn resolve_type(&self, typ: ty::t) -> ty::t { + debug!("resolve_type(%s)", typ.inf_str(self.infcx)); + let _i = indenter(); - match ty::get(typ).sty { - ty::ty_infer(TyVar(vid)) => { + if !ty::type_needs_infer(typ) { + return typ; + } + + if self.type_depth > 0 && !self.should(resolve_nested_tvar) { + return typ; + } + + match /*bad*/ copy ty::get(typ).sty { + ty::ty_infer(TyVar(vid)) => { self.resolve_ty_var(vid) - } - ty::ty_infer(IntVar(vid)) => { + } + ty::ty_infer(IntVar(vid)) => { self.resolve_int_var(vid) - } - ty::ty_infer(FloatVar(vid)) => { + } + ty::ty_infer(FloatVar(vid)) => { self.resolve_float_var(vid) - } - _ => { - if !self.should(resolve_rvar) && - !self.should(resolve_nested_tvar) { - // shortcircuit for efficiency + } + _ => { + if self.modes & resolve_all == 0 { + // if we are only resolving top-level type + // variables, and this is not a top-level type + // variable, then shortcircuit for efficiency typ } else { - ty::fold_regions_and_ty( + self.type_depth += 1; + let result = ty::fold_regions_and_ty( self.infcx.tcx, typ, |r| self.resolve_region(r), - |t| self.resolve_nested_tvar(t), - |t| self.resolve_nested_tvar(t)) + |t| self.resolve_type(t), + |t| self.resolve_type(t)); + self.type_depth -= 1; + result } - } } - }) - } - - fn resolve_nested_tvar(typ: ty::t) -> ty::t { - debug!("Resolve_if_deep(%s)", typ.to_str(self.infcx)); - if !self.should(resolve_nested_tvar) { - typ - } else { - self.resolve_type(typ) } } - fn resolve_region(orig: ty::Region) -> ty::Region { - debug!("Resolve_region(%s)", orig.to_str(self.infcx)); + fn resolve_region(&self, orig: ty::Region) -> ty::Region { + debug!("Resolve_region(%s)", orig.inf_str(self.infcx)); match orig { ty::re_infer(ty::ReVar(rid)) => self.resolve_region_var(rid), _ => orig } } - fn resolve_region_var(rid: RegionVid) -> ty::Region { + fn resolve_region_var(&self, rid: RegionVid) -> ty::Region { if !self.should(resolve_rvar) { return ty::re_infer(ty::ReVar(rid)); } self.infcx.region_vars.resolve_var(rid) } - fn assert_not_rvar(rid: RegionVid, r: ty::Region) { + fn assert_not_rvar(&self, rid: RegionVid, r: ty::Region) { match r { ty::re_infer(ty::ReVar(rid2)) => { self.err = Some(region_var_bound_by_region_var(rid, rid2)); @@ -187,7 +195,7 @@ impl resolve_state { } } - fn resolve_ty_var(vid: TyVid) -> ty::t { + fn resolve_ty_var(&self, vid: TyVid) -> ty::t { if vec::contains(self.v_seen, &vid) { self.err = Some(cyclic_ty(vid)); return ty::mk_var(self.infcx.tcx, vid); @@ -220,27 +228,22 @@ impl resolve_state { } } - fn resolve_int_var(vid: IntVid) -> ty::t { + fn resolve_int_var(&self, vid: IntVid) -> ty::t { if !self.should(resolve_ivar) { return ty::mk_int_var(self.infcx.tcx, vid); } - let nde = self.infcx.get(&self.infcx.int_var_bindings, vid); - let pt = nde.possible_types; - - // If there's only one type in the set of possible types, then - // that's the answer. - match integral::single_type_contained_in(self.infcx.tcx, pt) { - Some(t) => t, + let node = self.infcx.get(&self.infcx.int_var_bindings, vid); + match node.possible_types { + Some(IntType(t)) => ty::mk_mach_int(self.infcx.tcx, t), + Some(UintType(t)) => ty::mk_mach_uint(self.infcx.tcx, t), None => { if self.should(force_ivar) { // As a last resort, default to int. let ty = ty::mk_int(self.infcx.tcx); self.infcx.set( &self.infcx.int_var_bindings, vid, - root(convert_integral_ty_to_int_ty_set(self.infcx.tcx, - ty), - nde.rank)); + Root(Some(IntType(ast::ty_i)), node.rank)); ty } else { ty::mk_int_var(self.infcx.tcx, vid) @@ -249,18 +252,14 @@ impl resolve_state { } } - fn resolve_float_var(vid: FloatVid) -> ty::t { + fn resolve_float_var(&self, vid: FloatVid) -> ty::t { if !self.should(resolve_fvar) { return ty::mk_float_var(self.infcx.tcx, vid); } - let nde = self.infcx.get(&self.infcx.float_var_bindings, vid); - let pt = nde.possible_types; - - // If there's only one type in the set of possible types, then - // that's the answer. - match floating::single_type_contained_in(self.infcx.tcx, pt) { - Some(t) => t, + let node = self.infcx.get(&self.infcx.float_var_bindings, vid); + match node.possible_types { + Some(t) => ty::mk_mach_float(self.infcx.tcx, t), None => { if self.should(force_fvar) { // As a last resort, default to float. @@ -268,10 +267,7 @@ impl resolve_state { self.infcx.set( &self.infcx.float_var_bindings, vid, - root( - convert_floating_point_ty_to_float_ty_set( - self.infcx.tcx, ty), - nde.rank)); + Root(Some(ast::ty_f), node.rank)); ty } else { ty::mk_float_var(self.infcx.tcx, vid) diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 1cec971f15629..2f43fd616205b 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -8,34 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use middle::ty; use middle::typeck::infer::combine::*; -use middle::typeck::infer::to_str::ToStr; +use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::unify::*; use std::list; +use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig}; fn macros() { include!("macros.rs"); } // FIXME(#3114): Macro import/export. -enum Sub = combine_fields; // "subtype", "subregion" etc +enum Sub = CombineFields; // "subtype", "subregion" etc -impl Sub: combine { - fn infcx() -> infer_ctxt { self.infcx } +impl Sub: Combine { + fn infcx() -> @InferCtxt { self.infcx } fn tag() -> ~str { ~"sub" } fn a_is_expected() -> bool { self.a_is_expected } + fn span() -> span { self.span } fn sub() -> Sub { Sub(*self) } fn lub() -> Lub { Lub(*self) } fn glb() -> Glb { Glb(*self) } fn contratys(a: ty::t, b: ty::t) -> cres { - let opp = combine_fields { + let opp = CombineFields { a_is_expected: !self.a_is_expected,.. *self }; Sub(opp).tys(b, a) } fn contraregions(a: ty::Region, b: ty::Region) -> cres { - let opp = combine_fields { + let opp = CombineFields { a_is_expected: !self.a_is_expected,.. *self }; Sub(opp).regions(b, a) @@ -44,8 +47,8 @@ impl Sub: combine { fn regions(a: ty::Region, b: ty::Region) -> cres { debug!("%s.regions(%s, %s)", self.tag(), - a.to_str(self.infcx), - b.to_str(self.infcx)); + a.inf_str(self.infcx), + b.inf_str(self.infcx)); do indent { match self.infcx.region_vars.make_subregion(self.span, a, b) { Ok(()) => Ok(a), @@ -55,7 +58,7 @@ impl Sub: combine { } fn mts(a: ty::mt, b: ty::mt) -> cres { - debug!("mts(%s <: %s)", a.to_str(self.infcx), b.to_str(self.infcx)); + debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); if a.mutbl != b.mutbl && b.mutbl != m_const { return Err(ty::terr_mutability); @@ -74,14 +77,6 @@ impl Sub: combine { } } - fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { - match (p1, p2) { - (ast::ProtoBare, _) => Ok(p1), - _ if p1 == p2 => Ok(p1), - _ => Err(ty::terr_proto_mismatch(expected_found(&self, p1, p2))) - } - } - fn purities(a: purity, b: purity) -> cres { self.lub().purities(a, b).compare(b, || { ty::terr_purity_mismatch(expected_found(&self, a, b)) @@ -94,42 +89,49 @@ impl Sub: combine { }) } - fn ret_styles(a: ret_style, b: ret_style) -> cres { - self.lub().ret_styles(a, b).compare(b, || { - ty::terr_ret_style_mismatch(expected_found(&self, a, b)) - }) - } - fn tys(a: ty::t, b: ty::t) -> cres { debug!("%s.tys(%s, %s)", self.tag(), - a.to_str(self.infcx), b.to_str(self.infcx)); + a.inf_str(self.infcx), b.inf_str(self.infcx)); if a == b { return Ok(a); } do indent { match (ty::get(a).sty, ty::get(b).sty) { - (ty::ty_bot, _) => { - Ok(a) - } - (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { - var_sub_var(&self, a_id, b_id).then(|| Ok(a) ) - } - (ty::ty_infer(TyVar(a_id)), _) => { - var_sub_t(&self, a_id, b).then(|| Ok(a) ) - } - (_, ty::ty_infer(TyVar(b_id))) => { - t_sub_var(&self, a, b_id).then(|| Ok(a) ) - } - (_, ty::ty_bot) => { - Err(ty::terr_sorts(expected_found(&self, a, b))) - } - _ => { - super_tys(&self, a, b) - } + (ty::ty_bot, _) => { + Ok(a) + } + + (ty::ty_infer(TyVar(a_id)), ty::ty_infer(TyVar(b_id))) => { + do self.var_sub_var(&self.infcx.ty_var_bindings, + a_id, b_id).then { + Ok(a) + } + } + (ty::ty_infer(TyVar(a_id)), _) => { + do self.var_sub_t(&self.infcx.ty_var_bindings, + a_id, b).then { + Ok(a) + } + } + (_, ty::ty_infer(TyVar(b_id))) => { + do self.t_sub_var(&self.infcx.ty_var_bindings, + a, b_id).then { + Ok(a) + } + } + + (_, ty::ty_bot) => { + Err(ty::terr_sorts(expected_found(&self, a, b))) + } + + _ => { + super_tys(&self, a, b) + } } } } - fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { - debug!("fns(a=%s, b=%s)", a.to_str(self.infcx), b.to_str(self.infcx)); + fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { + debug!("fn_sigs(a=%s, b=%s)", + a.inf_str(self.infcx), b.inf_str(self.infcx)); let _indenter = indenter(); // Rather than checking the subtype relationship between `a` and `b` @@ -147,14 +149,14 @@ impl Sub: combine { // First, we instantiate each bound region in the subtype with a fresh // region variable. - let (a_fn_ty, _) = + let (a_sig, _) = self.infcx.replace_bound_regions_with_fresh_regions( self.span, a); // Second, we instantiate each bound region in the supertype with a // fresh concrete region. - let {fn_ty: b_fn_ty, isr: skol_isr, _} = { - do replace_bound_regions_in_fn_ty(self.infcx.tcx, @Nil, + let {fn_sig: b_sig, isr: skol_isr, _} = { + do replace_bound_regions_in_fn_sig(self.infcx.tcx, @Nil, None, b) |br| { let skol = self.infcx.region_vars.new_skolemized(br); debug!("Bound region %s skolemized to %?", @@ -164,11 +166,11 @@ impl Sub: combine { } }; - debug!("a_fn_ty=%s", a_fn_ty.to_str(self.infcx)); - debug!("b_fn_ty=%s", b_fn_ty.to_str(self.infcx)); + debug!("a_sig=%s", a_sig.inf_str(self.infcx)); + debug!("b_sig=%s", b_sig.inf_str(self.infcx)); // Compare types now that bound regions have been replaced. - let fn_ty = if_ok!(super_fns(&self, &a_fn_ty, &b_fn_ty)); + let sig = if_ok!(super_fn_sigs(&self, &a_sig, &b_sig)); // Presuming type comparison succeeds, we need to check // that the skolemized regions do not "leak". @@ -200,21 +202,25 @@ impl Sub: combine { } } - return Ok(fn_ty) + return Ok(sig); } // Traits please (FIXME: #2794): + fn protos(p1: ast::Proto, p2: ast::Proto) -> cres { + super_protos(&self, p1, p2) + } + fn flds(a: ty::field, b: ty::field) -> cres { super_flds(&self, a, b) } - fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { - super_fn_metas(&self, a, b) + fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres { + super_fns(&self, a, b) } - fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres { - super_fn_sigs(&self, a, b) + fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres { + super_fn_metas(&self, a, b) } fn vstores(vk: ty::terr_vstore_kind, diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs index c585b45e7ac00..abc249a45ec3f 100644 --- a/src/librustc/middle/typeck/infer/test.rs +++ b/src/librustc/middle/typeck/infer/test.rs @@ -16,6 +16,7 @@ Note: This module is only compiled when doing unit testing. */ +use dvec::DVec; use std::getopts; use std::map::HashMap; use std::getopts; @@ -27,7 +28,7 @@ use driver::driver::{optgroups, build_session_options, build_session, use driver::diagnostic; use syntax::{ast, attr, parse}; use syntax::parse::parse_crate_from_source_str; -use middle::lang_items::{LanguageItems, language_items}; +use middle::lang_items::LanguageItems; use util::ppaux::ty_to_str; use syntax::ast_util::dummy_sp; use middle::ty::{FnTyBase, FnMeta, FnSig}; @@ -35,7 +36,8 @@ use middle::ty::{FnTyBase, FnMeta, FnSig}; struct Env { crate: @ast::crate, tcx: ty::ctxt, - infcx: infer::infer_ctxt + infcx: infer::infer_ctxt, + err_messages: @DVec<~str> } struct RH { @@ -43,17 +45,21 @@ struct RH { sub: &[RH] } +const EMPTY_SOURCE_STR: &str = "/* Hello, world! */"; + fn setup_env(test_name: &str, source_string: &str) -> Env { - let matches = &getopts(~[~"-Z", ~"verbose"], optgroups()).get(); - let sessopts = build_session_options(~"rustc", matches, diagnostic::emit); - let sess = build_session(sessopts, diagnostic::emit); + let messages = @DVec(); + let matches = getopts(~[~"-Z", ~"verbose"], optgroups()).get(); + let diag = diagnostic::collect(messages); + let sessopts = build_session_options(~"rustc", &matches, diag); + let sess = build_session(sessopts, diag); let cfg = build_configuration(sess, ~"whatever", str_input(~"")); let dm = HashMap(); let amap = HashMap(); let freevars = HashMap(); let region_paramd_items = HashMap(); let region_map = HashMap(); - let lang_items = language_items::make(); + let lang_items = LanguageItems::new(); let parse_sess = parse::new_parse_sess(None); let crate = parse_crate_from_source_str( @@ -65,7 +71,10 @@ fn setup_env(test_name: &str, source_string: &str) -> Env { let infcx = infer::new_infer_ctxt(tcx); - return Env { crate: crate, tcx: tcx, infcx: infcx }; + return Env {crate: crate, + tcx: tcx, + infcx: infcx, + err_messages: messages}; } impl Env { @@ -180,8 +189,7 @@ impl Env { proto: ast::ProtoBare, onceness: ast::Many, region: ty::re_static, - bounds: @~[], - ret_style: ast::return_val}, + bounds: @~[]}, sig: FnSig {inputs: move inputs, output: output_ty} }) @@ -210,6 +218,22 @@ impl Env { fn lub() -> Lub { Lub(self.infcx.combine_fields(true, dummy_sp())) } + fn glb() -> Glb { Glb(self.infcx.combine_fields(true, dummy_sp())) } + + fn resolve_regions(exp_count: uint) { + debug!("resolve_regions(%u)", exp_count); + + self.infcx.resolve_regions(); + if self.err_messages.len() != exp_count { + for self.err_messages.each |msg| { + debug!("Error encountered: %s", *msg); + } + fmt!("Resolving regions encountered %u errors but expected %u!", + self.err_messages.len(), + exp_count); + } + } + /// Checks that `LUB(t1,t2) == t_lub` fn check_lub(&self, t1: ty::t, t2: ty::t, t_lub: ty::t) { match self.lub().tys(t1, t2) { @@ -222,6 +246,30 @@ impl Env { // sanity check for good measure: self.assert_subtype(t1, t); self.assert_subtype(t2, t); + + self.resolve_regions(0); + } + } + } + + /// Checks that `GLB(t1,t2) == t_glb` + fn check_glb(&self, t1: ty::t, t2: ty::t, t_glb: ty::t) { + debug!("check_glb(t1=%s, t2=%s, t_glb=%s)", + self.ty_to_str(t1), + self.ty_to_str(t2), + self.ty_to_str(t_glb)); + match self.glb().tys(t1, t2) { + Err(e) => { + fail fmt!("Unexpected error computing LUB: %?", e) + } + Ok(t) => { + self.assert_eq(t, t_glb); + + // sanity check for good measure: + self.assert_subtype(t, t1); + self.assert_subtype(t, t2); + + self.resolve_regions(0); } } } @@ -236,11 +284,22 @@ impl Env { } } } + + /// Checks that `GLB(t1,t2)` is undefined + fn check_no_glb(&self, t1: ty::t, t2: ty::t) { + match self.glb().tys(t1, t2) { + Err(_) => {} + Ok(t) => { + fail fmt!("Unexpected success computing GLB: %?", + self.ty_to_str(t)) + } + } + } } #[test] fn contravariant_region_ptr() { - let env = setup_env("contravariant_region_ptr", ""); + let env = setup_env("contravariant_region_ptr", EMPTY_SOURCE_STR); env.create_simple_region_hierarchy(); let t_rptr1 = env.t_rptr_scope(1); let t_rptr10 = env.t_rptr_scope(10); @@ -251,7 +310,7 @@ fn contravariant_region_ptr() { #[test] fn lub_bound_bound() { - let env = setup_env("lub_bound_bound", ""); + let env = setup_env("lub_bound_bound", EMPTY_SOURCE_STR); let t_rptr_bound1 = env.t_rptr_bound(1); let t_rptr_bound2 = env.t_rptr_bound(2); env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()), @@ -261,7 +320,7 @@ fn lub_bound_bound() { #[test] fn lub_bound_free() { - let env = setup_env("lub_bound_free", ""); + let env = setup_env("lub_bound_free", EMPTY_SOURCE_STR); let t_rptr_bound1 = env.t_rptr_bound(1); let t_rptr_free1 = env.t_rptr_free(0, 1); env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()), @@ -271,7 +330,7 @@ fn lub_bound_free() { #[test] fn lub_bound_static() { - let env = setup_env("lub_bound_static", ""); + let env = setup_env("lub_bound_static", EMPTY_SOURCE_STR); let t_rptr_bound1 = env.t_rptr_bound(1); let t_rptr_static = env.t_rptr_static(); env.check_lub(env.t_fn([t_rptr_bound1], env.t_int()), @@ -281,7 +340,7 @@ fn lub_bound_static() { #[test] fn lub_bound_bound_inverse_order() { - let env = setup_env("lub_bound_bound_inverse_order", ""); + let env = setup_env("lub_bound_bound_inverse_order", EMPTY_SOURCE_STR); let t_rptr_bound1 = env.t_rptr_bound(1); let t_rptr_bound2 = env.t_rptr_bound(2); env.check_lub(env.t_fn([t_rptr_bound1, t_rptr_bound2], t_rptr_bound1), @@ -291,7 +350,7 @@ fn lub_bound_bound_inverse_order() { #[test] fn lub_free_free() { - let env = setup_env("lub_free_free", ""); + let env = setup_env("lub_free_free", EMPTY_SOURCE_STR); let t_rptr_free1 = env.t_rptr_free(0, 1); let t_rptr_free2 = env.t_rptr_free(0, 2); let t_rptr_static = env.t_rptr_static(); @@ -302,10 +361,50 @@ fn lub_free_free() { #[test] fn lub_returning_scope() { - let env = setup_env("lub_returning_scope", ""); + let env = setup_env("lub_returning_scope", EMPTY_SOURCE_STR); let t_rptr_scope10 = env.t_rptr_scope(10); let t_rptr_scope11 = env.t_rptr_scope(11); env.check_no_lub(env.t_fn([], t_rptr_scope10), env.t_fn([], t_rptr_scope11)); } +#[test] +fn glb_free_free_with_common_scope() { + let env = setup_env("glb_free_free", EMPTY_SOURCE_STR); + let t_rptr_free1 = env.t_rptr_free(0, 1); + let t_rptr_free2 = env.t_rptr_free(0, 2); + let t_rptr_scope = env.t_rptr_scope(0); + env.check_glb(env.t_fn([t_rptr_free1], env.t_int()), + env.t_fn([t_rptr_free2], env.t_int()), + env.t_fn([t_rptr_scope], env.t_int())); +} + +#[test] +fn glb_bound_bound() { + let env = setup_env("glb_bound_bound", EMPTY_SOURCE_STR); + let t_rptr_bound1 = env.t_rptr_bound(1); + let t_rptr_bound2 = env.t_rptr_bound(2); + env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()), + env.t_fn([t_rptr_bound2], env.t_int()), + env.t_fn([t_rptr_bound1], env.t_int())); +} + +#[test] +fn glb_bound_free() { + let env = setup_env("glb_bound_free", EMPTY_SOURCE_STR); + let t_rptr_bound1 = env.t_rptr_bound(1); + let t_rptr_free1 = env.t_rptr_free(0, 1); + env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()), + env.t_fn([t_rptr_free1], env.t_int()), + env.t_fn([t_rptr_bound1], env.t_int())); +} + +#[test] +fn glb_bound_static() { + let env = setup_env("glb_bound_static", EMPTY_SOURCE_STR); + let t_rptr_bound1 = env.t_rptr_bound(1); + let t_rptr_static = env.t_rptr_static(); + env.check_glb(env.t_fn([t_rptr_bound1], env.t_int()), + env.t_fn([t_rptr_static], env.t_int()), + env.t_fn([t_rptr_bound1], env.t_int())); +} diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs index 166907ba7a862..2ef772e24deb8 100644 --- a/src/librustc/middle/typeck/infer/to_str.rs +++ b/src/librustc/middle/typeck/infer/to_str.rs @@ -8,78 +8,97 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::typeck::infer::integral::int_ty_set; -use middle::typeck::infer::floating::float_ty_set; -use middle::typeck::infer::unify::{redirect, root, var_value}; +use middle::ty::{FnMeta, FnTyBase, FnSig, FnVid}; +use middle::ty; +use middle::typeck::infer::unify::{Redirect, Root, VarValue}; +use util::ppaux; -trait ToStr { - fn to_str(cx: infer_ctxt) -> ~str; +use syntax::{ast, ast_util}; + +use core::uint; +use core::str; + +pub trait InferStr { + fn inf_str(cx: @InferCtxt) -> ~str; } -impl ty::t: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { +impl ty::t : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { ty_to_str(cx.tcx, self) } } -impl ty::mt: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - mt_to_str(cx.tcx, self) +impl FnMeta : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + fmt!("%?", self) + } +} + +impl FnSig : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { + fmt!("(%s) -> %s", + str::connect(self.inputs.map(|a| a.ty.inf_str(cx)), ", "), + self.output.inf_str(cx)) + } +} + +impl FnTyBase : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { + fmt!("%s%s", self.meta.inf_str(cx), self.sig.inf_str(cx)) } } -impl ty::Region: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - util::ppaux::region_to_str(cx.tcx, self) +impl ty::mt : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { + mt_to_str(cx.tcx, self) } } -impl ty::FnTy: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - ty::mk_fn(cx.tcx, self).to_str(cx) +impl ty::Region : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + fmt!("%?", self) } } -impl bound: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { +impl Bound : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { match self { - Some(ref v) => (*v).to_str(cx), + Some(ref v) => v.inf_str(cx), None => ~"none" } } } -impl bounds: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { +impl Bounds : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { fmt!("{%s <: %s}", - self.lb.to_str(cx), - self.ub.to_str(cx)) + self.lb.inf_str(cx), + self.ub.inf_str(cx)) } } -impl int_ty_set: ToStr { - fn to_str(_cx: infer_ctxt) -> ~str { +impl VarValue : InferStr { + fn inf_str(cx: @InferCtxt) -> ~str { match self { - int_ty_set(v) => uint::to_str(v, 10u) + Redirect(ref vid) => fmt!("Redirect(%s)", vid.to_str()), + Root(ref pt, rk) => fmt!("Root(%s, %s)", pt.inf_str(cx), + uint::to_str(rk, 10u)) } } } -impl float_ty_set: ToStr { - fn to_str(_cx: infer_ctxt) -> ~str { +impl IntVarValue : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { match self { - float_ty_set(v) => uint::to_str(v, 10u) + IntType(t) => ast_util::int_ty_to_str(t), + UintType(t) => ast_util::uint_ty_to_str(t) } } } -impl var_value: ToStr { - fn to_str(cx: infer_ctxt) -> ~str { - match self { - redirect(ref vid) => fmt!("redirect(%s)", (*vid).to_str()), - root(ref pt, rk) => fmt!("root(%s, %s)", (*pt).to_str(cx), - uint::to_str(rk, 10u)) - } +impl ast::float_ty : InferStr { + fn inf_str(_cx: @InferCtxt) -> ~str { + ast_util::float_ty_to_str(self) } } diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs index 2ec356a6dc845..9500d89bf2263 100644 --- a/src/librustc/middle/typeck/infer/unify.rs +++ b/src/librustc/middle/typeck/infer/unify.rs @@ -8,32 +8,42 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::typeck::infer::combine::combine; -use middle::typeck::infer::floating::*; -use middle::typeck::infer::integral::*; -use middle::typeck::infer::to_str::ToStr; +use middle::ty; +use middle::typeck::infer::combine::Combine; +use middle::typeck::infer::to_str::InferStr; + +use core::result; use std::smallintmap::SmallIntMap; -enum var_value { - redirect(V), - root(T, uint), +enum VarValue { + Redirect(V), + Root(T, uint), } -struct vals_and_bindings { - vals: SmallIntMap>, - mut bindings: ~[(V, var_value)], +struct ValsAndBindings { + vals: SmallIntMap>, + mut bindings: ~[(V, VarValue)], } -struct node { +struct Node { root: V, possible_types: T, rank: uint, } -impl infer_ctxt { - fn get( - vb: &vals_and_bindings, vid: V) -> node { +impl @InferCtxt { + fn get( + vb: &ValsAndBindings, + vid: V) + -> Node + { + /*! + * + * Find the root node for `vid`. This uses the standard + * union-find algorithm with path compression: + * http://en.wikipedia.org/wiki/Disjoint-set_data_structure + */ let vid_u = vid.to_uint(); match vb.vals.find(vid_u) { @@ -42,431 +52,141 @@ impl infer_ctxt { } Some(ref var_val) => { match (*var_val) { - redirect(ref vid) => { + Redirect(ref vid) => { let node = self.get(vb, (*vid)); if node.root.ne(vid) { // Path compression - vb.vals.insert((*vid).to_uint(), redirect(node.root)); + vb.vals.insert(vid.to_uint(), Redirect(node.root)); } node } - root(ref pt, rk) => { - node {root: vid, possible_types: (*pt), rank: rk} + Root(ref pt, rk) => { + Node {root: vid, possible_types: *pt, rank: rk} } } } } } - fn set( - vb: &vals_and_bindings, vid: V, - +new_v: var_value) { + fn set( + vb: &ValsAndBindings, + vid: V, + +new_v: VarValue) + { + /*! + * + * Sets the value for `vid` to `new_v`. `vid` MUST be a root node! + */ let old_v = vb.vals.get(vid.to_uint()); vb.bindings.push((vid, old_v)); vb.vals.insert(vid.to_uint(), new_v); debug!("Updating variable %s from %s to %s", - vid.to_str(), old_v.to_str(self), new_v.to_str(self)); - } -} - -// Combines the two bounds into a more general bound. -fn merge_bnd( - self: &C, a: bound, b: bound, - merge_op: fn(ty::t,ty::t) -> cres) -> cres> { - - debug!("merge_bnd(%s,%s)", - a.to_str(self.infcx()), - b.to_str(self.infcx())); - let _r = indenter(); - - match (a, b) { - (None, None) => Ok(None), - (Some(_), None) => Ok(a), - (None, Some(_)) => Ok(b), - (Some(v_a), Some(v_b)) => { - do merge_op(v_a, v_b).chain |v| { - Ok(Some(v)) - } - } - } -} - -fn merge_bnds( - self: &C, a: bounds, b: bounds, - lub: fn(ty::t,ty::t) -> cres, - glb: fn(ty::t,ty::t) -> cres) -> cres> { - - let _r = indenter(); - do merge_bnd(self, a.ub, b.ub, glb).chain |ub| { - debug!("glb of ubs %s and %s is %s", - a.ub.to_str(self.infcx()), - b.ub.to_str(self.infcx()), - ub.to_str(self.infcx())); - do merge_bnd(self, a.lb, b.lb, lub).chain |lb| { - debug!("lub of lbs %s and %s is %s", - a.lb.to_str(self.infcx()), - b.lb.to_str(self.infcx()), - lb.to_str(self.infcx())); - Ok({lb: lb, ub: ub}) - } - } -} - -// Updates the bounds for the variable `v_id` to be the intersection -// of `a` and `b`. That is, the new bounds for `v_id` will be -// a bounds c such that: -// c.ub <: a.ub -// c.ub <: b.ub -// a.lb <: c.lb -// b.lb <: c.lb -// If this cannot be achieved, the result is failure. - -fn set_var_to_merged_bounds( - self: &C, - v_id: ty::TyVid, - a: bounds, - b: bounds, - rank: uint) -> ures { - - let vb = &self.infcx().ty_var_bindings; - - // Think of the two diamonds, we want to find the - // intersection. There are basically four possibilities (you - // can swap A/B in these pictures): - // - // A A - // / \ / \ - // / B \ / B \ - // / / \ \ / / \ \ - // * * * * * / * * - // \ \ / / \ / / - // \ B / / \ / / - // \ / * \ / - // A \ / A - // B - - debug!("merge(%s,%s,%s)", - v_id.to_str(), - a.to_str(self.infcx()), - b.to_str(self.infcx())); - - // First, relate the lower/upper bounds of A and B. - // Note that these relations *must* hold for us to - // to be able to merge A and B at all, and relating - // them explicitly gives the type inferencer more - // information and helps to produce tighter bounds - // when necessary. - do indent { - do bnds(self, a.lb, b.ub).then { - do bnds(self, b.lb, a.ub).then { - do merge_bnd(self, a.ub, b.ub, - |x, y| self.glb().tys(x, y)).chain |ub| { - do merge_bnd(self, a.lb, b.lb, - |x, y| self.lub().tys(x, y)).chain |lb| { - let bounds = {lb: lb, ub: ub}; - debug!("merge(%s): bounds=%s", - v_id.to_str(), - bounds.to_str(self.infcx())); - - // the new bounds must themselves - // be relatable: - do bnds(self, bounds.lb, bounds.ub).then { - self.infcx().set(vb, v_id, root(bounds, rank)); - uok() - } - } - } - } - } - } -} - -/// Ensure that variable A is a subtype of variable B. This is a -/// subtle and tricky process, as described in detail at the top -/// of infer.rs -fn var_sub_var(self: &C, - a_id: ty::TyVid, - b_id: ty::TyVid) -> ures { - let vb = &self.infcx().ty_var_bindings; - - // Need to make sub_id a subtype of sup_id. - let nde_a = self.infcx().get(vb, a_id); - let nde_b = self.infcx().get(vb, b_id); - let a_id = nde_a.root; - let b_id = nde_b.root; - let a_bounds = nde_a.possible_types; - let b_bounds = nde_b.possible_types; - - debug!("vars(%s=%s <: %s=%s)", - a_id.to_str(), a_bounds.to_str(self.infcx()), - b_id.to_str(), b_bounds.to_str(self.infcx())); - - if a_id == b_id { return uok(); } - - // If both A's UB and B's LB have already been bound to types, - // see if we can make those types subtypes. - match (a_bounds.ub, b_bounds.lb) { - (Some(a_ub), Some(b_lb)) => { - let r = self.infcx().try(|| self.sub().tys(a_ub, b_lb)); - match r { - Ok(_ty) => return result::Ok(()), - Err(_) => { /*fallthrough */ } - } - } - _ => { /*fallthrough*/ } - } - - // Otherwise, we need to merge A and B so as to guarantee that - // A remains a subtype of B. Actually, there are other options, - // but that's the route we choose to take. - - // Rank optimization - - // Make the node with greater rank the parent of the node with - // smaller rank. - if nde_a.rank > nde_b.rank { - debug!("vars(): a has smaller rank"); - // a has greater rank, so a should become b's parent, - // i.e., b should redirect to a. - self.infcx().set(vb, b_id, redirect(a_id)); - set_var_to_merged_bounds( - self, a_id, a_bounds, b_bounds, nde_a.rank) - } else if nde_a.rank < nde_b.rank { - debug!("vars(): b has smaller rank"); - // b has greater rank, so a should redirect to b. - self.infcx().set(vb, a_id, redirect(b_id)); - set_var_to_merged_bounds( - self, b_id, a_bounds, b_bounds, nde_b.rank) - } else { - debug!("vars(): a and b have equal rank"); - assert nde_a.rank == nde_b.rank; - // If equal, just redirect one to the other and increment - // the other's rank. We choose arbitrarily to redirect b - // to a and increment a's rank. - self.infcx().set(vb, b_id, redirect(a_id)); - set_var_to_merged_bounds( - self, a_id, a_bounds, b_bounds, nde_a.rank + 1u - ) - } -} - -/// make variable a subtype of T -fn var_sub_t(self: &C, a_id: ty::TyVid, b: ty::t) -> ures { - - let vb = &self.infcx().ty_var_bindings; - let nde_a = self.infcx().get(vb, a_id); - let a_id = nde_a.root; - let a_bounds = nde_a.possible_types; - - debug!("var_sub_t(%s=%s <: %s)", - a_id.to_str(), - a_bounds.to_str(self.infcx()), - b.to_str(self.infcx())); - let b_bounds = {lb: None, ub: Some(b)}; - set_var_to_merged_bounds(self, a_id, a_bounds, b_bounds, nde_a.rank) -} - -/// make T a subtype of variable -fn t_sub_var(self: &C, a: ty::t, b_id: ty::TyVid) -> ures { - - let vb = &self.infcx().ty_var_bindings; - let a_bounds = {lb: Some(a), ub: None}; - let nde_b = self.infcx().get(vb, b_id); - let b_id = nde_b.root; - let b_bounds = nde_b.possible_types; - - debug!("t_sub_var(%s <: %s=%s)", - a.to_str(self.infcx()), - b_id.to_str(), - b_bounds.to_str(self.infcx())); - set_var_to_merged_bounds(self, b_id, a_bounds, b_bounds, nde_b.rank) -} - -fn bnds( - self: &C, a: bound, b: bound) -> ures { - - debug!("bnds(%s <: %s)", a.to_str(self.infcx()), b.to_str(self.infcx())); - do indent { - match (a, b) { - (None, None) | - (Some(_), None) | - (None, Some(_)) => { - uok() - } - (Some(t_a), Some(t_b)) => { - self.sub().tys(t_a, t_b).to_ures() - } - } + vid.to_str(), old_v.inf_str(self), new_v.inf_str(self)); } -} - -// ______________________________________________________________________ -// Integral variables -impl infer_ctxt { - fn optimize_ranks(vb: &vals_and_bindings, - nde_a: node, - nde_b: node, - a_id: V, - b_id: V, - intersection: T) { - if nde_a.rank > nde_b.rank { - debug!("int_vars(): a has smaller rank"); + fn unify( + vb: &ValsAndBindings, + node_a: &Node, + node_b: &Node, + op: &fn(new_root: V, new_rank: uint) -> R + ) -> R { + // Rank optimization: if you don't know what it is, check + // out + + debug!("unify(node_a(id=%?, rank=%?), \ + node_b(id=%?, rank=%?))", + node_a.root, node_a.rank, + node_b.root, node_b.rank); + + if node_a.rank > node_b.rank { // a has greater rank, so a should become b's parent, // i.e., b should redirect to a. - self.set(vb, a_id, root(intersection, nde_a.rank)); - self.set(vb, b_id, redirect(a_id)); - } else if nde_a.rank < nde_b.rank { - debug!("int_vars(): b has smaller rank"); + self.set(vb, node_b.root, Redirect(node_a.root)); + op(node_a.root, node_a.rank) + } else if node_a.rank < node_b.rank { // b has greater rank, so a should redirect to b. - self.set(vb, b_id, root(intersection, nde_b.rank)); - self.set(vb, a_id, redirect(b_id)); + self.set(vb, node_a.root, Redirect(node_b.root)); + op(node_b.root, node_b.rank) } else { - debug!("int_vars(): a and b have equal rank"); - assert nde_a.rank == nde_b.rank; - // If equal, just redirect one to the other and increment - // the other's rank. We choose arbitrarily to redirect b - // to a and increment a's rank. - self.set(vb, a_id, root(intersection, nde_a.rank + 1u)); - self.set(vb, b_id, redirect(a_id)); - }; - } - - fn int_vars(a_id: ty::IntVid, b_id: ty::IntVid) -> ures { - let vb = &self.int_var_bindings; - - let nde_a = self.get(vb, a_id); - let nde_b = self.get(vb, b_id); - let a_id = nde_a.root; - let b_id = nde_b.root; - let a_pt = nde_a.possible_types; - let b_pt = nde_b.possible_types; - - // If we're already dealing with the same two variables, - // there's nothing to do. - if a_id == b_id { return uok(); } - - // Otherwise, take the intersection of the two sets of - // possible types. - let intersection = integral::intersection(a_pt, b_pt); - if *intersection == INT_TY_SET_EMPTY { - return Err(ty::terr_no_integral_type); + // If equal, redirect one to the other and increment the + // other's rank. + assert node_a.rank == node_b.rank; + self.set(vb, node_b.root, Redirect(node_a.root)); + op(node_a.root, node_a.rank + 1) } - - // Rank optimization - self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection); - - uok() } - fn int_var_sub_t(a_id: ty::IntVid, b: ty::t) -> ures { - assert ty::type_is_integral(b); - - let vb = &self.int_var_bindings; - let nde_a = self.get(vb, a_id); - let a_id = nde_a.root; - let a_pt = nde_a.possible_types; - - let intersection = - integral::intersection(a_pt, - convert_integral_ty_to_int_ty_set(self.tcx, b)); - if *intersection == INT_TY_SET_EMPTY { - return Err(ty::terr_no_integral_type); - } - self.set(vb, a_id, root(intersection, nde_a.rank)); - uok() - } - - fn t_sub_int_var(a: ty::t, b_id: ty::IntVid) -> ures { - assert ty::type_is_integral(a); - let vb = &self.int_var_bindings; - - let nde_b = self.get(vb, b_id); - let b_id = nde_b.root; - let b_pt = nde_b.possible_types; - - let intersection = - integral::intersection(b_pt, - convert_integral_ty_to_int_ty_set(self.tcx, a)); - if *intersection == INT_TY_SET_EMPTY { - return Err(ty::terr_no_integral_type); - } - self.set(vb, b_id, root(intersection, nde_b.rank)); - uok() - } - - } // ______________________________________________________________________ -// Floating point variables - -impl infer_ctxt { - fn float_vars(a_id: ty::FloatVid, b_id: ty::FloatVid) -> ures { - let vb = &self.float_var_bindings; - - let nde_a = self.get(vb, a_id); - let nde_b = self.get(vb, b_id); - let a_id = nde_a.root; - let b_id = nde_b.root; - let a_pt = nde_a.possible_types; - let b_pt = nde_b.possible_types; +// Code to handle simple variables like ints, floats---anything that +// doesn't have a subtyping relationship we need to worry about. + +impl @InferCtxt { + fn simple_vars( + vb: &ValsAndBindings>, + err: ty::type_err, + a_id: V, + b_id: V) -> ures + { + /*! + * + * Unifies two simple variables. Because simple variables do + * not have any subtyping relationships, if both variables + * have already been associated with a value, then those two + * values must be the same. */ + + let node_a = self.get(vb, a_id); + let node_b = self.get(vb, b_id); + let a_id = node_a.root; + let b_id = node_b.root; - // If we're already dealing with the same two variables, - // there's nothing to do. if a_id == b_id { return uok(); } - // Otherwise, take the intersection of the two sets of - // possible types. - let intersection = floating::intersection(a_pt, b_pt); - if *intersection == FLOAT_TY_SET_EMPTY { - return Err(ty::terr_no_floating_point_type); - } - - // Rank optimization - self.optimize_ranks(vb, nde_a, nde_b, a_id, b_id, intersection); + let combined = match (&node_a.possible_types, &node_b.possible_types) + { + (&None, &None) => None, + (&Some(ref v), &None) | (&None, &Some(ref v)) => Some(*v), + (&Some(ref v1), &Some(ref v2)) => { + if *v1 != *v2 { return Err(err); } + Some(*v1) + } + }; - uok() + self.unify(vb, &node_a, &node_b, |new_root, new_rank| { + self.set(vb, new_root, Root(combined, new_rank)); + }); + return uok(); } - fn float_var_sub_t(a_id: ty::FloatVid, b: ty::t) -> ures { - assert ty::type_is_fp(b); - - let vb = &self.float_var_bindings; - let nde_a = self.get(vb, a_id); - let a_id = nde_a.root; - let a_pt = nde_a.possible_types; - - let intersection = - floating::intersection( - a_pt, - convert_floating_point_ty_to_float_ty_set(self.tcx, b)); - if *intersection == FLOAT_TY_SET_EMPTY { - return Err(ty::terr_no_floating_point_type); + fn simple_var_t( + vb: &ValsAndBindings>, + err: ty::type_err, + a_id: V, + b: T) -> ures + { + /*! + * + * Sets the value of the variable `a_id` to `b`. Because + * simple variables do not have any subtyping relationships, + * if `a_id` already has a value, it must be the same as + * `b`. */ + + let node_a = self.get(vb, a_id); + let a_id = node_a.root; + + if node_a.possible_types.is_none() { + self.set(vb, a_id, Root(Some(b), node_a.rank)); + return uok(); } - self.set(vb, a_id, root(intersection, nde_a.rank)); - uok() - } - - fn t_sub_float_var(a: ty::t, b_id: ty::FloatVid) -> ures { - assert ty::type_is_fp(a); - let vb = &self.float_var_bindings; - let nde_b = self.get(vb, b_id); - let b_id = nde_b.root; - let b_pt = nde_b.possible_types; - - let intersection = - floating::intersection( - b_pt, - convert_floating_point_ty_to_float_ty_set(self.tcx, a)); - if *intersection == FLOAT_TY_SET_EMPTY { - return Err(ty::terr_no_floating_point_type); + if node_a.possible_types == Some(b) { + return uok(); } - self.set(vb, b_id, root(intersection, nde_b.rank)); - uok() + + return Err(err); } } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 684ee4fa45422..ac9d8eb8e386a 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -52,6 +52,7 @@ independently: use metadata::csearch; use middle::pat_util::{pat_id_map, PatIdMap}; +use middle::resolve; use middle::ty::{arg, field, node_type_table, mk_nil, ty_param_bounds_and_ty}; use middle::ty::{ty_param_substs_and_ty, vstore_uniq}; use middle::ty; @@ -62,6 +63,8 @@ use util::ppaux; use core::dvec::DVec; use core::result::Result; +use core::result; +use core::vec; use std::list::{List, Nil, Cons}; use std::list; use std::map::HashMap; @@ -213,16 +216,17 @@ impl vtable_origin { type vtable_map = HashMap; -type crate_ctxt_ = {// A mapping from method call sites to traits that have - // that method. - trait_map: resolve::TraitMap, - method_map: method_map, - vtable_map: vtable_map, - coherence_info: @coherence::CoherenceInfo, - tcx: ty::ctxt}; +struct crate_ctxt__ { + // A mapping from method call sites to traits that have that method. + trait_map: resolve::TraitMap, + method_map: method_map, + vtable_map: vtable_map, + coherence_info: @coherence::CoherenceInfo, + tcx: ty::ctxt +} enum crate_ctxt { - crate_ctxt_(crate_ctxt_) + crate_ctxt_(crate_ctxt__) } // Functions that write types into the node type table @@ -259,7 +263,7 @@ fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty { fn require_same_types( tcx: ty::ctxt, - maybe_infcx: Option, + maybe_infcx: Option<@infer::InferCtxt>, t1_is_expected: bool, span: span, t1: ty::t, @@ -343,7 +347,8 @@ fn check_main_fn_ty(ccx: @crate_ctxt, match tcx.items.find(main_id) { Some(ast_map::node_item(it,_)) => { match it.node { - ast::item_fn(_,_,ps,_) if vec::is_not_empty(ps) => { + ast::item_fn(_, _, ref ps, _) + if vec::is_not_empty(*ps) => { tcx.sess.span_err( main_span, ~"main function is not allowed \ @@ -389,12 +394,13 @@ fn check_crate(tcx: ty::ctxt, crate: @ast::crate) -> (method_map, vtable_map) { - let ccx = @crate_ctxt_({trait_map: trait_map, - method_map: std::map::HashMap(), - vtable_map: std::map::HashMap(), - coherence_info: @coherence::CoherenceInfo(), - tcx: tcx - }); + let ccx = @crate_ctxt_(crate_ctxt__ { + trait_map: trait_map, + method_map: map::HashMap(), + vtable_map: map::HashMap(), + coherence_info: @coherence::CoherenceInfo(), + tcx: tcx + }); collect::collect_item_types(ccx, crate); coherence::check_coherence(ccx, crate); diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 5fba2b7e6fad6..ecd73b4783a2a 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. + +use middle::ty; + use core::result::Result; +use core::result; +use syntax::ast; use syntax::parse::token::special_idents; trait region_scope { diff --git a/src/librustc/rustc.rc b/src/librustc/rustc.rc index 9331693bf0a5f..60780df52873d 100644 --- a/src/librustc/rustc.rc +++ b/src/librustc/rustc.rc @@ -19,22 +19,22 @@ #[license = "MIT"]; #[crate_type = "lib"]; -#[no_core]; - #[legacy_modes]; #[legacy_exports]; -#[allow(vecs_implicitly_copyable)]; +#[allow(non_implicitly_copyable_typarams)]; #[allow(non_camel_case_types)]; #[allow(deprecated_mode)]; #[warn(deprecated_pattern)]; +#[no_core]; + extern mod core(vers = "0.6"); +use core::*; + extern mod std(vers = "0.6"); extern mod syntax(vers = "0.6"); -use core::*; - /* Alternate names for some modules. @@ -77,7 +77,7 @@ mod middle { #[legacy_exports] mod base; #[legacy_exports] - mod alt; + mod _match; #[legacy_exports] mod uniq; #[legacy_exports] @@ -109,7 +109,7 @@ mod middle { #[legacy_exports] mod check_loop; #[legacy_exports] - mod check_alt; + mod check_match; #[legacy_exports] mod check_const; #[legacy_exports] @@ -262,7 +262,7 @@ Available lint options: fn describe_debug_flags() { io::println(fmt!("\nAvailable debug options:\n")); for session::debugging_opts_map().each |pair| { - let (name, desc, _) = *pair; + let (name, desc, _) = /*bad*/copy *pair; io::println(fmt!(" -Z %-20s -- %s", name, desc)); } } @@ -271,7 +271,7 @@ fn run_compiler(args: &~[~str], demitter: diagnostic::emitter) { // Don't display log spew by default. Can override with RUST_LOG. logging::console_off(); - let mut args = *args; + let mut args = /*bad*/copy *args; let binary = args.shift(); if args.is_empty() { usage(binary); return; } @@ -308,7 +308,7 @@ fn run_compiler(args: &~[~str], demitter: diagnostic::emitter) { let input = match vec::len(matches.free) { 0u => early_error(demitter, ~"no input filename given"), 1u => { - let ifile = matches.free[0]; + let ifile = /*bad*/copy matches.free[0]; if ifile == ~"-" { let src = str::from_bytes(io::stdin().read_whole_stream()); str_input(src) @@ -319,7 +319,8 @@ fn run_compiler(args: &~[~str], demitter: diagnostic::emitter) { _ => early_error(demitter, ~"multiple input filenames provided") }; - let sopts = build_session_options(binary, matches, demitter); + // XXX: Bad copy. + let sopts = build_session_options(copy binary, matches, demitter); let sess = build_session(sopts, demitter); let odir = getopts::opt_maybe_str(matches, ~"out-dir"); let odir = odir.map(|o| Path(*o)); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index c1a88cae13cde..e801721ffc84f 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map::HashMap; + use syntax::ast; use syntax::codemap::{span}; use syntax::visit; use syntax::print; +use syntax; + +use core::option; +use core::str; +use core::vec; +use std::map::HashMap; fn indent(op: fn() -> R) -> R { // Use in conjunction with the log post-processor like `src/etc/indenter` @@ -62,8 +68,9 @@ fn loop_query(b: ast::blk, p: fn@(ast::expr_) -> bool) -> bool { _ => visit::visit_expr(e, flag, v) } }; - let v = visit::mk_vt(@{visit_expr: visit_expr - ,.. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor { + visit_expr: visit_expr, + .. *visit::default_visitor()}); visit::visit_block(b, rs, v); return *rs; } @@ -77,8 +84,9 @@ fn block_query(b: ast::blk, p: fn@(@ast::expr) -> bool) -> bool { *flag |= p(e); visit::visit_expr(e, flag, v) }; - let v = visit::mk_vt(@{visit_expr: visit_expr - ,.. *visit::default_visitor()}); + let v = visit::mk_vt(@visit::Visitor{ + visit_expr: visit_expr, + .. *visit::default_visitor()}); visit::visit_block(b, rs, v); return *rs; } @@ -96,7 +104,7 @@ fn is_main_name(path: syntax::ast_map::path) -> bool { ) } -fn pluralize(n: uint, s: ~str) -> ~str { +fn pluralize(n: uint, +s: ~str) -> ~str { if n == 1 { s } else { str::concat([s, ~"s"]) } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9e2f5a063ac0d..16eb9a2cbd0a3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map::HashMap; + use middle::ty; use middle::ty::{arg, canon_mode}; use middle::ty::{bound_copy, bound_const, bound_durable, bound_owned, bound_trait}; -use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid}; +use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid, + br_fresh}; use middle::ty::{ctxt, field, method}; use middle::ty::{mt, t, param_bound}; use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region}; @@ -23,17 +24,19 @@ use middle::ty::{ty_err, 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}; use middle::ty::{ty_ptr, ty_rec, ty_rptr, ty_self, ty_tup}; use middle::ty::{ty_type, ty_uniq, ty_uint, ty_infer}; -use middle::ty::{ty_unboxed_vec, vid}; +use middle::ty::{ty_unboxed_vec}; use metadata::encoder; use syntax::codemap; use syntax::codemap::span; use syntax::print::pprust; -use syntax::print::pprust::{path_to_str, proto_to_str, - mode_to_str, purity_to_str, - onceness_to_str}; +use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str}; use syntax::{ast, ast_util}; use syntax::ast_map; +use core::str; +use core::vec; +use std::map::HashMap; + fn note_and_explain_region(cx: ctxt, prefix: ~str, region: ty::Region, @@ -66,16 +69,16 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region) re_scope(node_id) => { match cx.items.find(node_id) { Some(ast_map::node_block(ref blk)) => { - explain_span(cx, ~"block", (*blk).span) + explain_span(cx, "block", (*blk).span) } Some(ast_map::node_expr(expr)) => { match expr.node { - ast::expr_call(*) => explain_span(cx, ~"call", expr.span), + ast::expr_call(*) => explain_span(cx, "call", expr.span), ast::expr_method_call(*) => { - explain_span(cx, ~"method call", expr.span) + explain_span(cx, "method call", expr.span) }, - ast::expr_match(*) => explain_span(cx, ~"match", expr.span), - _ => explain_span(cx, ~"expression", expr.span) + ast::expr_match(*) => explain_span(cx, "match", expr.span), + _ => explain_span(cx, "expression", expr.span) } } Some(_) | None => { @@ -90,13 +93,14 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region) let prefix = match br { br_anon(idx) => fmt!("the anonymous lifetime #%u defined on", idx + 1), + br_fresh(_) => fmt!("an anonymous lifetime defined on"), _ => fmt!("the lifetime %s as defined on", bound_region_to_str(cx, br)) }; match cx.items.find(id) { Some(ast_map::node_block(ref blk)) => { - let (msg, opt_span) = explain_span(cx, ~"block", (*blk).span); + let (msg, opt_span) = explain_span(cx, "block", (*blk).span); (fmt!("%s %s", prefix, msg), opt_span) } Some(_) | None => { @@ -115,7 +119,7 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region) } }; - fn explain_span(cx: ctxt, heading: ~str, span: span) + fn explain_span(cx: ctxt, heading: &str, span: span) -> (~str, Option) { let lo = cx.sess.codemap.lookup_char_pos_adj(span.lo); @@ -125,17 +129,18 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region) } fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str { - bound_region_to_str_adorned(cx, ~"&", br, ~"") + bound_region_to_str_adorned(cx, "&", br, "") } -fn bound_region_to_str_adorned(cx: ctxt, prefix: ~str, - br: bound_region, sep: ~str) -> ~str { +fn bound_region_to_str_adorned(cx: ctxt, prefix: &str, + br: bound_region, sep: &str) -> ~str { if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, sep); } match br { br_named(id) => fmt!("%s%s%s", prefix, cx.sess.str_of(id), sep), br_self => fmt!("%sself%s", prefix, sep), - br_anon(_) => prefix, + br_anon(_) => prefix.to_str(), + br_fresh(_) => prefix.to_str(), br_cap_avoid(_, br) => bound_region_to_str_adorned(cx, prefix, *br, sep) } @@ -154,7 +159,7 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { cx.sess.codemap.span_to_str(expr.span)) } ast::expr_match(*) => { - fmt!("", + fmt!("", cx.sess.codemap.span_to_str(expr.span)) } ast::expr_assign_op(*) | @@ -185,11 +190,11 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str { // you should use `explain_region()` or, better yet, // `note_and_explain_region()` fn region_to_str(cx: ctxt, region: Region) -> ~str { - region_to_str_adorned(cx, ~"&", region, ~"") + region_to_str_adorned(cx, "&", region, "") } -fn region_to_str_adorned(cx: ctxt, prefix: ~str, - region: Region, sep: ~str) -> ~str { +fn region_to_str_adorned(cx: ctxt, prefix: &str, + region: Region, sep: &str) -> ~str { if cx.sess.verbose() { return fmt!("%s%?%s", prefix, region, sep); } @@ -199,24 +204,24 @@ fn region_to_str_adorned(cx: ctxt, prefix: ~str, // to fit that into a short string. Hence the recommendation to use // `explain_region()` or `note_and_explain_region()`. match region { - re_scope(_) => prefix, + re_scope(_) => prefix.to_str(), re_bound(br) => bound_region_to_str_adorned(cx, prefix, br, sep), re_free(_, br) => bound_region_to_str_adorned(cx, prefix, br, sep), re_infer(ReSkolemized(_, br)) => { bound_region_to_str_adorned(cx, prefix, br, sep) } - re_infer(ReVar(_)) => prefix, + re_infer(ReVar(_)) => prefix.to_str(), re_static => fmt!("%sstatic%s", prefix, sep) } } fn mt_to_str(cx: ctxt, m: mt) -> ~str { let mstr = match m.mutbl { - ast::m_mutbl => ~"mut ", - ast::m_imm => ~"", - ast::m_const => ~"const " + ast::m_mutbl => "mut ", + ast::m_imm => "", + ast::m_const => "const " }; - return mstr + ty_to_str(cx, m.ty); + return fmt!("%s%s", mstr, ty_to_str(cx, m.ty)); } fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str { @@ -240,12 +245,14 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str { } } -fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> ~str { +fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto, + followed_by_word: bool) -> &static/str { match proto { - ast::ProtoBare => ~"", - ast::ProtoBox => ~"@", - ast::ProtoBorrowed => ~"&", - ast::ProtoUniq => ~"~", + ast::ProtoBare if followed_by_word => "extern ", + ast::ProtoBare => "extern", + ast::ProtoBox => "@", + ast::ProtoBorrowed => "&", + ast::ProtoUniq => "~", } } @@ -255,15 +262,21 @@ fn expr_repr(cx: ctxt, expr: @ast::expr) -> ~str { pprust::expr_to_str(expr, cx.sess.intr())) } -fn tys_to_str(cx: ctxt, ts: ~[t]) -> ~str { +fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str { let tstrs = ts.map(|t| ty_to_str(cx, *t)); - fmt!("[%s]", str::connect(tstrs, ", ")) + fmt!("(%s)", str::connect(tstrs, ", ")) } fn bound_to_str(cx: ctxt, b: param_bound) -> ~str { ty::param_bound_to_str(cx, &b) } +fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str { + fmt!("fn%s -> %s", + tys_to_str(cx, typ.inputs.map(|a| a.ty)), + ty_to_str(cx, typ.output)) +} + fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) -> ~str { @@ -275,11 +288,11 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { m == ty::default_arg_mode_for_ty(cx, ty) { ~"" } else { - mode_to_str(ast::expl(m)) + ":" + mode_to_str(ast::expl(m)) + ~":" } } }; - modestr + ty_to_str(cx, ty) + fmt!("%s%s", modestr, ty_to_str(cx, ty)) } fn fn_to_str(cx: ctxt, proto: ast::Proto, @@ -287,22 +300,21 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { purity: ast::purity, onceness: ast::Onceness, ident: Option, - inputs: ~[arg], - output: t, - cf: ast::ret_style) -> ~str { + inputs: &[arg], + output: t) -> ~str { let mut s; s = match purity { ast::impure_fn => ~"", - _ => purity_to_str(purity) + ~" " + _ => purity.to_str() + ~" " }; s += match onceness { ast::Many => ~"", - ast::Once => onceness_to_str(onceness) + ~" " + ast::Once => onceness.to_str() + ~" " }; - s += proto_ty_to_str(cx, proto); + s += proto_ty_to_str(cx, proto, true); match (proto, region) { (ast::ProtoBox, ty::re_static) | @@ -327,9 +339,10 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { s += ~")"; if ty::get(output).sty != ty_nil { s += ~" -> "; - match cf { - ast::noreturn => { s += ~"!"; } - ast::return_val => { s += ty_to_str(cx, output); } + if ty::type_is_bot(output) { + s += ~"!"; + } else { + s += ty_to_str(cx, output); } } return s; @@ -343,24 +356,23 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { m.fty.meta.onceness, Some(m.ident), m.fty.sig.inputs, - m.fty.sig.output, - m.fty.meta.ret_style) + ~";"; + m.fty.sig.output) + ~";"; } fn field_to_str(cx: ctxt, f: field) -> ~str { return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt); } // if there is an id, print that instead of the structural type: - for ty::type_def_id(typ).each |def_id| { + /*for ty::type_def_id(typ).each |def_id| { // note that this typedef cannot have type parameters return ast_map::path_to_str(ty::item_path(cx, *def_id), cx.sess.intr()); - } + }*/ // pretty print the structural type representation: - return match ty::get(typ).sty { + return match /*bad*/copy ty::get(typ).sty { ty_nil => ~"()", - ty_bot => ~"_|_", + ty_bot => ~"!", ty_bool => ~"bool", ty_int(ast::ty_i) => ~"int", ty_int(ast::ty_char) => ~"char", @@ -393,8 +405,7 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { f.meta.onceness, None, f.sig.inputs, - f.sig.output, - f.meta.ret_style) + f.sig.output) } ty_infer(infer_ty) => infer_ty.to_str(), ty_err => ~"[type error]", @@ -405,12 +416,12 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { ty_enum(did, ref substs) | ty_struct(did, ref substs) => { let path = ty::item_path(cx, did); let base = ast_map::path_to_str(path, cx.sess.intr()); - parameterized(cx, base, (*substs).self_r, (*substs).tps) + parameterized(cx, base, substs.self_r, substs.tps) } ty_trait(did, ref substs, vs) => { let path = ty::item_path(cx, did); let base = ast_map::path_to_str(path, cx.sess.intr()); - let result = parameterized(cx, base, (*substs).self_r, (*substs).tps); + let result = parameterized(cx, base, substs.self_r, substs.tps); vstore_ty_to_str(cx, result, vs) } ty_evec(mt, vs) => { @@ -426,9 +437,9 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str { } fn parameterized(cx: ctxt, - base: ~str, + base: &str, self_r: Option, - tps: ~[ty::t]) -> ~str { + tps: &[ty::t]) -> ~str { let r_str = match self_r { None => ~"", @@ -439,7 +450,7 @@ fn parameterized(cx: ctxt, if vec::len(tps) > 0u { let strs = vec::map(tps, |t| ty_to_str(cx, *t)); - fmt!("%s%s<%s>", base, r_str, str::connect(strs, ~",")) + fmt!("%s%s<%s>", base, r_str, str::connect(strs, ",")) } else { fmt!("%s%s", base, r_str) } diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs index 14b7b52e4d360..83516a589b5f5 100644 --- a/src/librustdoc/astsrv.rs +++ b/src/librustdoc/astsrv.rs @@ -17,6 +17,11 @@ query AST-related information, shielding the rest of Rustdoc from its non-sendableness. */ +use parse; +use util; + +use core::oldcomm; +use core::vec; use rustc::back::link; use rustc::driver::driver; use rustc::driver::session::Session; @@ -30,6 +35,7 @@ use syntax::ast_map; use syntax::codemap; use syntax::diagnostic::handler; use syntax::diagnostic; +use syntax; pub type Ctxt = { ast: @ast::crate, diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs index 1a46b924147ee..e47bdbb00daab 100644 --- a/src/librustdoc/attr_parser.rs +++ b/src/librustdoc/attr_parser.rs @@ -15,9 +15,13 @@ The attribute parser provides methods for pulling documentation out of an AST's attributes. */ +use core::str; +use core::tuple; +use core::vec; use syntax::ast; use syntax::attr; -use core::tuple; +use syntax::codemap; +use syntax; pub type CrateAttrs = { name: Option<~str> @@ -27,6 +31,9 @@ pub type CrateAttrs = { mod test { #[legacy_exports]; + use syntax::ast; + use syntax; + fn parse_attributes(+source: ~str) -> ~[ast::attribute] { use syntax::parse; use syntax::parse::parser; diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index 0180d18668daf..bc6d1f5ad9de0 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -16,15 +16,23 @@ corresponding AST nodes. The information gathered here is the basis of the natural-language documentation for a crate. */ +use astsrv; +use attr_parser; use doc::ItemUtils; +use doc; use extract::to_str; use fold::Fold; +use fold; + +use core::option; +use core::vec; use syntax::ast; use syntax::ast_map; use std::map::HashMap; +use std::par; pub fn mk_pass() -> Pass { - { + Pass { name: ~"attr", f: run } @@ -61,7 +69,7 @@ fn fold_crate( { topmod: doc::ModDoc_({ item: { - name: option::get_default(attrs.name, doc.topmod.name()), + name: option::get_or_default(attrs.name, doc.topmod.name()), .. doc.topmod.item }, .. *doc.topmod @@ -302,6 +310,11 @@ fn should_extract_impl_method_docs() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use doc; + use extract; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index ec600860690bf..94b3a96618476 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -8,7 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use result::Result; +use core::cmp; +use core::os; +use core::result; +use core::run; +use core::vec; +use core::result::Result; use std::getopts; use std::cell::Cell; @@ -149,7 +154,7 @@ fn config_from_opts( let output_dir = getopts::opt_maybe_str(matches, opt_output_dir()); let output_dir = output_dir.map(|s| Path(*s)); result::Ok({ - output_dir: output_dir.get_default(config.output_dir), + output_dir: output_dir.get_or_default(config.output_dir), .. config }) }; diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index fa21366d917cc..001f958c2e583 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -15,11 +15,18 @@ If the first paragraph of a long description is short enough then it is interpreted as the brief description. */ +use astsrv; use doc::ItemUtils; +use doc; use fold::Fold; +use fold; + +use core::str; +use core::vec; +use std::par; pub fn mk_pass() -> Pass { - { + Pass { name: ~"desc_to_brief", f: run } @@ -93,6 +100,12 @@ fn should_promote_impl_method_desc() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use attr_pass; + use doc; + use extract; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/doc.rs b/src/librustdoc/doc.rs index c7d52fb77d663..4b5f82235dd0b 100644 --- a/src/librustdoc/doc.rs +++ b/src/librustdoc/doc.rs @@ -10,6 +10,12 @@ //! The document model +use doc; + +use core::cmp; +use core::option; +use core::vec; + pub type AstId = int; pub type Doc_ = { diff --git a/src/librustdoc/escape_pass.rs b/src/librustdoc/escape_pass.rs index 9daf334758603..46b2106377463 100644 --- a/src/librustdoc/escape_pass.rs +++ b/src/librustdoc/escape_pass.rs @@ -10,6 +10,10 @@ //! Escapes text sequences +use text_pass; + +use core::str; + pub fn mk_pass() -> Pass { text_pass::mk_pass(~"escape", escape) } diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs index 717ae9d7fba8e..8f2c61ba26ee9 100644 --- a/src/librustdoc/extract.rs +++ b/src/librustdoc/extract.rs @@ -10,9 +10,15 @@ //! Converts the Rust AST to the rustdoc document model -use syntax::ast; +use astsrv; use doc::ItemUtils; -use task::local_data::local_data_get; +use doc; + +use core::cast; +use core::task::local_data::local_data_get; +use core::vec; +use syntax::ast; +use syntax; /* can't import macros yet, so this is copied from token.rs. See its comment * there. */ @@ -338,6 +344,12 @@ fn should_extract_struct_fields() { mod test { #[legacy_exports]; + use astsrv; + use doc; + use parse; + + use core::vec; + fn mk_doc(+source: ~str) -> doc::Doc { let ast = parse::from_str(source); extract(ast, ~"") diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index ba626f80ddb8f..deb6af224e5d4 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -8,6 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use astsrv; +use doc; +use extract; +use parse; + +use core::vec; +use std::par; + pub struct Fold { ctxt: T, fold_doc: FoldDoc, diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index b1cc778bd1bf3..a84f4d66ab288 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -10,11 +10,20 @@ //! Build indexes as appropriate for the markdown pass +use astsrv; +use config; use doc::ItemUtils; +use doc; use fold::Fold; +use fold; +use markdown_pass; +use markdown_writer; + +use core::str; +use std::par; pub fn mk_pass(+config: config::Config) -> Pass { - { + Pass { name: ~"markdown_index", f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, config) @@ -243,6 +252,15 @@ fn should_index_foreign_mod_contents() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use attr_pass; + use config; + use desc_to_brief_pass; + use doc; + use extract; + use path_pass; + fn mk_doc(output_style: config::OutputStyle, +source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let config = { diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs index 3328cdd527a86..87cdefd90df89 100644 --- a/src/librustdoc/markdown_pass.rs +++ b/src/librustdoc/markdown_pass.rs @@ -10,10 +10,33 @@ //! Generate markdown from a document tree +use astsrv; +use attr_pass; +use config; +use desc_to_brief_pass; use doc::ItemUtils; +use doc; +use extract; +use fold; +use markdown_index_pass; +use markdown_pass; use markdown_writer::Writer; use markdown_writer::WriterUtils; use markdown_writer::WriterFactory; +use markdown_writer; +use page_pass; +use path_pass; +use sectionalize_pass; +use sort_pass; +use trim_pass; +use unindent_pass; + +use core::iter; +use core::oldcomm; +use core::str; +use core::vec; +use std::par; +use syntax; pub fn mk_pass(+writer_factory: WriterFactory) -> Pass { let f = fn~(move writer_factory, @@ -21,7 +44,7 @@ pub fn mk_pass(+writer_factory: WriterFactory) -> Pass { run(srv, doc, copy writer_factory) }; - { + Pass { name: ~"markdown", f: move f } @@ -212,7 +235,7 @@ pub fn header_kind(+doc: doc::ItemTag) -> ~str { ~"Enum" } doc::TraitTag(_) => { - ~"Interface" + ~"Trait" } doc::ImplTag(_) => { ~"Implementation" @@ -701,7 +724,7 @@ fn write_method(ctxt: &Ctxt, +doc: doc::MethodDoc) { #[test] fn should_write_trait_header() { let markdown = test::render(~"trait i { fn a(); }"); - assert str::contains(markdown, ~"## Interface `i`"); + assert str::contains(markdown, ~"## Trait `i`"); } #[test] @@ -807,6 +830,24 @@ fn should_write_struct_header() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use attr_pass; + use config; + use desc_to_brief_pass; + use doc; + use extract; + use markdown_index_pass; + use markdown_writer; + use path_pass; + use sectionalize_pass; + use trim_pass; + use tystr_pass; + use unindent_pass; + + use core::oldcomm; + use core::str; + fn render(+source: ~str) -> ~str { let (srv, doc) = create_doc_srv(source); let markdown = write_markdown_str_srv(srv, doc); diff --git a/src/librustdoc/markdown_writer.rs b/src/librustdoc/markdown_writer.rs index 9cf404e0533d5..f4e5db304e7d6 100644 --- a/src/librustdoc/markdown_writer.rs +++ b/src/librustdoc/markdown_writer.rs @@ -8,9 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use config; use doc::ItemUtils; -use io::ReaderUtil; +use doc; + +use core::io::ReaderUtil; +use core::io; +use core::libc; +use core::oldcomm; +use core::os; +use core::pipes; +use core::result; +use core::run; +use core::str; +use core::task; use std::future; +use syntax; pub enum WriteInstr { Write(~str), @@ -254,6 +267,12 @@ fn should_name_mod_file_names_by_path() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use doc; + use extract; + use path_pass; + fn mk_doc(+name: ~str, +source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, name); diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index af8ac5f1427ef..d495654e67db4 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -15,13 +15,23 @@ Each page corresponds is a logical section. There may be pages for individual modules, pages for the crate, indexes, etc. */ +use astsrv; +use config; use doc::{ItemUtils, PageUtils}; +use doc; use fold::Fold; -use syntax::ast; +use fold; +use sort_pass; use util::NominalOp; +use util; + +use core::oldcomm; +use core::option; +use core::vec; +use syntax::ast; pub fn mk_pass(output_style: config::OutputStyle) -> Pass { - { + Pass { name: ~"page", f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, output_style) @@ -173,6 +183,12 @@ fn should_remove_foreign_mods_from_containing_mods() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use config; + use doc; + use extract; + fn mk_doc_( output_style: config::OutputStyle, source: ~str diff --git a/src/librustdoc/pass.rs b/src/librustdoc/pass.rs index 0fbc61ad4544d..a893ba23d32ad 100644 --- a/src/librustdoc/pass.rs +++ b/src/librustdoc/pass.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use astsrv; +use doc; +use extract; + +use core::vec; + /// A single operation on the document model -pub type Pass = { +pub struct Pass { name: ~str, f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc -}; +} pub fn run_passes( srv: astsrv::Srv, @@ -73,11 +79,11 @@ fn test_run_passes() { let source = ~""; do astsrv::from_str(source) |srv| { let passes = ~[ - { + Pass { name: ~"", f: pass1 }, - { + Pass { name: ~"", f: pass2 } diff --git a/src/librustdoc/path_pass.rs b/src/librustdoc/path_pass.rs index b17f4d67a5c32..b2729d7155049 100644 --- a/src/librustdoc/path_pass.rs +++ b/src/librustdoc/path_pass.rs @@ -10,12 +10,17 @@ //! Records the full path to items +use astsrv; use doc::ItemUtils; +use doc; +use extract; use fold::Fold; +use fold; + use syntax::ast; pub fn mk_pass() -> Pass { - { + Pass { name: ~"path", f: run } diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs index bfe6f83870416..162d0d446f56e 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -10,12 +10,18 @@ //! Prunes things with the #[doc(hidden)] attribute +use astsrv; +use attr_parser; use doc::ItemUtils; +use doc; use fold::Fold; +use fold; + +use core::vec; use std::map::HashMap; pub fn mk_pass() -> Pass { - { + Pass { name: ~"prune_hidden", f: run } @@ -65,6 +71,11 @@ fn should_prune_hidden_items() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use doc; + use extract; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index e3dc1553a6392..10f5b42a4f274 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -12,12 +12,19 @@ #[legacy_exports]; +use astsrv; +use doc; use fold::Fold; +use fold; + +use core::util; +use core::vec; +use syntax::ast; export mk_pass; fn mk_pass() -> Pass { - { + Pass { name: ~"prune_private", f: run } @@ -56,7 +63,7 @@ fn is_visible(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool { ast_map::node_item(item, _) => { item.vis == ast::public } - _ => core::util::unreachable() + _ => util::unreachable() } } } @@ -69,6 +76,10 @@ fn should_prune_items_without_pub_modifier() { #[cfg(test)] mod test { + use astsrv; + use doc; + use extract; + pub fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index 2c73d4c478b12..186fddc528dce 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -10,11 +10,20 @@ //! Breaks rustdocs into sections according to their headers +use astsrv; +use attr_pass; use doc::ItemUtils; +use doc; +use extract; use fold::Fold; +use fold; + +use core::str; +use core::vec; +use std::par; pub fn mk_pass() -> Pass { - { + Pass { name: ~"sectionalize", f: run } @@ -242,6 +251,12 @@ fn should_sectionalize_impl_methods() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use attr_pass; + use doc; + use extract; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/sort_item_name_pass.rs b/src/librustdoc/sort_item_name_pass.rs index 3ef4750b9ad84..58349318bbbec 100644 --- a/src/librustdoc/sort_item_name_pass.rs +++ b/src/librustdoc/sort_item_name_pass.rs @@ -10,7 +10,11 @@ //! Sorts items by name +use astsrv; use doc::ItemUtils; +use doc; +use extract; +use sort_pass; pub fn mk_pass() -> Pass { pure fn by_item_name(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { diff --git a/src/librustdoc/sort_item_type_pass.rs b/src/librustdoc/sort_item_type_pass.rs index 25fc11a4a2a0e..4f69a307c204b 100644 --- a/src/librustdoc/sort_item_type_pass.rs +++ b/src/librustdoc/sort_item_type_pass.rs @@ -10,7 +10,11 @@ //! Sorts items by type +use astsrv; use doc::ItemUtils; +use doc; +use extract; +use sort_pass; pub fn mk_pass() -> Pass { pure fn by_score(item1: &doc::ItemTag, item2: &doc::ItemTag) -> bool { diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs index a4926e765a773..4b3c3730a0378 100644 --- a/src/librustdoc/sort_pass.rs +++ b/src/librustdoc/sort_pass.rs @@ -10,17 +10,22 @@ //! A general sorting pass +use astsrv; use doc::ItemUtils; +use doc; +use extract; use fold::Fold; -use std::sort; +use fold; use util::NominalOp; +use std::sort; + pub type ItemLtEqOp = pure fn~(v1: &doc::ItemTag, v2: &doc::ItemTag) -> bool; type ItemLtEq = NominalOp; pub fn mk_pass(name: ~str, +lteq: ItemLtEqOp) -> Pass { - { + Pass { name: name, f: fn~(move lteq, srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, NominalOp { op: copy lteq }) diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index 9a48822b45360..c3b1a4fb67ee2 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -10,12 +10,17 @@ //! Generic pass for performing an operation on all descriptions +use astsrv; use doc::ItemUtils; +use doc; use fold::Fold; +use fold; use util::NominalOp; +use std::par; + pub fn mk_pass(name: ~str, +op: fn~(~str) -> ~str) -> Pass { - { + Pass { name: name, f: fn~(move op, srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { run(srv, doc, copy op) @@ -284,6 +289,16 @@ fn should_execute_on_impl_method_section_bodies() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use attr_pass; + use desc_to_brief_pass; + use doc; + use extract; + use sectionalize_pass; + + use core::str; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/trim_pass.rs b/src/librustdoc/trim_pass.rs index e6696b74eaec3..731a2bb7ad6eb 100644 --- a/src/librustdoc/trim_pass.rs +++ b/src/librustdoc/trim_pass.rs @@ -16,6 +16,10 @@ is interpreted as the brief description. */ use doc::ItemUtils; +use doc; +use text_pass; + +use core::str; pub fn mk_pass() -> Pass { text_pass::mk_pass(~"trim", |s| str::trim(s) ) @@ -32,6 +36,12 @@ fn should_trim_text() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use attr_pass; + use doc; + use extract; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index 4609454315f26..0a3fd75f288f3 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -10,16 +10,23 @@ //! Pulls type information out of the AST and attaches it to the document +use astsrv; use doc::ItemUtils; +use doc; +use extract::to_str; +use extract; use fold::Fold; +use fold; + +use core::vec; +use std::map::HashMap; +use std::par; use syntax::ast; use syntax::print::pprust; use syntax::ast_map; -use std::map::HashMap; -use extract::to_str; pub fn mk_pass() -> Pass { - { + Pass { name: ~"tystr", f: run } @@ -400,6 +407,11 @@ fn should_not_serialize_struct_attrs() { #[cfg(test)] mod test { #[legacy_exports]; + + use astsrv; + use doc; + use extract; + fn mk_doc(source: ~str) -> doc::Doc { do astsrv::from_str(source) |srv| { let doc = extract::from_srv(srv, ~""); diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs index a2a402385004a..e18d1652a5b7e 100644 --- a/src/librustdoc/unindent_pass.rs +++ b/src/librustdoc/unindent_pass.rs @@ -19,6 +19,13 @@ instances where the string containing the doc comment is opened in the middle of a line, and each of the following lines is indented. */ +use text_pass; + +use core::str; +use core::uint; +use core::vec; +use std::par; + pub fn mk_pass() -> Pass { text_pass::mk_pass(~"unindent", unindent) } diff --git a/src/librustdoc/util.rs b/src/librustdoc/util.rs index ebeb9346d3c49..998b64421d506 100644 --- a/src/librustdoc/util.rs +++ b/src/librustdoc/util.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::oldcomm; +use core::task; + // Just a named container for our op, so it can have impls pub struct NominalOp { op: T diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 8afb8d3f85136..828877fc4a401 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -134,6 +134,7 @@ fn run(repl: Repl, input: ~str) -> Repl { crate_type: session::unknown_crate, binary: repl.binary, addl_lib_search_paths: repl.lib_search_paths.map(|p| Path(*p)), + jit: true, .. *session::basic_options() }; @@ -153,8 +154,12 @@ fn run(repl: Repl, input: ~str) -> Repl { repl.binary, wrapped); - debug!("parsing"); - let mut crate = driver::parse_input(sess, cfg, wrapped); + let outputs = driver::build_output_filenames(wrapped, &None, &None, sess); + debug!("calling compile_upto"); + let {crate: crate, tcx: _} = driver::compile_upto(sess, cfg, wrapped, + driver::cu_everything, + Some(outputs)); + let mut opt = None; for crate.node.module.items.each |item| { @@ -177,114 +182,6 @@ fn run(repl: Repl, input: ~str) -> Repl { } _ => fail }; - - debug!("configuration"); - crate = front::config::strip_unconfigured_items(crate); - - debug!("maybe building test harness"); - crate = front::test::modify_for_testing(sess, crate); - - debug!("expansion"); - crate = syntax::ext::expand::expand_crate(sess.parse_sess, - sess.opts.cfg, - crate); - - debug!("intrinsic injection"); - crate = front::intrinsic_inject::inject_intrinsic(sess, crate); - - debug!("core injection"); - crate = front::core_inject::maybe_inject_libcore_ref(sess, crate); - - debug!("building lint settings table"); - lint::build_settings_crate(sess, crate); - - debug!("ast indexing"); - let ast_map = syntax::ast_map::map_crate(sess.diagnostic(), *crate); - - debug!("external crate/lib resolution"); - creader::read_crates(sess.diagnostic(), *crate, sess.cstore, - sess.filesearch, - session::sess_os_to_meta_os(sess.targ_cfg.os), - sess.opts.static, sess.parse_sess.interner); - - debug!("language item collection"); - let lang_items = middle::lang_items::collect_language_items(crate, sess); - - debug!("resolution"); - let {def_map: def_map, - exp_map2: exp_map2, - trait_map: trait_map} = middle::resolve::resolve_crate(sess, - lang_items, - crate); - - debug!("freevar finding"); - let freevars = freevars::annotate_freevars(def_map, crate); - - debug!("region_resolution"); - let region_map = middle::region::resolve_crate(sess, def_map, crate); - - debug!("region paramaterization inference"); - let rp_set = middle::region::determine_rp_in_crate(sess, ast_map, - def_map, crate); - - debug!("typechecking"); - let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars, - region_map, rp_set, move lang_items, crate); - let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map, - crate); - - debug!("const marking"); - middle::const_eval::process_crate(crate, def_map, ty_cx); - - debug!("const checking"); - middle::check_const::check_crate(sess, crate, ast_map, def_map, - method_map, ty_cx); - - debug!("privacy checking"); - middle::privacy::check_crate(ty_cx, &method_map, crate); - - debug!("loop checking"); - middle::check_loop::check_crate(ty_cx, crate); - - debug!("mode computation"); - middle::mode::compute_modes(ty_cx, method_map, crate); - - debug!("alt checking"); - middle::check_alt::check_crate(ty_cx, method_map, crate); - - debug!("liveness checking"); - let last_use_map = middle::liveness::check_crate(ty_cx, - method_map, crate); - - debug!("borrow checking"); - let (root_map, mutbl_map) = middle::borrowck::check_crate(ty_cx, - method_map, - last_use_map, - crate); - - debug!("kind checking"); - kind::check_crate(ty_cx, method_map, last_use_map, crate); - - debug!("lint checking"); - lint::check_crate(ty_cx, crate); - - let maps = {mutbl_map: mutbl_map, - root_map: root_map, - last_use_map: last_use_map, - method_map: method_map, - vtable_map: vtable_map}; - - debug!("translation"); - let path = ~path::GenericPath::from_str(""); - let (llmod, _) = trans::base::trans_crate(sess, crate, ty_cx, - path, - exp_map2, maps); - let pm = llvm::LLVMCreatePassManager(); - - debug!("executing jit"); - back::link::jit::exec(sess, pm, llmod, 0, false); - llvm::LLVMDisposePassManager(pm); - debug!("recording input into repl history"); record(repl, blk, sess.parse_sess.interner) } @@ -380,7 +277,7 @@ fn run_cmd(repl: &mut Repl, _in: io::Reader, _out: io::Writer, io::println( ~":{\\n ..lines.. \\n:}\\n - execute multiline command\n" + ~":load ... - \ - loads given crates as dynamic libraries" + + loads given crates as dynamic libraries\n" + ~":clear - clear the screen\n" + ~":exit - exit from the repl\n" + ~":help - show this message"); diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs index e2bbda46d7cf3..b38f756a2b57d 100644 --- a/src/libstd/arc.rs +++ b/src/libstd/arc.rs @@ -15,12 +15,17 @@ * between tasks. */ -use private::{SharedMutableState, shared_mutable_state, - clone_shared_mutable_state, unwrap_shared_mutable_state, - get_shared_mutable_state, get_shared_immutable_state}; -use sync::{Mutex, mutex_with_condvars, - RWlock, rwlock_with_condvars}; - +use sync; +use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars}; + +use core::cast; +use core::pipes; +use core::private::{SharedMutableState, shared_mutable_state}; +use core::private::{clone_shared_mutable_state, unwrap_shared_mutable_state}; +use core::private::{get_shared_mutable_state, get_shared_immutable_state}; +use core::ptr; +use core::task; +use core::util; /// As sync::condvar, a mechanism for unlock-and-descheduling and signalling. pub struct Condvar { is_mutex: bool, failed: &mut bool, cond: &sync::Condvar } @@ -464,7 +469,15 @@ impl &RWReadMode { #[cfg(test)] mod tests { #[legacy_exports]; - use comm::*; + + use arc; + + use core::oldcomm::*; + use core::option::{Some, None}; + use core::option; + use core::pipes; + use core::task; + use core::vec; #[test] fn manually_share_arc() { diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index 9054f9355ad87..e817e6e160f7a 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -34,10 +34,19 @@ #[forbid(deprecated_mode)]; +use arena; +use list; use list::{List, Cons, Nil}; -use cast::reinterpret_cast; -use sys::TypeDesc; -use libc::size_t; + +use core::at_vec; +use core::cast::reinterpret_cast; +use core::cast; +use core::libc::size_t; +use core::ptr; +use core::sys::TypeDesc; +use core::sys; +use core::uint; +use core::vec; #[abi = "rust-intrinsic"] extern mod rusti { diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs index 43f13b5b91f48..db3991a1d3bed 100644 --- a/src/libstd/base64.rs +++ b/src/libstd/base64.rs @@ -9,7 +9,11 @@ // except according to those terms. #[forbid(deprecated_mode)]; -use io::Reader; + +use core::io::Reader; +use core::iter; +use core::str; +use core::vec; pub trait ToBase64 { pure fn to_base64() -> ~str; @@ -149,6 +153,9 @@ impl ~str: FromBase64 { #[cfg(test)] mod tests { #[legacy_exports]; + + use core::str; + #[test] fn test_to_base64() { assert (~"").to_base64() == ~""; diff --git a/src/libstd/bigint.rs b/src/libstd/bigint.rs new file mode 100644 index 0000000000000..37d5890070ace --- /dev/null +++ b/src/libstd/bigint.rs @@ -0,0 +1,1498 @@ +/*! + +A Big integer (signed version: BigInt, unsigned version: BigUint). + +A BigUint is represented as an array of BigDigits. +A BigInt is a combination of BigUint and Sign. +*/ + +use core::cmp::{Eq, Ord}; +use core::num::{Num, Zero, One}; +use core::*; + +/** +A BigDigit is a BigUint's composing element. + +A BigDigit is half the size of machine word size. +*/ +#[cfg(target_arch = "x86")] +#[cfg(target_arch = "arm")] +pub type BigDigit = u16; + +/** +A BigDigit is a BigUint's composing element. + +A BigDigit is half the size of machine word size. +*/ +#[cfg(target_arch = "x86_64")] +pub type BigDigit = u32; + +pub mod BigDigit { + #[cfg(target_arch = "x86")] + #[cfg(target_arch = "arm")] + pub const bits: uint = 16; + + #[cfg(target_arch = "x86_64")] + pub const bits: uint = 32; + + pub const base: uint = 1 << bits; + priv const hi_mask: uint = (-1 as uint) << bits; + priv const lo_mask: uint = (-1 as uint) >> bits; + + priv pure fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit } + priv pure fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit } + + /// Split one machine sized unsigned integer into two BigDigits. + pub pure fn from_uint(n: uint) -> (BigDigit, BigDigit) { + (get_hi(n), get_lo(n)) + } + + /// Join two BigDigits into one machine sized unsigned integer + pub pure fn to_uint(hi: BigDigit, lo: BigDigit) -> uint { + (lo as uint) | ((hi as uint) << bits) + } +} + +/** +A big unsigned integer type. + +A BigUint-typed value BigUint { data: @[a, b, c] } represents a number +(a + b * BigDigit::base + c * BigDigit::base^2). +*/ +pub struct BigUint { + priv data: ~[BigDigit] +} + +impl BigUint : Eq { + pure fn eq(&self, other: &BigUint) -> bool { self.cmp(other) == 0 } + pure fn ne(&self, other: &BigUint) -> bool { self.cmp(other) != 0 } +} + +impl BigUint : Ord { + pure fn lt(&self, other: &BigUint) -> bool { self.cmp(other) < 0 } + pure fn le(&self, other: &BigUint) -> bool { self.cmp(other) <= 0 } + pure fn ge(&self, other: &BigUint) -> bool { self.cmp(other) >= 0 } + pure fn gt(&self, other: &BigUint) -> bool { self.cmp(other) > 0 } +} + +impl BigUint : ToStr { + pure fn to_str() -> ~str { self.to_str_radix(10) } +} + +impl BigUint : from_str::FromStr { + static pure fn from_str(s: &str) -> Option { + BigUint::from_str_radix(s, 10) + } +} + +impl BigUint : Shl { + pure fn shl(&self, rhs: &uint) -> BigUint { + let n_unit = *rhs / BigDigit::bits; + let n_bits = *rhs % BigDigit::bits; + return self.shl_unit(n_unit).shl_bits(n_bits); + } +} + +impl BigUint : Shr { + pure fn shr(&self, rhs: &uint) -> BigUint { + let n_unit = *rhs / BigDigit::bits; + let n_bits = *rhs % BigDigit::bits; + return self.shr_unit(n_unit).shr_bits(n_bits); + } +} + +impl BigUint : Zero { + static pure fn zero() -> BigUint { BigUint::new(~[]) } +} + +impl BigUint : One { + static pub pure fn one() -> BigUint { BigUint::new(~[1]) } +} + +impl BigUint : Num { + pure fn add(&self, other: &BigUint) -> BigUint { + let new_len = uint::max(self.data.len(), other.data.len()); + + let mut carry = 0; + let sum = do vec::from_fn(new_len) |i| { + let ai = if i < self.data.len() { self.data[i] } else { 0 }; + let bi = if i < other.data.len() { other.data[i] } else { 0 }; + let (hi, lo) = BigDigit::from_uint( + (ai as uint) + (bi as uint) + (carry as uint) + ); + carry = hi; + lo + }; + if carry == 0 { return BigUint::new(sum) }; + return BigUint::new(sum + [carry]); + } + + pure fn sub(&self, other: &BigUint) -> BigUint { + let new_len = uint::max(self.data.len(), other.data.len()); + + let mut borrow = 0; + let diff = do vec::from_fn(new_len) |i| { + let ai = if i < self.data.len() { self.data[i] } else { 0 }; + let bi = if i < other.data.len() { other.data[i] } else { 0 }; + let (hi, lo) = BigDigit::from_uint( + (BigDigit::base) + + (ai as uint) - (bi as uint) - (borrow as uint) + ); + /* + hi * (base) + lo == 1*(base) + ai - bi - borrow + => ai - bi - borrow < 0 <=> hi == 0 + */ + borrow = if hi == 0 { 1 } else { 0 }; + lo + }; + + assert borrow == 0; // <=> assert (self >= other); + return BigUint::new(diff); + } + + pure fn mul(&self, other: &BigUint) -> BigUint { + if self.is_zero() || other.is_zero() { return Zero::zero(); } + + let s_len = self.data.len(), o_len = other.data.len(); + if s_len == 1 { return mul_digit(other, self.data[0]); } + if o_len == 1 { return mul_digit(self, other.data[0]); } + + // Using Karatsuba multiplication + // (a1 * base + a0) * (b1 * base + b0) + // = a1*b1 * base^2 + + // (a1*b1 + a0*b0 - (a1-b0)*(b1-a0)) * base + + // a0*b0 + let half_len = uint::max(s_len, o_len) / 2; + let (sHi, sLo) = cut_at(self, half_len); + let (oHi, oLo) = cut_at(other, half_len); + + let ll = sLo * oLo; + let hh = sHi * oHi; + let mm = { + let (s1, n1) = sub_sign(sHi, sLo); + let (s2, n2) = sub_sign(oHi, oLo); + if s1 * s2 < 0 { + hh + ll + (n1 * n2) + } else if s1 * s2 > 0 { + hh + ll - (n1 * n2) + } else { + hh + ll + } + }; + + return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2); + + pure fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint { + if n == 0 { return Zero::zero(); } + if n == 1 { return copy *a; } + + let mut carry = 0; + let prod = do vec::map(a.data) |ai| { + let (hi, lo) = BigDigit::from_uint( + (*ai as uint) * (n as uint) + (carry as uint) + ); + carry = hi; + lo + }; + if carry == 0 { return BigUint::new(prod) }; + return BigUint::new(prod + [carry]); + } + + pure fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) { + let mid = uint::min(a.data.len(), n); + return (BigUint::from_slice(vec::view(a.data, mid, a.data.len())), + BigUint::from_slice(vec::view(a.data, 0, mid))); + } + + pure fn sub_sign(a: BigUint, b: BigUint) -> (int, BigUint) { + match a.cmp(&b) { + s if s < 0 => (s, b - a), + s if s > 0 => (s, a - b), + _ => (0, Zero::zero()) + } + } + } + + pure fn div(&self, other: &BigUint) -> BigUint { + let (d, _) = self.divmod(other); + return d; + } + pure fn modulo(&self, other: &BigUint) -> BigUint { + let (_, m) = self.divmod(other); + return m; + } + + pure fn neg(&self) -> BigUint { fail } + + pure fn to_int(&self) -> int { + uint::min(self.to_uint(), int::max_value as uint) as int + } + + static pure fn from_int(n: int) -> BigUint { + if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) } + } +} + +pub impl BigUint { + /// Creates and initializes an BigUint. + static pub pure fn new(v: ~[BigDigit]) -> BigUint { + // omit trailing zeros + let new_len = v.rposition(|n| *n != 0).map_default(0, |p| *p + 1); + + if new_len == v.len() { return BigUint { data: v }; } + let mut v = v; + unsafe { v.truncate(new_len); } + return BigUint { data: v }; + } + + /// Creates and initializes an BigUint. + static pub pure fn from_uint(n: uint) -> BigUint { + match BigDigit::from_uint(n) { + (0, 0) => Zero::zero(), + (0, n0) => BigUint::new(~[n0]), + (n1, n0) => BigUint::new(~[n0, n1]) + } + } + + /// Creates and initializes an BigUint. + static pub pure fn from_slice(slice: &[BigDigit]) -> BigUint { + return BigUint::new(vec::from_slice(slice)); + } + + /// Creates and initializes an BigUint. + static pub pure fn from_str_radix(s: &str, radix: uint) + -> Option { + BigUint::parse_bytes(str::to_bytes(s), radix) + } + + /// Creates and initializes an BigUint. + static pub pure fn parse_bytes(buf: &[u8], radix: uint) + -> Option { + let (base, unit_len) = get_radix_base(radix); + let base_num: BigUint = BigUint::from_uint(base); + + let mut end = buf.len(); + let mut n: BigUint = Zero::zero(); + let mut power: BigUint = One::one(); + loop { + let start = uint::max(end, unit_len) - unit_len; + match uint::parse_bytes(vec::view(buf, start, end), radix) { + Some(d) => n += BigUint::from_uint(d) * power, + None => return None + } + if end <= unit_len { + return Some(n); + } + end -= unit_len; + power *= base_num; + } + } + + pure fn abs(&self) -> BigUint { copy *self } + + /// Compare two BigUint value. + pure fn cmp(&self, other: &BigUint) -> int { + let s_len = self.data.len(), o_len = other.data.len(); + if s_len < o_len { return -1; } + if s_len > o_len { return 1; } + + for vec::rev_eachi(self.data) |i, elm| { + match (*elm, other.data[i]) { + (l, r) if l < r => return -1, + (l, r) if l > r => return 1, + _ => loop + }; + } + return 0; + } + + pure fn divmod(&self, other: &BigUint) -> (BigUint, BigUint) { + if other.is_zero() { fail } + if self.is_zero() { return (Zero::zero(), Zero::zero()); } + if *other == One::one() { return (copy *self, Zero::zero()); } + + match self.cmp(other) { + s if s < 0 => return (Zero::zero(), copy *self), + 0 => return (One::one(), Zero::zero()), + _ => {} // Do nothing + } + + let mut shift = 0; + let mut n = other.data.last(); + while n < (1 << BigDigit::bits - 2) { + n <<= 1; + shift += 1; + } + assert shift < BigDigit::bits; + let (d, m) = divmod_inner(self << shift, other << shift); + return (d, m >> shift); + + pure fn divmod_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { + let mut r = a; + let mut d = Zero::zero::(); + let mut n = 1; + while r >= b { + let mut (d0, d_unit, b_unit) = div_estimate(&r, &b, n); + let mut prod = b * d0; + while prod > r { + d0 -= d_unit; + prod -= b_unit; + } + if d0.is_zero() { + n = 2; + loop; + } + n = 1; + d += d0; + r -= prod; + } + return (d, r); + } + + pure fn div_estimate(a: &BigUint, b: &BigUint, n: uint) + -> (BigUint, BigUint, BigUint) { + if a.data.len() < n { + return (Zero::zero(), Zero::zero(), copy *a); + } + + let an = vec::view(a.data, a.data.len() - n, a.data.len()); + let bn = b.data.last(); + let mut d = ~[]; + let mut carry = 0; + for vec::rev_each(an) |elt| { + let ai = BigDigit::to_uint(carry, *elt); + let di = ai / (bn as uint); + assert di < BigDigit::base; + carry = (ai % (bn as uint)) as BigDigit; + d = ~[di as BigDigit] + d; + } + + let shift = (a.data.len() - an.len()) - (b.data.len() - 1); + if shift == 0 { + return (BigUint::new(d), One::one(), copy *b); + } + return (BigUint::from_slice(d).shl_unit(shift), + One::one::().shl_unit(shift), + b.shl_unit(shift)); + } + } + + pure fn quot(&self, other: &BigUint) -> BigUint { + let (q, _) = self.quotrem(other); + return q; + } + pure fn rem(&self, other: &BigUint) -> BigUint { + let (_, r) = self.quotrem(other); + return r; + } + pure fn quotrem(&self, other: &BigUint) -> (BigUint, BigUint) { + self.divmod(other) + } + + pure fn is_zero(&self) -> bool { self.data.is_empty() } + pure fn is_not_zero(&self) -> bool { self.data.is_not_empty() } + pure fn is_positive(&self) -> bool { self.is_not_zero() } + pure fn is_negative(&self) -> bool { false } + pure fn is_nonpositive(&self) -> bool { self.is_zero() } + pure fn is_nonnegative(&self) -> bool { true } + + pure fn to_uint(&self) -> uint { + match self.data.len() { + 0 => 0, + 1 => self.data[0] as uint, + 2 => BigDigit::to_uint(self.data[1], self.data[0]), + _ => uint::max_value + } + } + + pure fn to_str_radix(&self, radix: uint) -> ~str { + assert 1 < radix && radix <= 16; + let (base, max_len) = get_radix_base(radix); + if base == BigDigit::base { + return fill_concat(self.data, radix, max_len) + } + return fill_concat(convert_base(copy *self, base), radix, max_len); + + pure fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] { + let divider = BigUint::from_uint(base); + let mut result = ~[]; + let mut r = n; + while r > divider { + let (d, r0) = r.divmod(÷r); + result += [r0.to_uint() as BigDigit]; + r = d; + } + if r.is_not_zero() { + result += [r.to_uint() as BigDigit]; + } + return result; + } + + pure fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str { + if v.is_empty() { return ~"0" } + str::trim_left_chars(str::concat(vec::reversed(v).map(|n| { + let s = uint::to_str(*n as uint, radix); + str::from_chars(vec::from_elem(l - s.len(), '0')) + s + })), ['0']) + } + } + + priv pure fn shl_unit(self, n_unit: uint) -> BigUint { + if n_unit == 0 || self.is_zero() { return self; } + + return BigUint::new(vec::from_elem(n_unit, 0) + self.data); + } + + priv pure fn shl_bits(self, n_bits: uint) -> BigUint { + if n_bits == 0 || self.is_zero() { return self; } + + let mut carry = 0; + let shifted = do vec::map(self.data) |elem| { + let (hi, lo) = BigDigit::from_uint( + (*elem as uint) << n_bits | (carry as uint) + ); + carry = hi; + lo + }; + if carry == 0 { return BigUint::new(shifted); } + return BigUint::new(shifted + [carry]); + } + + priv pure fn shr_unit(self, n_unit: uint) -> BigUint { + if n_unit == 0 { return self; } + if self.data.len() < n_unit { return Zero::zero(); } + return BigUint::from_slice( + vec::view(self.data, n_unit, self.data.len()) + ); + } + + priv pure fn shr_bits(self, n_bits: uint) -> BigUint { + if n_bits == 0 || self.data.is_empty() { return self; } + + let mut borrow = 0; + let mut shifted = ~[]; + for vec::rev_each(self.data) |elem| { + shifted = ~[(*elem >> n_bits) | borrow] + shifted; + borrow = *elem << (uint::bits - n_bits); + } + return BigUint::new(shifted); + } +} + +priv pure fn get_radix_base(radix: uint) -> (uint, uint) { + assert 1 < radix && radix <= 16; + match radix { + 2 => (4294967296, 32), + 3 => (3486784401, 20), + 4 => (4294967296, 16), + 5 => (1220703125, 13), + 6 => (2176782336, 12), + 7 => (1977326743, 11), + 8 => (1073741824, 10), + 9 => (3486784401, 10), + 10 => (1000000000, 9), + 11 => (2357947691, 9), + 12 => (429981696, 8), + 13 => (815730721, 8), + 14 => (1475789056, 8), + 15 => (2562890625, 8), + 16 => (4294967296, 8), + _ => fail + } +} + +/// A Sign is a BigInt's composing element. +pub enum Sign { Minus, Zero, Plus } + +impl Sign : Eq { + pure fn eq(&self, other: &Sign) -> bool { self.cmp(other) == 0 } + pure fn ne(&self, other: &Sign) -> bool { self.cmp(other) != 0 } +} + +impl Sign : Ord { + pure fn lt(&self, other: &Sign) -> bool { self.cmp(other) < 0 } + pure fn le(&self, other: &Sign) -> bool { self.cmp(other) <= 0 } + pure fn ge(&self, other: &Sign) -> bool { self.cmp(other) >= 0 } + pure fn gt(&self, other: &Sign) -> bool { self.cmp(other) > 0 } +} + +pub impl Sign { + /// Compare two Sign. + pure fn cmp(&self, other: &Sign) -> int { + match (*self, *other) { + (Minus, Minus) | (Zero, Zero) | (Plus, Plus) => 0, + (Minus, Zero) | (Minus, Plus) | (Zero, Plus) => -1, + _ => 1 + } + } + + /// Negate Sign value. + pure fn neg(&self) -> Sign { + match *self { + Minus => Plus, + Zero => Zero, + Plus => Minus + } + } +} + +/// A big signed integer type. +pub struct BigInt { + priv sign: Sign, + priv data: BigUint +} + +impl BigInt : Eq { + pure fn eq(&self, other: &BigInt) -> bool { self.cmp(other) == 0 } + pure fn ne(&self, other: &BigInt) -> bool { self.cmp(other) != 0 } +} + +impl BigInt : Ord { + pure fn lt(&self, other: &BigInt) -> bool { self.cmp(other) < 0 } + pure fn le(&self, other: &BigInt) -> bool { self.cmp(other) <= 0 } + pure fn ge(&self, other: &BigInt) -> bool { self.cmp(other) >= 0 } + pure fn gt(&self, other: &BigInt) -> bool { self.cmp(other) > 0 } +} + +impl BigInt : ToStr { + pure fn to_str() -> ~str { self.to_str_radix(10) } +} + +impl BigInt : from_str::FromStr { + static pure fn from_str(s: &str) -> Option { + BigInt::from_str_radix(s, 10) + } +} + +impl BigInt : Shl { + pure fn shl(&self, rhs: &uint) -> BigInt { + BigInt::from_biguint(self.sign, self.data << *rhs) + } +} + +impl BigInt : Shr { + pure fn shr(&self, rhs: &uint) -> BigInt { + BigInt::from_biguint(self.sign, self.data >> *rhs) + } +} + +impl BigInt : Zero { + static pub pure fn zero() -> BigInt { + BigInt::from_biguint(Zero, Zero::zero()) + } +} + +impl BigInt : One { + static pub pure fn one() -> BigInt { + BigInt::from_biguint(Plus, One::one()) + } +} + +impl BigInt : Num { + pure fn add(&self, other: &BigInt) -> BigInt { + match (self.sign, other.sign) { + (Zero, _) => copy *other, + (_, Zero) => copy *self, + (Plus, Plus) => BigInt::from_biguint(Plus, + self.data + other.data), + (Plus, Minus) => self - (-*other), + (Minus, Plus) => other - (-*self), + (Minus, Minus) => -((-self) + (-*other)) + } + } + pure fn sub(&self, other: &BigInt) -> BigInt { + match (self.sign, other.sign) { + (Zero, _) => -other, + (_, Zero) => copy *self, + (Plus, Plus) => match self.data.cmp(&other.data) { + s if s < 0 => + BigInt::from_biguint(Minus, other.data - self.data), + s if s > 0 => + BigInt::from_biguint(Plus, self.data - other.data), + _ => + Zero::zero() + }, + (Plus, Minus) => self + (-*other), + (Minus, Plus) => -((-self) + *other), + (Minus, Minus) => (-other) - (-*self) + } + } + pure fn mul(&self, other: &BigInt) -> BigInt { + match (self.sign, other.sign) { + (Zero, _) | (_, Zero) => Zero::zero(), + (Plus, Plus) | (Minus, Minus) => { + BigInt::from_biguint(Plus, self.data * other.data) + }, + (Plus, Minus) | (Minus, Plus) => { + BigInt::from_biguint(Minus, self.data * other.data) + } + } + } + pure fn div(&self, other: &BigInt) -> BigInt { + let (d, _) = self.divmod(other); + return d; + } + pure fn modulo(&self, other: &BigInt) -> BigInt { + let (_, m) = self.divmod(other); + return m; + } + pure fn neg(&self) -> BigInt { + BigInt::from_biguint(self.sign.neg(), copy self.data) + } + + pure fn to_int(&self) -> int { + match self.sign { + Plus => uint::min(self.to_uint(), int::max_value as uint) as int, + Zero => 0, + Minus => uint::min((-self).to_uint(), + (int::max_value as uint) + 1) as int + } + } + + static pure fn from_int(n: int) -> BigInt { + if n > 0 { + return BigInt::from_biguint(Plus, BigUint::from_uint(n as uint)); + } + if n < 0 { + return BigInt::from_biguint( + Minus, BigUint::from_uint(uint::max_value - (n as uint) + 1) + ); + } + return Zero::zero(); + } +} + +pub impl BigInt { + /// Creates and initializes an BigInt. + static pub pure fn new(sign: Sign, v: ~[BigDigit]) -> BigInt { + BigInt::from_biguint(sign, BigUint::new(v)) + } + + /// Creates and initializes an BigInt. + static pub pure fn from_biguint(sign: Sign, data: BigUint) -> BigInt { + if sign == Zero || data.is_zero() { + return BigInt { sign: Zero, data: Zero::zero() }; + } + return BigInt { sign: sign, data: data }; + } + + /// Creates and initializes an BigInt. + static pub pure fn from_uint(n: uint) -> BigInt { + if n == 0 { return Zero::zero(); } + return BigInt::from_biguint(Plus, BigUint::from_uint(n)); + } + + /// Creates and initializes an BigInt. + static pub pure fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt { + BigInt::from_biguint(sign, BigUint::from_slice(slice)) + } + + /// Creates and initializes an BigInt. + static pub pure fn from_str_radix(s: &str, radix: uint) + -> Option { + BigInt::parse_bytes(str::to_bytes(s), radix) + } + + /// Creates and initializes an BigInt. + static pub pure fn parse_bytes(buf: &[u8], radix: uint) + -> Option { + if buf.is_empty() { return None; } + let mut sign = Plus; + let mut start = 0; + if buf[0] == ('-' as u8) { + sign = Minus; + start = 1; + } + return BigUint::parse_bytes(vec::view(buf, start, buf.len()), radix) + .map(|bu| BigInt::from_biguint(sign, *bu)); + } + + pure fn abs(&self) -> BigInt { + BigInt::from_biguint(Plus, copy self.data) + } + + pure fn cmp(&self, other: &BigInt) -> int { + let ss = self.sign, os = other.sign; + if ss < os { return -1; } + if ss > os { return 1; } + + assert ss == os; + match ss { + Zero => 0, + Plus => self.data.cmp(&other.data), + Minus => self.data.cmp(&other.data).neg(), + } + } + + pure fn divmod(&self, other: &BigInt) -> (BigInt, BigInt) { + // m.sign == other.sign + let (d_ui, m_ui) = self.data.divmod(&other.data); + let d = BigInt::from_biguint(Plus, d_ui), + m = BigInt::from_biguint(Plus, m_ui); + match (self.sign, other.sign) { + (_, Zero) => fail, + (Plus, Plus) | (Zero, Plus) => (d, m), + (Plus, Minus) | (Zero, Minus) => if m.is_zero() { + (-d, Zero::zero()) + } else { + (-d - One::one(), m + *other) + }, + (Minus, Plus) => if m.is_zero() { + (-d, Zero::zero()) + } else { + (-d - One::one(), other - m) + }, + (Minus, Minus) => (d, -m) + } + } + + pure fn quot(&self, other: &BigInt) -> BigInt { + let (q, _) = self.quotrem(other); + return q; + } + pure fn rem(&self, other: &BigInt) -> BigInt { + let (_, r) = self.quotrem(other); + return r; + } + + pure fn quotrem(&self, other: &BigInt) -> (BigInt, BigInt) { + // r.sign == self.sign + let (q_ui, r_ui) = self.data.quotrem(&other.data); + let q = BigInt::from_biguint(Plus, q_ui); + let r = BigInt::from_biguint(Plus, r_ui); + match (self.sign, other.sign) { + (_, Zero) => fail, + (Plus, Plus) | (Zero, Plus) => ( q, r), + (Plus, Minus) | (Zero, Minus) => (-q, r), + (Minus, Plus) => (-q, -r), + (Minus, Minus) => ( q, -r) + } + } + + pure fn is_zero(&self) -> bool { self.sign == Zero } + pure fn is_not_zero(&self) -> bool { self.sign != Zero } + pure fn is_positive(&self) -> bool { self.sign == Plus } + pure fn is_negative(&self) -> bool { self.sign == Minus } + pure fn is_nonpositive(&self) -> bool { self.sign != Plus } + pure fn is_nonnegative(&self) -> bool { self.sign != Minus } + + pure fn to_uint(&self) -> uint { + match self.sign { + Plus => self.data.to_uint(), + Zero => 0, + Minus => 0 + } + } + + pure fn to_str_radix(&self, radix: uint) -> ~str { + match self.sign { + Plus => self.data.to_str_radix(radix), + Zero => ~"0", + Minus => ~"-" + self.data.to_str_radix(radix) + } + } +} + +#[cfg(test)] +mod biguint_tests { + + use core::*; + use core::num::{Num, Zero, One}; + use super::{BigInt, BigUint, BigDigit}; + + #[test] + fn test_from_slice() { + fn check(slice: &[BigDigit], data: &[BigDigit]) { + assert data == BigUint::from_slice(slice).data; + } + check(~[1], ~[1]); + check(~[0, 0, 0], ~[]); + check(~[1, 2, 0, 0], ~[1, 2]); + check(~[0, 0, 1, 2], ~[0, 0, 1, 2]); + check(~[0, 0, 1, 2, 0, 0], ~[0, 0, 1, 2]); + check(~[-1], ~[-1]); + } + + #[test] + fn test_cmp() { + let data = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1] ] + .map(|v| BigUint::from_slice(*v)); + for data.eachi |i, ni| { + for vec::view(data, i, data.len()).eachi |j0, nj| { + let j = j0 + i; + if i == j { + assert ni.cmp(nj) == 0; + assert nj.cmp(ni) == 0; + assert ni == nj; + assert !(ni != nj); + assert ni <= nj; + assert ni >= nj; + assert !(ni < nj); + assert !(ni > nj); + } else { + assert ni.cmp(nj) < 0; + assert nj.cmp(ni) > 0; + + assert !(ni == nj); + assert ni != nj; + + assert ni <= nj; + assert !(ni >= nj); + assert ni < nj; + assert !(ni > nj); + + assert !(nj <= ni); + assert nj >= ni; + assert !(nj < ni); + assert nj > ni; + } + } + } + } + + #[test] + fn test_shl() { + fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) { + assert BigUint::new(v) << shift == BigUint::new(ans); + } + + check(~[], 3, ~[]); + check(~[1, 1, 1], 3, ~[1 << 3, 1 << 3, 1 << 3]); + check(~[1 << (BigDigit::bits - 2)], 2, ~[0, 1]); + check(~[1 << (BigDigit::bits - 2)], 3, ~[0, 2]); + check(~[1 << (BigDigit::bits - 2)], 3 + BigDigit::bits, ~[0, 0, 2]); + check(~[0x7654_3210, 0xfedc_ba98, 0x7654_3210, 0xfedc_ba98], 4, + ~[0x6543_2100, 0xedcb_a987, 0x6543_210f, 0xedcb_a987, 0xf]); + check(~[0x2222_1111, 0x4444_3333, 0x6666_5555, 0x8888_7777], 16, + ~[0x1111_0000, 0x3333_2222, 0x5555_4444, 0x7777_6666, 0x8888]); + } + + #[test] + fn test_shr() { + fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) { + assert BigUint::new(v) >> shift == BigUint::new(ans); + } + + check(~[], 3, ~[]); + check(~[1, 1, 1], 3, + ~[1 << (BigDigit::bits - 3), 1 << (BigDigit::bits - 3)]); + check(~[1 << 2], 2, ~[1]); + check(~[1, 2], 3, ~[1 << (BigDigit::bits - 2)]); + check(~[1, 1, 2], 3 + BigDigit::bits, ~[1 << (BigDigit::bits - 2)]); + check(~[0x6543_2100, 0xedcb_a987, 0x6543_210f, 0xedcb_a987, 0xf], 4, + ~[0x7654_3210, 0xfedc_ba98, 0x7654_3210, 0xfedc_ba98]); + check(~[0x1111_0000, 0x3333_2222, 0x5555_4444, 0x7777_6666, 0x8888], + 16, + ~[0x2222_1111, 0x4444_3333, 0x6666_5555, 0x8888_7777]); + } + + #[test] + fn test_convert_int() { + fn check(v: ~[BigDigit], i: int) { + let b = BigUint::new(v); + assert b == Num::from_int(i); + assert b.to_int() == i; + } + + check(~[], 0); + check(~[1], 1); + check(~[-1], (uint::max_value >> BigDigit::bits) as int); + check(~[ 0, 1], ((uint::max_value >> BigDigit::bits) + 1) as int); + check(~[-1, -1 >> 1], int::max_value); + + assert BigUint::new(~[0, -1]).to_int() == int::max_value; + assert BigUint::new(~[0, 0, 1]).to_int() == int::max_value; + assert BigUint::new(~[0, 0, -1]).to_int() == int::max_value; + } + + #[test] + fn test_convert_uint() { + fn check(v: ~[BigDigit], u: uint) { + let b = BigUint::new(v); + assert b == BigUint::from_uint(u); + assert b.to_uint() == u; + } + + check(~[], 0); + check(~[ 1], 1); + check(~[-1], uint::max_value >> BigDigit::bits); + check(~[ 0, 1], (uint::max_value >> BigDigit::bits) + 1); + check(~[ 0, -1], uint::max_value << BigDigit::bits); + check(~[-1, -1], uint::max_value); + + assert BigUint::new(~[0, 0, 1]).to_uint() == uint::max_value; + assert BigUint::new(~[0, 0, -1]).to_uint() == uint::max_value; + } + + const sum_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[ + (&[], &[], &[]), + (&[], &[ 1], &[ 1]), + (&[ 1], &[ 1], &[ 2]), + (&[ 1], &[ 1, 1], &[ 2, 1]), + (&[ 1], &[-1], &[ 0, 1]), + (&[ 1], &[-1, -1], &[ 0, 0, 1]), + (&[-1, -1], &[-1, -1], &[-2, -1, 1]), + (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]), + (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2]) + ]; + + #[test] + fn test_add() { + for sum_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigUint::from_slice(aVec); + let b = BigUint::from_slice(bVec); + let c = BigUint::from_slice(cVec); + + assert a + b == c; + assert b + a == c; + } + } + + #[test] + fn test_sub() { + for sum_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigUint::from_slice(aVec); + let b = BigUint::from_slice(bVec); + let c = BigUint::from_slice(cVec); + + assert c - a == b; + assert c - b == a; + } + } + + const mul_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[ + (&[], &[], &[]), + (&[], &[ 1], &[]), + (&[ 2], &[], &[]), + (&[ 1], &[ 1], &[1]), + (&[ 2], &[ 3], &[ 6]), + (&[ 1], &[ 1, 1, 1], &[1, 1, 1]), + (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]), + (&[ 1, 1, 1], &[-1], &[-1, -1, -1]), + (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]), + (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]), + (&[-1], &[-1], &[ 1, -2]), + (&[-1, -1], &[-1], &[ 1, -1, -2]), + (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]), + (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]), + (&[-1/2 + 1], &[ 2], &[ 0, 1]), + (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]), + (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]), + (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]), + (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]), + (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]), + (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]) + ]; + + const divmod_quadruples: &[(&[BigDigit], &[BigDigit], + &[BigDigit], &[BigDigit])] + = &[ + (&[ 1], &[ 2], &[], &[1]), + (&[ 1, 1], &[ 2], &[-1/2+1], &[1]), + (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]), + (&[ 0, 1], &[-1], &[1], &[1]), + (&[-1, -1], &[-2], &[2, 1], &[3]) + ]; + + #[test] + fn test_mul() { + for mul_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigUint::from_slice(aVec); + let b = BigUint::from_slice(bVec); + let c = BigUint::from_slice(cVec); + + assert a * b == c; + assert b * a == c; + } + + for divmod_quadruples.each |elm| { + let (aVec, bVec, cVec, dVec) = *elm; + let a = BigUint::from_slice(aVec); + let b = BigUint::from_slice(bVec); + let c = BigUint::from_slice(cVec); + let d = BigUint::from_slice(dVec); + + assert a == b * c + d; + assert a == c * b + d; + } + } + + #[test] + fn test_divmod() { + for mul_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigUint::from_slice(aVec); + let b = BigUint::from_slice(bVec); + let c = BigUint::from_slice(cVec); + + if a.is_not_zero() { + assert c.divmod(&a) == (b, Zero::zero()); + } + if b.is_not_zero() { + assert c.divmod(&b) == (a, Zero::zero()); + } + } + + for divmod_quadruples.each |elm| { + let (aVec, bVec, cVec, dVec) = *elm; + let a = BigUint::from_slice(aVec); + let b = BigUint::from_slice(bVec); + let c = BigUint::from_slice(cVec); + let d = BigUint::from_slice(dVec); + + if b.is_not_zero() { assert a.divmod(&b) == (c, d); } + } + } + + fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] { + ~[( Zero::zero(), ~[ + (2, ~"0"), (3, ~"0") + ]), ( BigUint::from_slice([ 0xff ]), ~[ + (2, ~"11111111"), + (3, ~"100110"), + (4, ~"3333"), + (5, ~"2010"), + (6, ~"1103"), + (7, ~"513"), + (8, ~"377"), + (9, ~"313"), + (10, ~"255"), + (11, ~"212"), + (12, ~"193"), + (13, ~"168"), + (14, ~"143"), + (15, ~"120"), + (16, ~"ff") + ]), ( BigUint::from_slice([ 0xfff ]), ~[ + (2, ~"111111111111"), + (4, ~"333333"), + (16, ~"fff") + ]), ( BigUint::from_slice([ 1, 2 ]), ~[ + (2, ~"10" + str::from_chars(vec::from_elem(31, '0')) + "1"), + (4, ~"2" + str::from_chars(vec::from_elem(15, '0')) + "1"), + (10, ~"8589934593"), + (16, ~"2" + str::from_chars(vec::from_elem(7, '0')) + "1") + ]), (BigUint::from_slice([ 1, 2, 3 ]), ~[ + (2, ~"11" + str::from_chars(vec::from_elem(30, '0')) + "10" + + str::from_chars(vec::from_elem(31, '0')) + "1"), + (4, ~"3" + str::from_chars(vec::from_elem(15, '0')) + "2" + + str::from_chars(vec::from_elem(15, '0')) + "1"), + (10, ~"55340232229718589441"), + (16, ~"3" + str::from_chars(vec::from_elem(7, '0')) + "2" + + str::from_chars(vec::from_elem(7, '0')) + "1") + ])] + } + + #[test] + fn test_to_str_radix() { + for to_str_pairs().each |num_pair| { + let &(n, rs) = num_pair; + for rs.each |str_pair| { + let &(radix, str) = str_pair; + assert n.to_str_radix(radix) == str; + } + } + } + + #[test] + fn test_from_str_radix() { + for to_str_pairs().each |num_pair| { + let &(n, rs) = num_pair; + for rs.each |str_pair| { + let &(radix, str) = str_pair; + assert Some(n) == BigUint::from_str_radix(str, radix); + } + } + + assert BigUint::from_str_radix(~"Z", 10) == None; + assert BigUint::from_str_radix(~"_", 2) == None; + assert BigUint::from_str_radix(~"-1", 10) == None; + } + + #[test] + fn test_factor() { + fn factor(n: uint) -> BigUint { + let mut f= One::one::(); + for uint::range(2, n + 1) |i| { + f *= BigUint::from_uint(i); + } + return f; + } + + fn check(n: uint, s: &str) { + let n = factor(n); + let ans = match BigUint::from_str_radix(s, 10) { + Some(x) => x, None => fail + }; + assert n == ans; + } + + check(3, "6"); + check(10, "3628800"); + check(20, "2432902008176640000"); + check(30, "265252859812191058636308480000000"); + } +} + +#[cfg(test)] +mod bigint_tests { + + use core::*; + use core::num::{Num, Zero, One}; + use super::{BigInt, BigUint, BigDigit}; + + #[test] + fn test_from_biguint() { + fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) { + let inp = BigInt::from_biguint(inp_s, BigUint::from_uint(inp_n)); + let ans = BigInt { sign: ans_s, data: BigUint::from_uint(ans_n)}; + assert inp == ans; + } + check(Plus, 1, Plus, 1); + check(Plus, 0, Zero, 0); + check(Minus, 1, Minus, 1); + check(Zero, 1, Zero, 0); + } + + #[test] + fn test_cmp() { + let vs = [ &[2], &[1, 1], &[2, 1], &[1, 1, 1] ]; + let mut nums = vec::reversed(vs) + .map(|s| BigInt::from_slice(Minus, *s)); + nums.push(Zero::zero()); + nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s))); + + for nums.eachi |i, ni| { + for vec::view(nums, i, nums.len()).eachi |j0, nj| { + let j = i + j0; + if i == j { + assert ni.cmp(nj) == 0; + assert nj.cmp(ni) == 0; + assert ni == nj; + assert !(ni != nj); + assert ni <= nj; + assert ni >= nj; + assert !(ni < nj); + assert !(ni > nj); + } else { + assert ni.cmp(nj) < 0; + assert nj.cmp(ni) > 0; + + assert !(ni == nj); + assert ni != nj; + + assert ni <= nj; + assert !(ni >= nj); + assert ni < nj; + assert !(ni > nj); + + assert !(nj <= ni); + assert nj >= ni; + assert !(nj < ni); + assert nj > ni; + } + } + } + } + + #[test] + fn test_convert_int() { + fn check(b: BigInt, i: int) { + assert b == Num::from_int(i); + assert b.to_int() == i; + } + + check(Zero::zero(), 0); + check(One::one(), 1); + check(BigInt::from_biguint( + Plus, BigUint::from_uint(int::max_value as uint) + ), int::max_value); + + assert BigInt::from_biguint( + Plus, BigUint::from_uint(int::max_value as uint + 1) + ).to_int() == int::max_value; + assert BigInt::from_biguint( + Plus, BigUint::new(~[1, 2, 3]) + ).to_int() == int::max_value; + + check(BigInt::from_biguint( + Minus, BigUint::from_uint(-int::min_value as uint) + ), int::min_value); + assert BigInt::from_biguint( + Minus, BigUint::from_uint(-int::min_value as uint + 1) + ).to_int() == int::min_value; + assert BigInt::from_biguint( + Minus, BigUint::new(~[1, 2, 3]) + ).to_int() == int::min_value; + } + + #[test] + fn test_convert_uint() { + fn check(b: BigInt, u: uint) { + assert b == BigInt::from_uint(u); + assert b.to_uint() == u; + } + + check(Zero::zero(), 0); + check(One::one(), 1); + + check( + BigInt::from_biguint(Plus, BigUint::from_uint(uint::max_value)), + uint::max_value); + assert BigInt::from_biguint( + Plus, BigUint::new(~[1, 2, 3]) + ).to_uint() == uint::max_value; + + assert BigInt::from_biguint( + Minus, BigUint::from_uint(uint::max_value) + ).to_uint() == 0; + assert BigInt::from_biguint( + Minus, BigUint::new(~[1, 2, 3]) + ).to_uint() == 0; + } + + const sum_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[ + (&[], &[], &[]), + (&[], &[ 1], &[ 1]), + (&[ 1], &[ 1], &[ 2]), + (&[ 1], &[ 1, 1], &[ 2, 1]), + (&[ 1], &[-1], &[ 0, 1]), + (&[ 1], &[-1, -1], &[ 0, 0, 1]), + (&[-1, -1], &[-1, -1], &[-2, -1, 1]), + (&[ 1, 1, 1], &[-1, -1], &[ 0, 1, 2]), + (&[ 2, 2, 1], &[-1, -2], &[ 1, 1, 2]) + ]; + + #[test] + fn test_add() { + for sum_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + + assert a + b == c; + assert b + a == c; + assert c + (-a) == b; + assert c + (-b) == a; + assert a + (-c) == (-b); + assert b + (-c) == (-a); + assert (-a) + (-b) == (-c); + assert a + (-a) == Zero::zero(); + } + } + + #[test] + fn test_sub() { + for sum_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + + assert c - a == b; + assert c - b == a; + assert (-b) - a == (-c); + assert (-a) - b == (-c); + assert b - (-a) == c; + assert a - (-b) == c; + assert (-c) - (-a) == (-b); + assert a - a == Zero::zero(); + } + } + + const mul_triples: &[(&[BigDigit], &[BigDigit], &[BigDigit])] = &[ + (&[], &[], &[]), + (&[], &[ 1], &[]), + (&[ 2], &[], &[]), + (&[ 1], &[ 1], &[1]), + (&[ 2], &[ 3], &[ 6]), + (&[ 1], &[ 1, 1, 1], &[1, 1, 1]), + (&[ 1, 2, 3], &[ 3], &[ 3, 6, 9]), + (&[ 1, 1, 1], &[-1], &[-1, -1, -1]), + (&[ 1, 2, 3], &[-1], &[-1, -2, -2, 2]), + (&[ 1, 2, 3, 4], &[-1], &[-1, -2, -2, -2, 3]), + (&[-1], &[-1], &[ 1, -2]), + (&[-1, -1], &[-1], &[ 1, -1, -2]), + (&[-1, -1, -1], &[-1], &[ 1, -1, -1, -2]), + (&[-1, -1, -1, -1], &[-1], &[ 1, -1, -1, -1, -2]), + (&[-1/2 + 1], &[ 2], &[ 0, 1]), + (&[0, -1/2 + 1], &[ 2], &[ 0, 0, 1]), + (&[ 1, 2], &[ 1, 2, 3], &[1, 4, 7, 6]), + (&[-1, -1], &[-1, -1, -1], &[1, 0, -1, -2, -1]), + (&[-1, -1, -1], &[-1, -1, -1, -1], &[1, 0, 0, -1, -2, -1, -1]), + (&[ 0, 0, 1], &[ 1, 2, 3], &[0, 0, 1, 2, 3]), + (&[ 0, 0, 1], &[ 0, 0, 0, 1], &[0, 0, 0, 0, 0, 1]) + ]; + + const divmod_quadruples: &[(&[BigDigit], &[BigDigit], + &[BigDigit], &[BigDigit])] + = &[ + (&[ 1], &[ 2], &[], &[1]), + (&[ 1, 1], &[ 2], &[-1/2+1], &[1]), + (&[ 1, 1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]), + (&[ 0, 1], &[-1], &[1], &[1]), + (&[-1, -1], &[-2], &[2, 1], &[3]) + ]; + + #[test] + fn test_mul() { + for mul_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + + assert a * b == c; + assert b * a == c; + + assert (-a) * b == -c; + assert (-b) * a == -c; + } + + for divmod_quadruples.each |elm| { + let (aVec, bVec, cVec, dVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + let d = BigInt::from_slice(Plus, dVec); + + assert a == b * c + d; + assert a == c * b + d; + } + } + + #[test] + fn test_divmod() { + fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) { + let (d, m) = a.divmod(b); + if m.is_not_zero() { + assert m.sign == b.sign; + } + assert m.abs() <= b.abs(); + assert *a == b * d + m; + assert d == *ans_d; + assert m == *ans_m; + } + + fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) { + if m.is_zero() { + check_sub(a, b, d, m); + check_sub(a, &b.neg(), &d.neg(), m); + check_sub(&a.neg(), b, &d.neg(), m); + check_sub(&a.neg(), &b.neg(), d, m); + } else { + check_sub(a, b, d, m); + check_sub(a, &b.neg(), &(d.neg() - One::one()), &(m - *b)); + check_sub(&a.neg(), b, &(d.neg() - One::one()), &(b - *m)); + check_sub(&a.neg(), &b.neg(), d, &m.neg()); + } + } + + for mul_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + + if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); } + if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); } + } + + for divmod_quadruples.each |elm| { + let (aVec, bVec, cVec, dVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + let d = BigInt::from_slice(Plus, dVec); + + if b.is_not_zero() { + check(&a, &b, &c, &d); + } + } + } + + + #[test] + fn test_quotrem() { + fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) { + let (q, r) = a.quotrem(b); + if r.is_not_zero() { + assert r.sign == a.sign; + } + assert r.abs() <= b.abs(); + assert *a == b * q + r; + assert q == *ans_q; + assert r == *ans_r; + } + + fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) { + check_sub(a, b, q, r); + check_sub(a, &b.neg(), &q.neg(), r); + check_sub(&a.neg(), b, &q.neg(), &r.neg()); + check_sub(&a.neg(), &b.neg(), q, &r.neg()); + } + for mul_triples.each |elm| { + let (aVec, bVec, cVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + + if a.is_not_zero() { check(&c, &a, &b, &Zero::zero()); } + if b.is_not_zero() { check(&c, &b, &a, &Zero::zero()); } + } + + for divmod_quadruples.each |elm| { + let (aVec, bVec, cVec, dVec) = *elm; + let a = BigInt::from_slice(Plus, aVec); + let b = BigInt::from_slice(Plus, bVec); + let c = BigInt::from_slice(Plus, cVec); + let d = BigInt::from_slice(Plus, dVec); + + if b.is_not_zero() { + check(&a, &b, &c, &d); + } + } + } + + #[test] + fn test_to_str_radix() { + fn check(n: int, ans: &str) { + assert ans == Num::from_int::(n).to_str_radix(10); + } + check(10, "10"); + check(1, "1"); + check(0, "0"); + check(-1, "-1"); + check(-10, "-10"); + } + + + #[test] + fn test_from_str_radix() { + fn check(s: &str, ans: Option) { + let ans = ans.map(|&n| Num::from_int(n)); + assert BigInt::from_str_radix(s, 10) == ans; + } + check("10", Some(10)); + check("1", Some(1)); + check("0", Some(0)); + check("-1", Some(-1)); + check("-10", Some(-10)); + check("Z", None); + check("_", None); + } + + #[test] + fn test_neg() { + assert -BigInt::new(Plus, ~[1, 1, 1]) == + BigInt::new(Minus, ~[1, 1, 1]); + assert -BigInt::new(Minus, ~[1, 1, 1]) == + BigInt::new(Plus, ~[1, 1, 1]); + assert -Zero::zero::() == Zero::zero::(); + } +} + diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs index 5b9dc6cf3a895..38ebe67898d3a 100644 --- a/src/libstd/bitv.rs +++ b/src/libstd/bitv.rs @@ -10,7 +10,10 @@ #[forbid(deprecated_mode)]; -use vec::{to_mut, from_elem}; +use core::ops; +use core::uint; +use core::vec::{to_mut, from_elem}; +use core::vec; struct SmallBitv { /// only the lowest nbits of this value are used. the rest is undefined. @@ -574,6 +577,12 @@ impl Bitv: ops::Index { #[cfg(test)] mod tests { #[legacy_exports]; + + use bitv; + + use core::uint; + use core::vec; + #[test] fn test_to_str() { let zerolen = Bitv(0u, false); diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs index cc8cadb709d94..aa9e864adfdca 100644 --- a/src/libstd/c_vec.rs +++ b/src/libstd/c_vec.rs @@ -37,6 +37,12 @@ */ #[forbid(deprecated_mode)]; +use core::libc; +use core::oldcomm; +use core::option; +use core::ptr; +use core::task; + /** * The type representing a foreign chunk of memory * @@ -146,7 +152,8 @@ pub unsafe fn ptr(t: CVec) -> *mut T { #[cfg(test)] mod tests { - use libc::*; + use core::libc::*; + use core::libc; fn malloc(n: size_t) -> CVec { let mem = libc::malloc(n); diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index b972ef953e4f8..29c75e629e90e 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -9,6 +9,9 @@ // except according to those terms. #[forbid(deprecated_mode)]; + +use core::option; + /// A dynamic, mutable location. /// /// Similar to a mutable option type, but friendlier. diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs index 28ee8c81e73d0..7c126c7338b71 100644 --- a/src/libstd/cmp.rs +++ b/src/libstd/cmp.rs @@ -11,6 +11,10 @@ #[forbid(deprecated_mode)]; /// Additional general-purpose comparison functionality. +use core::f32; +use core::f64; +use core::float; + const fuzzy_epsilon: float = 1.0e-6; pub trait FuzzyEq { diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs index 1055f3ea7df72..850e53c2d48e7 100644 --- a/src/libstd/comm.rs +++ b/src/libstd/comm.rs @@ -17,8 +17,9 @@ Higher level communication abstractions. // NB: transitionary, de-mode-ing. #[forbid(deprecated_mode)]; -use pipes::{GenericChan, GenericSmartChan, GenericPort, - Chan, Port, Selectable, Peekable}; +use core::pipes::{GenericChan, GenericSmartChan, GenericPort}; +use core::pipes::{Chan, Port, Selectable, Peekable}; +use core::pipes; /// An extension of `pipes::stream` that allows both sending and receiving. pub struct DuplexStream { diff --git a/src/libstd/dbg.rs b/src/libstd/dbg.rs index 75e25f75c6c21..bcbe750ff7efa 100644 --- a/src/libstd/dbg.rs +++ b/src/libstd/dbg.rs @@ -11,8 +11,9 @@ #[forbid(deprecated_mode)]; //! Unsafe debugging functions for inspecting values. -use cast::reinterpret_cast; - +use core::cast::reinterpret_cast; +use core::ptr; +use core::sys; #[abi = "cdecl"] extern mod rustrt { diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs index 687eff887c8b2..e7042ffa89f05 100644 --- a/src/libstd/deque.rs +++ b/src/libstd/deque.rs @@ -12,9 +12,11 @@ #[forbid(deprecated_mode)]; #[forbid(non_camel_case_types)]; -use option::{Some, None}; -use dvec::DVec; -use core::cmp::{Eq}; +use core::cmp::Eq; +use core::dvec::DVec; +use core::dvec; +use core::uint; +use core::vec; pub trait Deque { fn size() -> uint; @@ -129,6 +131,8 @@ pub fn create() -> Deque { #[cfg(test)] mod tests { + use deque; + #[test] fn test_simple() { let d: deque::Deque = deque::create::(); diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs index 59e0a1e84fe8f..0f49507cea4dc 100644 --- a/src/libstd/ebml.rs +++ b/src/libstd/ebml.rs @@ -9,8 +9,14 @@ // except according to those terms. #[forbid(deprecated_mode)]; + use serialize; +use core::io; +use core::ops; +use core::str; +use core::vec; + // 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 @@ -54,6 +60,13 @@ enum EbmlEncoderTag { // -------------------------------------- pub mod reader { + use serialize; + + use core::int; + use core::io; + use core::ops; + use core::str; + use core::vec; // ebml reading @@ -271,7 +284,7 @@ pub mod reader { 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) { + if v > (::core::uint::max_value as u64) { fail fmt!("uint %? too large for this architecture", v); } v as uint @@ -385,6 +398,9 @@ pub mod reader { } pub mod writer { + use core::io; + use core::str; + use core::vec; // ebml writing pub struct Encoder { @@ -546,7 +562,7 @@ pub mod writer { } } - impl Encoder: serialize::Encoder { + impl Encoder: ::serialize::Encoder { fn emit_nil(&self) {} fn emit_uint(&self, v: uint) { @@ -647,6 +663,12 @@ pub mod writer { #[cfg(test)] mod tests { + use ebml::reader; + use ebml::writer; + use serialize; + + use core::io; + #[test] fn test_option_int() { fn test_v(v: Option) { diff --git a/src/libstd/flatpipes.rs b/src/libstd/flatpipes.rs index 1617641afe366..8f239b2a130ff 100644 --- a/src/libstd/flatpipes.rs +++ b/src/libstd/flatpipes.rs @@ -38,10 +38,13 @@ block the scheduler thread, so will their pipes. */ // The basic send/recv interface FlatChan and PortChan will implement +use core::io; use core::pipes::GenericChan; use core::pipes::GenericPort; - +use core::pipes; use core::sys::size_of; +use core::uint; +use core::vec; /** A FlatPort, consisting of a `BytePort` that recieves byte vectors, @@ -69,18 +72,20 @@ pub struct FlatChan, C: ByteChan> { Constructors for flat pipes that using serialization-based flattening. */ pub mod serial { - pub use DefaultEncoder = ebml::writer::Encoder; pub use DefaultDecoder = ebml::reader::Decoder; - use core::io::{Reader, Writer}; - use core::pipes::{Port, Chan}; use serialize::{Decodable, Encodable}; use flatpipes::flatteners::{DeserializingUnflattener, SerializingFlattener}; use flatpipes::flatteners::{deserialize_buffer, serialize_value}; use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan}; use flatpipes::bytepipes::{PipeBytePort, PipeByteChan}; + use flatpipes::{FlatPort, FlatChan}; + + use core::io::{Reader, Writer}; + use core::pipes::{Port, Chan}; + use core::pipes; pub type ReaderPort = FlatPort< T, DeserializingUnflattener, @@ -141,7 +146,6 @@ pub mod serial { let (port, chan) = pipes::stream(); return (pipe_port(move port), pipe_chan(move chan)); } - } // FIXME #4074 this doesn't correctly enforce POD bounds @@ -159,9 +163,11 @@ pub mod pod { use core::io::{Reader, Writer}; use core::pipes::{Port, Chan}; + use core::pipes; use flatpipes::flatteners::{PodUnflattener, PodFlattener}; use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan}; use flatpipes::bytepipes::{PipeBytePort, PipeByteChan}; + use flatpipes::{FlatPort, FlatChan}; pub type ReaderPort = FlatPort, ReaderBytePort>; @@ -242,7 +248,7 @@ pub trait ByteChan { const CONTINUE: [u8 * 4] = [0xAA, 0xBB, 0xCC, 0xDD]; -impl, P: BytePort> FlatPort: GenericPort { +pub impl,P:BytePort> FlatPort: GenericPort { fn recv() -> T { match self.try_recv() { Some(move val) => move val, @@ -287,7 +293,7 @@ impl, P: BytePort> FlatPort: GenericPort { } } -impl, C: ByteChan> FlatChan: GenericChan { +impl,C:ByteChan> FlatChan: GenericChan { fn send(val: T) { self.byte_chan.send(CONTINUE.to_vec()); let bytes = self.flattener.flatten(move val); @@ -299,7 +305,7 @@ impl, C: ByteChan> FlatChan: GenericChan { } } -impl, P: BytePort> FlatPort { +pub impl,P:BytePort> FlatPort { static fn new(u: U, p: P) -> FlatPort { FlatPort { unflattener: move u, @@ -308,7 +314,7 @@ impl, P: BytePort> FlatPort { } } -impl, C: ByteChan> FlatChan { +pub impl,C:ByteChan> FlatChan { static fn new(f: F, c: C) -> FlatChan { FlatChan { flattener: move f, @@ -319,14 +325,16 @@ impl, C: ByteChan> FlatChan { pub mod flatteners { + use ebml; + use flatpipes::util::BufReader; + use json; + use serialize::{Encoder, Decoder, Encodable, Decodable}; - use core::sys::size_of; - - use serialize::{Encoder, Decoder, - Encodable, Decodable}; - + use core::cast; use core::io::{Writer, Reader, BytesWriter, ReaderUtil}; - use flatpipes::util::BufReader; + use core::ptr; + use core::sys::size_of; + use core::vec; // XXX: Is copy/send equivalent to pod? pub struct PodUnflattener { @@ -488,9 +496,9 @@ pub mod flatteners { } pub mod bytepipes { - use core::io::{Writer, Reader, ReaderUtil}; use core::pipes::{Port, Chan}; + use core::pipes; pub struct ReaderBytePort { reader: R @@ -556,12 +564,12 @@ pub mod bytepipes { pub impl PipeBytePort: BytePort { fn try_recv(&self, count: uint) -> Option<~[u8]> { if self.buf.len() >= count { - let mut bytes = core::util::replace(&mut self.buf, ~[]); + let mut bytes = ::core::util::replace(&mut self.buf, ~[]); self.buf = bytes.slice(count, bytes.len()); bytes.truncate(count); return Some(bytes); } else if self.buf.len() > 0 { - let mut bytes = core::util::replace(&mut self.buf, ~[]); + let mut bytes = ::core::util::replace(&mut self.buf, ~[]); assert count > bytes.len(); match self.try_recv(count - bytes.len()) { Some(move rest) => { @@ -580,7 +588,7 @@ pub mod bytepipes { None => return None } } else { - core::util::unreachable() + ::core::util::unreachable() } } } @@ -612,8 +620,8 @@ pub mod bytepipes { // XXX: This belongs elsewhere mod util { - - use io::{Reader, BytesReader}; + use core::io::{Reader, BytesReader}; + use core::io; pub struct BufReader { buf: ~[u8], @@ -632,7 +640,7 @@ mod util { // Recreating the BytesReader state every call since // I can't get the borrowing to work correctly let bytes_reader = BytesReader { - bytes: core::util::id::<&[u8]>(self.buf), + bytes: ::core::util::id::<&[u8]>(self.buf), pos: self.pos }; @@ -677,11 +685,19 @@ mod test { use flatpipes::flatteners::*; use flatpipes::bytepipes::*; + use flatpipes::pod; + use flatpipes::serial; + use flatpipes::util::BufReader; + use net::ip; + use net::tcp::TcpSocketBuf; use core::dvec::DVec; - use io::BytesReader; - use util::BufReader; - use net::tcp::TcpSocketBuf; + use core::int; + use core::io::BytesReader; + use core::io; + use core::result; + use core::sys; + use core::task; #[test] fn test_serializing_memory_stream() { @@ -803,6 +819,7 @@ mod test { use net::ip; use cell::Cell; use net::tcp::TcpSocket; + use uv; // Indicate to the client task that the server is listening let (begin_connect_port, begin_connect_chan) = pipes::stream(); @@ -901,6 +918,14 @@ mod test { // Tests that the different backends behave the same when the // binary streaming protocol is broken mod broken_protocol { + use flatpipes::pod; + use flatpipes::util::BufReader; + + use core::io; + use core::pipes; + use core::sys; + use core::task; + type PortLoader = ~fn(~[u8]) -> FlatPort, P>; diff --git a/src/libstd/fun_treemap.rs b/src/libstd/fun_treemap.rs index 1eccb5a8d92da..6a24e1e581774 100644 --- a/src/libstd/fun_treemap.rs +++ b/src/libstd/fun_treemap.rs @@ -22,8 +22,7 @@ */ use core::cmp::{Eq, Ord}; -use option::{Some, None}; -use option = option; +use core::option::{Some, None}; pub type Treemap = @TreeNode; diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 2a72c2f696a54..7cbd42f217d2b 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -21,9 +21,12 @@ * ~~~ */ -use either::Either; -use pipes::{recv, oneshot, ChanOne, PortOne, send_one, recv_one}; -use cast::copy_lifetime; +use core::cast::copy_lifetime; +use core::cast; +use core::either::Either; +use core::option; +use core::pipes::{recv, oneshot, ChanOne, PortOne, send_one, recv_one}; +use core::task; #[doc = "The future type"] pub struct Future { @@ -142,6 +145,9 @@ pub fn spawn(blk: fn~() -> A) -> Future { #[allow(non_implicitly_copyable_typarams)] pub mod test { + use core::pipes::oneshot; + use core::task; + #[test] pub fn test_from_value() { let f = from_value(~"snail"); diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index 38540524daca3..3d9ee0d3d1296 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -76,8 +76,11 @@ use core::cmp::Eq; use core::result::{Err, Ok}; +use core::result; use core::option; use core::option::{Some, None}; +use core::str; +use core::vec; #[deriving_eq] enum Name { @@ -450,6 +453,10 @@ enum FailType { * groups of short and long option names, together. */ pub mod groups { + use getopts::Result; + + use core::str; + use core::vec; /** one group of options, e.g., both -h and --help, along with * their shared description and properties @@ -627,8 +634,11 @@ pub mod groups { mod tests { #[legacy_exports]; use opt = getopts; - use result::{Err, Ok}; use getopts::groups::OptGroup; + use getopts::groups; + + use core::result::{Err, Ok}; + use core::result; fn check_fail_type(f: Fail_, ft: FailType) { match f { diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 770d621d51fc7..44cd4fe44491a 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -15,11 +15,19 @@ //! json serialization -use core::cmp::{Eq, Ord}; -use io::{WriterUtil, ReaderUtil}; -use send_map::linear; +use serialize; use sort::Sort; +use core::char; +use core::cmp::{Eq, Ord}; +use core::float; +use core::io::{WriterUtil, ReaderUtil}; +use core::io; +use core::send_map::linear; +use core::str; +use core::to_str; +use core::vec; + /// Represents a json value pub enum Json { Number(float), @@ -1185,6 +1193,9 @@ impl Error: to_str::ToStr { #[cfg(test)] mod tests { + use core::result; + use core::send_map::linear; + fn mk_object(items: &[(~str, Json)]) -> Json { let mut d = ~linear::LinearMap(); diff --git a/src/libstd/list.rs b/src/libstd/list.rs index e41aab8ec1ffb..4a7574afd9f07 100644 --- a/src/libstd/list.rs +++ b/src/libstd/list.rs @@ -13,8 +13,8 @@ use core::cmp::Eq; use core::option; -use option::*; -use option::{Some, None}; +use core::option::*; +use core::vec; #[deriving_eq] pub enum List { @@ -162,6 +162,10 @@ pub pure fn each(l: @List, f: fn(&T) -> bool) { mod tests { #[legacy_exports]; + use list; + + use core::option; + #[test] fn test_is_empty() { let empty : @list::List = from_vec(~[]); diff --git a/src/libstd/map.rs b/src/libstd/map.rs index 39124dfbfbae2..e4f38496f1dd8 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -11,14 +11,17 @@ //! A map type #[forbid(deprecated_mode)]; -use io::WriterUtil; -use to_str::ToStr; -use mutable::Mut; -use send_map::linear::LinearMap; - use core::cmp::Eq; -use hash::Hash; -use to_bytes::IterBytes; +use core::hash::Hash; +use core::io::WriterUtil; +use core::io; +use core::ops; +use core::to_str::ToStr; +use core::mutable::Mut; +use core::send_map::linear::LinearMap; +use core::to_bytes::IterBytes; +use core::uint; +use core::vec; /// A convenience type to treat a hashmap as a set pub type Set = HashMap; @@ -51,7 +54,7 @@ pub trait Map { * Add a value to the map. * * If the map contains a value for the key, use the function to - * set a new value. (Like `insert_or_update_with_key`, but with a + * set a new value. (Like `update_with_key`, but with a * function of only values.) */ fn update(key: K, newval: V, ff: fn(V, V) -> V) -> bool; @@ -103,7 +106,7 @@ pub trait Map { pure fn each_value_ref(fn(value: &V) -> bool); } -mod util { +pub mod util { pub type Rational = {num: int, den: int}; // : int::positive(*.den); pub pure fn rational_leq(x: Rational, y: Rational) -> bool { @@ -117,6 +120,13 @@ mod util { // FIXME (#2344): package this up and export it as a datatype usable for // external code that doesn't want to pay the cost of a box. pub mod chained { + use map::util; + + use core::io; + use core::ops; + use core::option; + use core::uint; + use core::vec; const initial_capacity: uint = 32u; // 2^5 @@ -603,6 +613,10 @@ impl @Mut>: #[cfg(test)] mod tests { + use map; + + use core::option; + use core::uint; #[test] fn test_simple() { diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs index 8e58a010f469e..d10533008d965 100644 --- a/src/libstd/md4.rs +++ b/src/libstd/md4.rs @@ -10,6 +10,10 @@ #[forbid(deprecated_mode)]; +use core::str; +use core::uint; +use core::vec; + pub pure fn md4(msg: &[u8]) -> {a: u32, b: u32, c: u32, d: u32} { // subtle: if orig_len is merely uint, then the code below // which performs shifts by 32 bits or more has undefined diff --git a/src/libstd/net.rs b/src/libstd/net.rs index 230fb4b616d00..ca1cc1235961a 100644 --- a/src/libstd/net.rs +++ b/src/libstd/net.rs @@ -8,7 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Top-level module for network-related functionality +/*! +Top-level module for network-related functionality. + +Basically, including this module gives you: + +* `net_tcp` +* `net_ip` +* `net_url` + +See each of those three modules for documentation on what they do. +*/ pub use tcp = net_tcp; pub use ip = net_ip; diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs index 1eb970526c36b..96bd6367e569e 100644 --- a/src/libstd/net_ip.rs +++ b/src/libstd/net_ip.rs @@ -11,6 +11,14 @@ //! Types/fns concerning Internet Protocol (IP), versions 4 & 6 #[forbid(deprecated_mode)]; +use core::libc; +use core::oldcomm; +use core::ptr; +use core::result; +use core::str; +use core::uint; +use core::vec; + use iotask = uv::iotask::IoTask; use interact = uv::iotask::interact; @@ -139,6 +147,14 @@ pub fn get_addr(node: &str, iotask: iotask) } pub mod v4 { + use uv::ll; + + use core::ptr; + use core::result; + use core::str; + use core::uint; + use core::vec; + /** * Convert a str to `ip_addr` * @@ -225,6 +241,9 @@ pub mod v4 { } } pub mod v6 { + use core::result; + use core::str; + /** * Convert a str to `ip_addr` * @@ -331,6 +350,13 @@ extern fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, #[cfg(test)] mod test { + use net_ip::v4; + use net_ip::v6; + use uv; + + use core::result; + use core::vec; + #[test] fn test_ip_ipv4_parse_and_format_ip() { let localhost_str = ~"127.0.0.1"; diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs index c888b457356b6..ca365e2a7d3e3 100644 --- a/src/libstd/net_tcp.rs +++ b/src/libstd/net_tcp.rs @@ -12,13 +12,23 @@ // XXX Need FFI fixes #[allow(deprecated_mode)]; +use future; +use future_spawn = future::spawn; use ip = net_ip; +use uv; use uv::iotask; use uv::iotask::IoTask; -use future_spawn = future::spawn; -use result::{Result}; -use libc::size_t; -use io::{Reader, ReaderUtil, Writer}; + +use core::io::{Reader, ReaderUtil, Writer}; +use core::io; +use core::libc::size_t; +use core::libc; +use core::oldcomm; +use core::ptr; +use core::result::{Result}; +use core::result; +use core::uint; +use core::vec; #[nolink] extern mod rustrt { @@ -901,6 +911,8 @@ fn tear_down_socket_data(socket_data: @TcpSocketData) unsafe { // shared implementation for tcp::read fn read_common_impl(socket_data: *TcpSocketData, timeout_msecs: uint) -> result::Result<~[u8],TcpErrData> unsafe { + use timer; + log(debug, ~"starting tcp::read"); let iotask = (*socket_data).iotask; let rs_result = read_start_common_impl(socket_data); @@ -1258,6 +1270,17 @@ type TcpBufferedSocketData = { //#[cfg(test)] mod test { + use net; + use net::ip; + use uv; + + use core::io; + use core::oldcomm; + use core::result; + use core::str; + use core::task; + use core::vec; + // FIXME don't run on fbsd or linux 32 bit (#2064) #[cfg(target_os="win32")] #[cfg(target_os="darwin")] @@ -1566,7 +1589,8 @@ mod test { } fn impl_tcp_socket_impl_reader_handles_eof() { - use io::{Reader,ReaderUtil}; + use core::io::{Reader,ReaderUtil}; + let hl_loop = uv::global_loop::get(); let server_ip = ~"127.0.0.1"; let server_port = 10041u; diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs index a6ba728ccbb07..5fc2035179351 100644 --- a/src/libstd/net_url.rs +++ b/src/libstd/net_url.rs @@ -11,8 +11,24 @@ //! Types/fns concerning URLs (see RFC 3986) #[forbid(deprecated_mode)]; -use io::ReaderUtil; -use send_map::linear::LinearMap; +use map; +use map::HashMap; + +use core::cmp::Eq; +use core::dvec::DVec; +use core::from_str::FromStr; +use core::io::{Reader, ReaderUtil}; +use core::io; +use core::send_map::linear::LinearMap; +use core::send_map; +use core::str; +use core::to_bytes::IterBytes; +use core::to_bytes; +use core::to_str::ToStr; +use core::to_str; +use core::uint; +use core::util; +use core::vec; #[deriving_eq] struct Url { @@ -654,7 +670,7 @@ pub pure fn from_str(rawurl: &str) -> Result { Ok(Url::new(scheme, userinfo, host, port, path, query, fragment)) } -impl Url: from_str::FromStr { +impl Url: FromStr { static pure fn from_str(s: &str) -> Option { match from_str(s) { Ok(move url) => Some(url), @@ -719,6 +735,11 @@ impl Url: to_bytes::IterBytes { #[cfg(test)] mod tests { #[legacy_exports]; + use net_url::UserInfo; + + use core::result; + use core::str; + #[test] fn test_split_char_first() { let (u,v) = split_char_first(~"hello, sweet world", ','); @@ -1051,12 +1072,13 @@ mod tests { #[test] fn test_decode_form_urlencoded() { - assert decode_form_urlencoded(~[]).len() == 0; + // XXX: Broken. + /*assert decode_form_urlencoded(~[]).len() == 0; let s = str::to_bytes("a=1&foo+bar=abc&foo+bar=12+%3D+34"); let form = decode_form_urlencoded(s); assert form.len() == 2; assert form.get_ref(&~"a") == &~[~"1"]; - assert form.get_ref(&~"foo bar") == &~[~"abc", ~"12 = 34"]; + assert form.get_ref(&~"foo bar") == &~[~"abc", ~"12 = 34"];*/ } } diff --git a/src/libstd/par.rs b/src/libstd/par.rs index 10cbcaa0c3b3a..d88d298ef18d0 100644 --- a/src/libstd/par.rs +++ b/src/libstd/par.rs @@ -10,6 +10,12 @@ #[forbid(deprecated_mode)]; +use core::cast; +use core::ptr; +use core::sys; +use core::uint; +use core::vec; + use future_spawn = future::spawn; diff --git a/src/libstd/prettyprint.rs b/src/libstd/prettyprint.rs index ef26a8cb19035..87699a9c894e6 100644 --- a/src/libstd/prettyprint.rs +++ b/src/libstd/prettyprint.rs @@ -10,19 +10,21 @@ #[forbid(deprecated_mode)]; -use io::Writer; -use io::WriterUtil; use serialize; -pub struct Encoder { +use core::io::Writer; +use core::io::WriterUtil; +use core::io; + +pub struct Serializer { wr: io::Writer, } -pub fn Encoder(wr: io::Writer) -> Encoder { - Encoder { wr: wr } +pub fn Serializer(wr: io::Writer) -> Serializer { + Serializer { wr: wr } } -pub impl Encoder: serialize::Encoder { +pub impl Serializer: serialize::Encoder { fn emit_nil(&self) { self.wr.write_str(~"()") } diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index 642b27fa46543..4281867635918 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -2,7 +2,8 @@ //! A priority queue implemented with a binary heap use core::cmp::Ord; -use ptr::addr_of; +use core::ptr::addr_of; +use core::vec; #[abi = "rust-intrinsic"] extern "C" mod rusti { diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs index b8cd1dc3ca2e9..f384cceb41be2 100644 --- a/src/libstd/rl.rs +++ b/src/libstd/rl.rs @@ -11,7 +11,9 @@ // FIXME #3921. This is unsafe because linenoise uses global mutable // state without mutexes. -use libc::{c_char, c_int}; +use core::libc::{c_char, c_int}; +use core::str; +use core::task; extern mod rustrt { #[legacy_exports]; @@ -79,4 +81,4 @@ pub unsafe fn complete(cb: CompletionCb) unsafe { } rustrt::linenoiseSetCompletionCallback(callback); -} \ No newline at end of file +} diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs index aa78d22e4c8dd..1513e621fcbb3 100644 --- a/src/libstd/rope.rs +++ b/src/libstd/rope.rs @@ -35,6 +35,13 @@ #[forbid(deprecated_mode)]; +use core::cast; +use core::char; +use core::option; +use core::str; +use core::uint; +use core::vec; + /// The type of ropes. pub type Rope = node::Root; @@ -441,6 +448,8 @@ pub fn loop_leaves(rope: Rope, it: fn(node::Leaf) -> bool) -> bool{ pub mod iterator { pub mod leaf { + use rope::node; + pub fn start(rope: Rope) -> node::leaf_iterator::T { match (rope) { node::Empty => return node::leaf_iterator::empty(), @@ -452,6 +461,8 @@ pub mod iterator { } } pub mod char { + use rope::node; + pub fn start(rope: Rope) -> node::char_iterator::T { match (rope) { node::Empty => return node::char_iterator::empty(), @@ -543,7 +554,15 @@ pub fn char_at(rope: Rope, pos: uint) -> char { /* Section: Implementation */ -mod node { +pub mod node { + use rope::node; + + use core::cast; + use core::char; + use core::option; + use core::str; + use core::uint; + use core::vec; /// Implementation of type `rope` pub enum Root { @@ -1116,6 +1135,9 @@ mod node { } pub mod leaf_iterator { + use core::option; + use core::vec; + pub type T = { stack: ~[mut @Node], mut stackpos: int @@ -1153,6 +1175,11 @@ mod node { } pub mod char_iterator { + use rope::node::leaf_iterator; + + use core::option; + use core::str; + pub type T = { leaf_iterator: leaf_iterator::T, mut leaf: Option, @@ -1232,6 +1259,13 @@ mod node { #[cfg(test)] mod tests { + use rope::iterator; + use rope::node; + + use core::option; + use core::str; + use core::uint; + use core::vec; //Utility function, used for sanity check fn rope_to_string(r: Rope) -> ~str { diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs index 9b1949256931c..97d5ad1878036 100644 --- a/src/libstd/serialize.rs +++ b/src/libstd/serialize.rs @@ -17,6 +17,9 @@ Core encoding and decoding interfaces. #[forbid(deprecated_mode)]; #[forbid(non_camel_case_types)]; +use core::at_vec; +use core::vec; + pub trait Encoder { // Primitive types: fn emit_nil(&self); diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs index 1a005bdc03f9a..2fb12460498be 100644 --- a/src/libstd/sha1.rs +++ b/src/libstd/sha1.rs @@ -24,6 +24,10 @@ #[forbid(deprecated_mode)]; +use core::str; +use core::uint; +use core::vec; + /* * A SHA-1 implementation derived from Paul E. Jones's reference * implementation, which is written for clarity, not speed. At some @@ -33,9 +37,9 @@ /// The SHA-1 interface trait Sha1 { /// Provide message input as bytes - fn input((&[u8])); + fn input(&[const u8]); /// Provide message input as string - fn input_str((&str)); + fn input_str(&str); /** * Read the digest as a vector of 20 bytes. After calling this no further * input may be provided until reset is called. @@ -71,9 +75,9 @@ pub fn sha1() -> Sha1 { mut computed: bool, work_buf: @~[mut u32]}; - fn add_input(st: &Sha1State, msg: &[u8]) { + fn add_input(st: &Sha1State, msg: &[const u8]) { assert (!st.computed); - for vec::each(msg) |element| { + for vec::each_const(msg) |element| { st.msg_block[st.msg_block_idx] = *element; st.msg_block_idx += 1u; st.len_low += 8u32; @@ -239,7 +243,7 @@ pub fn sha1() -> Sha1 { self.h[4] = 0xC3D2E1F0u32; self.computed = false; } - fn input(msg: &[u8]) { add_input(&self, msg); } + fn input(msg: &[const u8]) { add_input(&self, msg); } fn input_str(msg: &str) { let bs = str::to_bytes(msg); add_input(&self, bs); @@ -272,6 +276,11 @@ pub fn sha1() -> Sha1 { mod tests { #[legacy_exports]; + use sha1; + + use core::str; + use core::vec; + #[test] fn test() unsafe { type Test = {input: ~str, output: ~[u8]}; diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs index b16cf99cb4eff..a6c14516af2cd 100644 --- a/src/libstd/smallintmap.rs +++ b/src/libstd/smallintmap.rs @@ -14,11 +14,14 @@ */ #[forbid(deprecated_mode)]; -use core::option; -use core::option::{Some, None}; -use dvec::DVec; +use map; use map::Map; +use core::dvec::DVec; +use core::ops; +use core::option::{Some, None}; +use core::option; + // FIXME (#2347): Should not be @; there's a bug somewhere in rustc that // requires this to be. type SmallIntMap_ = {v: DVec>}; @@ -165,6 +168,8 @@ pub fn as_map(s: SmallIntMap) -> map::Map { #[cfg(test)] mod tests { + use core::option::None; + use core::option; #[test] fn test_insert_with_key() { diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 316e23ef7ac22..505b252674126 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -11,9 +11,11 @@ //! Sorting methods #[forbid(deprecated_mode)]; -use vec::{len, push}; use core::cmp::{Eq, Ord}; -use dvec::DVec; +use core::dvec::DVec; +use core::util; +use core::vec::{len, push}; +use core::vec; type Le = pure fn(v1: &T, v2: &T) -> bool; @@ -712,6 +714,9 @@ fn copy_vec(dest: &[mut T], s1: uint, #[cfg(test)] mod test_qsort3 { #[legacy_exports]; + + use core::vec; + fn check_sort(v1: &[mut int], v2: &[mut int]) { let len = vec::len::(v1); quick_sort3::(v1); @@ -752,6 +757,10 @@ mod test_qsort3 { #[cfg(test)] mod test_qsort { #[legacy_exports]; + + use core::int; + use core::vec; + fn check_sort(v1: &[mut int], v2: &[mut int]) { let len = vec::len::(v1); pure fn leual(a: &int, b: &int) -> bool { *a <= *b } @@ -813,6 +822,8 @@ mod test_qsort { mod tests { #[legacy_exports]; + use core::vec; + fn check_sort(v1: &[int], v2: &[int]) { let len = vec::len::(v1); pub pure fn le(a: &int, b: &int) -> bool { *a <= *b } @@ -876,6 +887,9 @@ mod tests { #[cfg(test)] mod test_tim_sort { + use core::rand; + use core::vec; + struct CVal { val: float, } @@ -966,6 +980,10 @@ mod test_tim_sort { #[cfg(test)] mod big_tests { + use core::rand; + use core::task; + use core::uint; + use core::vec; #[test] fn test_unique() { diff --git a/src/libstd/std.rc b/src/libstd/std.rc index f3781c3867610..22cb91535717e 100644 --- a/src/libstd/std.rc +++ b/src/libstd/std.rc @@ -26,8 +26,6 @@ not required in or otherwise suitable for the core library. #[license = "MIT"]; #[crate_type = "lib"]; -#[no_core]; - #[allow(vecs_implicitly_copyable)]; #[deny(non_camel_case_types)]; // XXX this is set to allow because there are two methods in encoding @@ -35,6 +33,8 @@ not required in or otherwise suitable for the core library. #[allow(deprecated_mode)]; #[forbid(deprecated_pattern)]; +#[no_core]; + extern mod core(vers = "0.6"); use core::*; @@ -98,6 +98,7 @@ pub mod cmp; pub mod base64; pub mod rl; pub mod workcache; +pub mod bigint; #[cfg(unicode)] mod unicode; diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs index e1b029c5396f4..d957a7ee2abbf 100644 --- a/src/libstd/sync.rs +++ b/src/libstd/sync.rs @@ -17,7 +17,13 @@ * in std. */ -use private::{Exclusive, exclusive}; +use core::option; +use core::pipes; +use core::private::{Exclusive, exclusive}; +use core::ptr; +use core::task; +use core::util; +use core::vec; /**************************************************************************** * Internals @@ -702,6 +708,15 @@ impl &RWlockReadMode { #[cfg(test)] mod tests { #[legacy_exports]; + + use core::cast; + use core::option; + use core::pipes; + use core::ptr; + use core::result; + use core::task; + use core::vec; + /************************************************************************ * Semaphore tests ************************************************************************/ diff --git a/src/libstd/task_pool.rs b/src/libstd/task_pool.rs index a87576789af55..68bf2612f9a48 100644 --- a/src/libstd/task_pool.rs +++ b/src/libstd/task_pool.rs @@ -11,8 +11,12 @@ /// A task pool abstraction. Useful for achieving predictable CPU /// parallelism. -use pipes::{Chan, Port}; -use task::{SchedMode, SingleThreaded}; +use core::io; +use core::pipes::{Chan, Port}; +use core::pipes; +use core::task::{SchedMode, SingleThreaded}; +use core::task; +use core::vec; enum Msg { Execute(~fn(&T)), diff --git a/src/libstd/tempfile.rs b/src/libstd/tempfile.rs index 25ea4ad7bb5cf..afb9290f6cfbd 100644 --- a/src/libstd/tempfile.rs +++ b/src/libstd/tempfile.rs @@ -12,8 +12,9 @@ #[forbid(deprecated_mode)]; -use core::option; -use option::{None, Some}; +use core::os; +use core::rand; +use core::str; pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option { let r = rand::Rng(); diff --git a/src/libstd/term.rs b/src/libstd/term.rs index 5ec0f93444055..ae5949e6f183d 100644 --- a/src/libstd/term.rs +++ b/src/libstd/term.rs @@ -11,7 +11,12 @@ //! Simple ANSI color library #[forbid(deprecated_mode)]; -use core::Option; +use core::i32; +use core::io; +use core::option; +use core::os; +use core::str; +use core::vec; // FIXME (#2807): Windows support. diff --git a/src/libstd/test.rs b/src/libstd/test.rs index d365077d0639d..98416a88f10bc 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -17,17 +17,28 @@ #[forbid(deprecated_mode)]; +use getopts; +use sort; +use term; + use core::cmp::Eq; -use either::Either; -use result::{Ok, Err}; -use io::WriterUtil; -use libc::size_t; -use task::TaskBuilder; +use core::either::Either; +use core::either; +use core::io::WriterUtil; +use core::io; +use core::libc::size_t; +use core::oldcomm; +use core::option; +use core::result; +use core::str; +use core::task::TaskBuilder; +use core::task; +use core::vec; #[abi = "cdecl"] extern mod rustrt { #[legacy_exports]; - fn rust_sched_threads() -> libc::size_t; + fn rust_sched_threads() -> size_t; } // The name of a test. By convention this follows the rules for rust @@ -44,12 +55,12 @@ pub type TestFn = fn~(); // The definition of a single test. A test runner will run a list of // these. -pub type TestDesc = { +pub struct TestDesc { name: TestName, testfn: TestFn, ignore: bool, should_fail: bool -}; +} // The default console test runner. It accepts the command line // arguments and a vector of test_descs (generated at compile time). @@ -230,14 +241,14 @@ fn print_failures(st: ConsoleTestState) { #[test] fn should_sort_failures_before_printing_them() { let s = do io::with_str_writer |wr| { - let test_a = { + let test_a = TestDesc { name: ~"a", testfn: fn~() { }, ignore: false, should_fail: false }; - let test_b = { + let test_b = TestDesc { name: ~"b", testfn: fn~() { }, ignore: false, @@ -359,10 +370,11 @@ fn filter_tests(opts: &TestOpts, } else { fn filter(test: &TestDesc) -> Option { if test.ignore { - return option::Some({name: test.name, - testfn: copy test.testfn, - ignore: false, - should_fail: test.should_fail}); + return option::Some(TestDesc { + name: test.name, + testfn: copy test.testfn, + ignore: false, + should_fail: test.should_fail}); } else { return option::None; } }; @@ -414,10 +426,15 @@ fn calc_result(test: &TestDesc, task_succeeded: bool) -> TestResult { mod tests { #[legacy_exports]; + use core::either; + use core::oldcomm; + use core::option; + use core::vec; + #[test] fn do_not_run_ignored_tests() { fn f() { fail; } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: true, @@ -433,7 +450,7 @@ mod tests { #[test] fn ignored_tests_result_in_ignored() { fn f() { } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: true, @@ -450,7 +467,7 @@ mod tests { #[ignore(cfg(windows))] fn test_should_fail() { fn f() { fail; } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: false, @@ -466,7 +483,7 @@ mod tests { #[test] fn test_should_fail_but_succeeds() { fn f() { } - let desc = { + let desc = TestDesc { name: ~"whatever", testfn: f, ignore: false, @@ -507,10 +524,10 @@ mod tests { let opts = {filter: option::None, run_ignored: true, logfile: option::None}; let tests = - ~[{name: ~"1", testfn: fn~() { }, - ignore: true, should_fail: false}, - {name: ~"2", testfn: fn~() { }, - ignore: false, should_fail: false}]; + ~[TestDesc {name: ~"1", testfn: fn~() { }, + ignore: true, should_fail: false}, + TestDesc {name: ~"2", testfn: fn~() { }, + ignore: false, should_fail: false}]; let filtered = filter_tests(&opts, tests); assert (vec::len(filtered) == 1u); @@ -535,8 +552,9 @@ mod tests { let testfn = fn~() { }; let mut tests = ~[]; for vec::each(names) |name| { - let test = {name: *name, testfn: copy testfn, ignore: false, - should_fail: false}; + let test = TestDesc { + name: *name, testfn: copy testfn, ignore: false, + should_fail: false}; tests.push(move test); } move tests diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 1058910c35a64..7c586c3fd4e21 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -11,9 +11,13 @@ #[forbid(deprecated_mode)]; use core::cmp::Eq; -use libc::{c_char, c_int, c_long, size_t, time_t}; -use io::{Reader, ReaderUtil}; -use result::{Result, Ok, Err}; +use core::int; +use core::libc::{c_char, c_int, c_long, size_t, time_t}; +use core::i32; +use core::io::{Reader, ReaderUtil}; +use core::io; +use core::result::{Result, Ok, Err}; +use core::str; #[abi = "cdecl"] extern mod rustrt { @@ -853,6 +857,14 @@ priv fn do_strftime(format: &str, tm: &Tm) -> ~str { mod tests { #[legacy_exports]; + use core::float; + use core::os; + use core::result; + use core::str; + use core::u64; + use core::uint; + use core::vec; + #[test] fn test_get_time() { const some_recent_date: i64 = 1325376000i64; // 2012-01-01T00:00:00Z @@ -900,7 +912,7 @@ mod tests { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); - let time = Timespec::new(1234567890, 54321); + let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); assert utc.tm_sec == 30_i32; @@ -922,7 +934,7 @@ mod tests { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); - let time = Timespec::new(1234567890, 54321); + let time = ::time::Timespec::new(1234567890, 54321); let local = at(time); error!("time_at: %?", local); @@ -951,7 +963,7 @@ mod tests { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); - let time = Timespec::new(1234567890, 54321); + let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); assert utc.to_timespec() == time; @@ -963,7 +975,7 @@ mod tests { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); - let time = Timespec::new(1234567890, 54321); + let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); let local = at(time); @@ -1136,7 +1148,7 @@ mod tests { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); - let time = Timespec::new(1234567890, 54321); + let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); let local = at(time); @@ -1152,7 +1164,7 @@ mod tests { os::setenv(~"TZ", ~"America/Los_Angeles"); tzset(); - let time = Timespec::new(1234567890, 54321); + let time = ::time::Timespec::new(1234567890, 54321); let utc = at_utc(time); let local = at(time); diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs index c3a2a11e1f840..038486f2b902d 100644 --- a/src/libstd/timer.rs +++ b/src/libstd/timer.rs @@ -12,9 +12,16 @@ #[forbid(deprecated_mode)]; +use uv; use uv::iotask; use uv::iotask::IoTask; +use core::either; +use core::libc; +use core::oldcomm; +use core::ptr; +use core; + /** * Wait for timeout period then send provided value over a channel * @@ -32,7 +39,9 @@ use uv::iotask::IoTask; * * val - a value of type T to send over the provided `ch` */ pub fn delayed_send(iotask: IoTask, - msecs: uint, ch: oldcomm::Chan, val: T) { + msecs: uint, + ch: oldcomm::Chan, + val: T) { unsafe { let timer_done_po = oldcomm::Port::<()>(); let timer_done_ch = oldcomm::Chan(&timer_done_po); @@ -108,8 +117,9 @@ pub fn sleep(iotask: IoTask, msecs: uint) { * be a `some(T)`. If not, then `none` will be returned. */ pub fn recv_timeout(iotask: IoTask, - msecs: uint, - wait_po: oldcomm::Port) -> Option { + msecs: uint, + wait_po: oldcomm::Port) + -> Option { let timeout_po = oldcomm::Port::<()>(); let timeout_ch = oldcomm::Chan(&timeout_po); delayed_send(iotask, msecs, timeout_ch, ()); @@ -153,6 +163,14 @@ extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) unsafe { #[cfg(test)] mod test { #[legacy_exports]; + + use uv; + + use core::iter; + use core::oldcomm; + use core::rand; + use core::task; + #[test] fn test_gl_timer_simple_sleep_test() { let hl_loop = uv::global_loop::get(); diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs index e1874bd0bfd49..caccb763ee9d6 100644 --- a/src/libstd/treemap.rs +++ b/src/libstd/treemap.rs @@ -107,6 +107,8 @@ pub fn equals(t1: &const TreeEdge, mod tests { #[legacy_exports]; + use core::str; + #[test] fn init_treemap() { let _m = TreeMap::(); } diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs index 2efbfae3da4e2..43ed58aa0c125 100644 --- a/src/libstd/uv_global_loop.rs +++ b/src/libstd/uv_global_loop.rs @@ -16,10 +16,15 @@ use ll = uv_ll; use iotask = uv_iotask; use get_gl = get; use uv_iotask::{IoTask, spawn_iotask}; -use private::{chan_from_global_ptr, weaken_task}; + +use core::either::{Left, Right}; +use core::libc; use core::oldcomm::{Port, Chan, select2, listen}; -use task::TaskBuilder; -use either::{Left, Right}; +use core::private::{chan_from_global_ptr, weaken_task}; +use core::str; +use core::task::TaskBuilder; +use core::task; +use core::vec; extern mod rustrt { fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t; @@ -118,6 +123,15 @@ fn spawn_loop() -> IoTask { #[cfg(test)] mod test { + use uv::iotask; + use uv::ll; + + use core::iter; + use core::libc; + use core::oldcomm; + use core::ptr; + use core::task; + extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) unsafe { let exit_ch_ptr = ll::get_data_for_uv_handle( timer_ptr as *libc::c_void) as *oldcomm::Chan; diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs index d778606075d1a..7853f1cd9f79f 100644 --- a/src/libstd/uv_iotask.rs +++ b/src/libstd/uv_iotask.rs @@ -16,12 +16,15 @@ */ #[forbid(deprecated_mode)]; -use libc::c_void; -use ptr::addr_of; -use core::oldcomm::{Port, Chan, listen}; -use task::TaskBuilder; use ll = uv_ll; +use core::libc::c_void; +use core::libc; +use core::oldcomm::{Port, Chan, listen}; +use core::ptr::addr_of; +use core::task::TaskBuilder; +use core::task; + /// Used to abstract-away direct interaction with a libuv loop. pub enum IoTask { IoTask_({ @@ -173,6 +176,14 @@ extern fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe { #[cfg(test)] mod test { + use uv::ll; + + use core::iter; + use core::libc; + use core::oldcomm; + use core::ptr; + use core::task; + extern fn async_close_cb(handle: *ll::uv_async_t) unsafe { log(debug, fmt!("async_close_cb handle %?", handle)); let exit_ch = (*(ll::get_data_for_uv_handle(handle) diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs index 65333b41864e5..46574ced2e596 100644 --- a/src/libstd/uv_ll.rs +++ b/src/libstd/uv_ll.rs @@ -32,8 +32,12 @@ #[allow(non_camel_case_types)]; // C types -use libc::size_t; -use ptr::to_unsafe_ptr; +use core::libc::size_t; +use core::libc; +use core::ptr::to_unsafe_ptr; +use core::ptr; +use core::str; +use core::vec; // libuv struct mappings pub type uv_ip4_addr = { @@ -315,6 +319,8 @@ pub type uv_getaddrinfo_t = { }; pub mod uv_ll_struct_stubgen { + use core::ptr; + pub fn gen_stub_uv_tcp_t() -> uv_tcp_t { return gen_stub_os(); #[cfg(target_os = "linux")] @@ -1034,6 +1040,13 @@ pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 { #[cfg(test)] pub mod test { + use core::libc; + use core::oldcomm; + use core::ptr; + use core::str; + use core::sys; + use core::task; + use core::vec; enum tcp_read_data { tcp_read_eof, @@ -1556,7 +1569,8 @@ pub mod test { // struct size tests #[test] fn test_uv_ll_struct_size_uv_tcp_t() { - let foreign_handle_size = rustrt::rust_uv_helper_uv_tcp_t_size(); + let foreign_handle_size = + ::uv_ll::rustrt::rust_uv_helper_uv_tcp_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_tcp_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1566,7 +1580,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_uv_connect_t() { let foreign_handle_size = - rustrt::rust_uv_helper_uv_connect_t_size(); + ::uv_ll::rustrt::rust_uv_helper_uv_connect_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_connect_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1576,7 +1590,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_uv_buf_t() { let foreign_handle_size = - rustrt::rust_uv_helper_uv_buf_t_size(); + ::uv_ll::rustrt::rust_uv_helper_uv_buf_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_buf_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1586,7 +1600,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_uv_write_t() { let foreign_handle_size = - rustrt::rust_uv_helper_uv_write_t_size(); + ::uv_ll::rustrt::rust_uv_helper_uv_write_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_write_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1597,7 +1611,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_sockaddr_in() { let foreign_handle_size = - rustrt::rust_uv_helper_sockaddr_in_size(); + ::uv_ll::rustrt::rust_uv_helper_sockaddr_in_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("sockaddr_in -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1607,7 +1621,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_sockaddr_in6() { let foreign_handle_size = - rustrt::rust_uv_helper_sockaddr_in6_size(); + ::uv_ll::rustrt::rust_uv_helper_sockaddr_in6_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1622,7 +1636,7 @@ pub mod test { #[ignore(reason = "questionable size calculations")] fn test_uv_ll_struct_size_addr_in() { let foreign_handle_size = - rustrt::rust_uv_helper_addr_in_size(); + ::uv_ll::rustrt::rust_uv_helper_addr_in_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("addr_in -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1634,7 +1648,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_uv_async_t() { let foreign_handle_size = - rustrt::rust_uv_helper_uv_async_t_size(); + ::uv_ll::rustrt::rust_uv_helper_uv_async_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_async_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1645,7 +1659,7 @@ pub mod test { #[test] fn test_uv_ll_struct_size_uv_timer_t() { let foreign_handle_size = - rustrt::rust_uv_helper_uv_timer_t_size(); + ::uv_ll::rustrt::rust_uv_helper_uv_timer_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_timer_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1657,7 +1671,7 @@ pub mod test { #[ignore(cfg(target_os = "win32"))] fn test_uv_ll_struct_size_uv_getaddrinfo_t() { let foreign_handle_size = - rustrt::rust_uv_helper_uv_getaddrinfo_t_size(); + ::uv_ll::rustrt::rust_uv_helper_uv_getaddrinfo_t_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("uv_getaddrinfo_t -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); @@ -1669,7 +1683,7 @@ pub mod test { #[ignore(cfg(target_os = "win32"))] fn test_uv_ll_struct_size_addrinfo() { let foreign_handle_size = - rustrt::rust_uv_helper_addrinfo_size(); + ::uv_ll::rustrt::rust_uv_helper_addrinfo_size(); let rust_handle_size = sys::size_of::(); let output = fmt!("addrinfo -- foreign: %u rust: %u", foreign_handle_size as uint, rust_handle_size); diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs index 4d49e98a8b7ec..3631556c2ba00 100644 --- a/src/libstd/workcache.rs +++ b/src/libstd/workcache.rs @@ -8,15 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use core::cmp::Eq; -use send_map::linear::LinearMap; -use pipes::{recv, oneshot, PortOne, send_one}; -use either::{Right,Left,Either}; - use json; use sha1; use serialize::{Encoder, Encodable, Decoder, Decodable}; +use core::either::{Either, Left, Right}; +use core::io; +use core::option; +use core::pipes::{recv, oneshot, PortOne, send_one}; +use core::result; +use core::run; +use core::send_map::linear::LinearMap; +use core::task; +use core::to_bytes; + /** * * This is a loose clone of the fbuild build system, made a touch more @@ -327,6 +332,7 @@ fn unwrap = {node: T, span: span}; @@ -408,6 +415,7 @@ impl mutability : cmp::Eq { #[auto_encode] #[auto_decode] +#[deriving_eq] pub enum Proto { ProtoBare, // bare functions (deprecated) ProtoUniq, // ~fn @@ -415,13 +423,6 @@ pub enum Proto { ProtoBorrowed, // &fn } -impl Proto : cmp::Eq { - pure fn eq(&self, other: &Proto) -> bool { - ((*self) as uint) == ((*other) as uint) - } - pure fn ne(&self, other: &Proto) -> bool { !(*self).eq(other) } -} - impl Proto : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { (*self as uint).iter_bytes(lsb0, f); @@ -1061,20 +1062,24 @@ enum region_ { #[auto_encode] #[auto_decode] +#[deriving_eq] enum Onceness { Once, Many } -impl Onceness : cmp::Eq { - pure fn eq(&self, other: &Onceness) -> bool { - match ((*self), *other) { - (Once, Once) | (Many, Many) => true, - _ => false +impl Onceness : ToStr { + pure fn to_str() -> ~str { + match self { + ast::Once => ~"once", + ast::Many => ~"many" } } - pure fn ne(&self, other: &Onceness) -> bool { - !(*self).eq(other) +} + +impl Onceness : to_bytes::IterBytes { + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + (*self as uint).iter_bytes(lsb0, f); } } @@ -1149,6 +1154,17 @@ enum purity { extern_fn, // declared with "extern fn" } +impl purity : ToStr { + pure fn to_str() -> ~str { + match self { + impure_fn => ~"impure", + unsafe_fn => ~"unsafe", + pure_fn => ~"pure", + extern_fn => ~"extern" + } + } +} + impl purity : to_bytes::IterBytes { pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { (*self as u8).iter_bytes(lsb0, f) diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 6e684d0daf4f3..9872410a8079d 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -8,13 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map; -use std::map::HashMap; use ast::*; -use print::pprust; +use ast; use ast_util::{path_to_ident, stmt_id}; +use ast_util; +use attr; +use codemap; use diagnostic::span_handler; use parse::token::ident_interner; +use print::pprust; +use visit; + +use core::cmp; +use core::either; +use core::str; +use core::vec; +use std::map::HashMap; +use std::map; +use std; enum path_elt { path_mod(ident), @@ -97,7 +108,7 @@ fn extend(cx: ctx, +elt: ident) -> @path { } fn mk_ast_map_visitor() -> vt { - return visit::mk_vt(@{ + return visit::mk_vt(@visit::Visitor { visit_item: map_item, visit_expr: map_expr, visit_stmt: map_stmt, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 521114bf2973a..77953e783ba07 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -8,8 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use codemap::{span, BytePos}; use ast::*; +use ast; +use ast_util; +use codemap::{span, BytePos}; +use visit; + +use core::cmp; +use core::int; +use core::option; +use core::str; +use core::to_bytes; +use core::vec; pure fn spanned(+lo: BytePos, +hi: BytePos, +t: T) -> spanned { respan(mk_sp(lo, hi), move t) @@ -262,10 +272,10 @@ pure fn is_call_expr(e: @expr) -> bool { } // This makes def_id hashable -impl def_id : core::to_bytes::IterBytes { +impl def_id : to_bytes::IterBytes { #[inline(always)] - pure fn iter_bytes(&self, +lsb0: bool, f: core::to_bytes::Cb) { - core::to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f); + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + to_bytes::iter_bytes_2(&self.crate, &self.node, lsb0, f); } } @@ -426,10 +436,8 @@ fn empty(range: id_range) -> bool { } fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> { - visit::mk_simple_visitor(@{ - visit_mod: fn@(_m: _mod, _sp: span, id: node_id) { - vfn(id) - }, + visit::mk_simple_visitor(@visit::SimpleVisitor { + visit_mod: |_m, _sp, id| vfn(id), visit_view_item: fn@(vi: @view_item) { match vi.node { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index aadea886407cd..73c14e2d00cf2 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -10,13 +10,21 @@ // Functions dealing with attributes and meta_items -use std::map; -use std::map::HashMap; -use either::Either; -use diagnostic::span_handler; +use ast; use ast_util::{spanned, dummy_spanned}; -use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; +use attr; use codemap::BytePos; +use diagnostic::span_handler; +use parse::comments::{doc_comment_style, strip_doc_comment_decoration}; + +use core::cmp; +use core::either::Either; +use core::either; +use core::option; +use core::vec; +use std::map::HashMap; +use std::map; +use std; // Constructors export mk_name_value_item_str; @@ -170,15 +178,15 @@ fn get_name_value_str_pair(item: @ast::meta_item) -> Option<(~str, ~str)> { /* Searching */ /// Search a list of attributes and return only those with a specific name -fn find_attrs_by_name(attrs: ~[ast::attribute], name: ~str) -> +fn find_attrs_by_name(attrs: ~[ast::attribute], name: &str) -> ~[ast::attribute] { - let filter = ( - fn@(a: &ast::attribute) -> Option { - if get_attr_name(*a) == name { - option::Some(*a) - } else { option::None } + let filter: &fn(a: &ast::attribute) -> Option = |a| { + if name == get_attr_name(*a) { + option::Some(*a) + } else { + option::None } - ); + }; return vec::filter_map(attrs, filter); } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 974455972f15e..1f26711abb966 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -21,7 +21,14 @@ source code snippets, etc. */ -use dvec::DVec; +use ast_util; + +use core::cmp; +use core::dvec::DVec; +use core::str; +use core::to_bytes; +use core::uint; +use core::vec; use std::serialize::{Encodable, Decodable, Encoder, Decoder}; trait Pos { @@ -308,6 +315,10 @@ pub impl CodeMap { } pub fn span_to_str(&self, sp: span) -> ~str { + if self.files.len() == 0 && sp == ast_util::dummy_sp() { + return ~"no-location"; + } + let lo = self.lookup_char_pos_adj(sp.lo); let hi = self.lookup_char_pos_adj(sp.hi); return fmt!("%s:%u:%u: %u:%u", lo.filename, diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index e42bb00c2129d..ddffa04622f32 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -8,11 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::term; -use io::WriterUtil; use codemap::span; +use codemap; + +use core::cmp; +use core::io::WriterUtil; +use core::io; +use core::option; +use core::str; +use core::vec; +use core::dvec::DVec; + +use std::term; -export emitter, emit; +export emitter, collect, emit; export level, fatal, error, warning, note; export span_handler, handler, mk_span_handler, mk_handler; export codemap_span_handler, codemap_handler; @@ -136,7 +145,7 @@ fn mk_handler(emitter: Option) -> handler { Some(e) => e, None => { let f = fn@(cmsp: Option<(@codemap::CodeMap, span)>, - msg: &str, t: level) { + msg: &str, t: level) { emit(cmsp, msg, t); }; f @@ -199,6 +208,12 @@ fn print_diagnostic(topic: ~str, lvl: level, msg: &str) { io::stderr().write_str(fmt!(" %s\n", msg)); } +fn collect(messages: @DVec<~str>) + -> fn@(Option<(@codemap::CodeMap, span)>, &str, level) +{ + |_o, msg: &str, _l| { messages.push(msg.to_str()); } +} + fn emit(cmsp: Option<(@codemap::CodeMap, span)>, msg: &str, lvl: level) { match cmsp { Some((cm, sp)) => { diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 8eb37386364f4..b8fe00e246c7c 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -88,8 +88,12 @@ node twice. */ -use ext::base::*; +use ast_util; +use attr; use codemap::span; +use ext::base::*; + +use core::vec; use std::map; use std::map::HashMap; @@ -259,11 +263,20 @@ priv impl ext_ctxt { @{span: span, global: false, idents: strs, rp: None, types: ~[]} } + fn path_global(span: span, strs: ~[ast::ident]) -> @ast::path { + @{span: span, global: true, 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 path_tps_global(span: span, strs: ~[ast::ident], + tps: ~[@ast::Ty]) -> @ast::path { + @{span: span, global: true, idents: strs, rp: None, types: tps} + } + fn ty_path(span: span, strs: ~[ast::ident], tps: ~[@ast::Ty]) -> @ast::Ty { @{id: self.next_id(), @@ -334,6 +347,10 @@ priv impl ext_ctxt { self.expr(span, ast::expr_path(self.path(span, strs))) } + fn expr_path_global(span: span, strs: ~[ast::ident]) -> @ast::expr { + self.expr(span, ast::expr_path(self.path_global(span, strs))) + } + fn expr_var(span: span, var: ~str) -> @ast::expr { self.expr_path(span, ~[self.ident_of(var)]) } @@ -424,7 +441,7 @@ fn mk_ser_impl( let ty_param = cx.bind_path( span, cx.ident_of(~"__S"), - cx.path( + cx.path_global( span, ~[ cx.ident_of(~"std"), @@ -436,7 +453,7 @@ fn mk_ser_impl( ); // Make a path to the std::serialize::Encodable trait. - let path = cx.path_tps( + let path = cx.path_tps_global( span, ~[ cx.ident_of(~"std"), @@ -468,7 +485,7 @@ fn mk_deser_impl( let ty_param = cx.bind_path( span, cx.ident_of(~"__D"), - cx.path( + cx.path_global( span, ~[ cx.ident_of(~"std"), @@ -480,7 +497,7 @@ fn mk_deser_impl( ); // Make a path to the std::serialize::Decodable trait. - let path = cx.path_tps( + let path = cx.path_tps_global( span, ~[ cx.ident_of(~"std"), @@ -815,7 +832,7 @@ fn mk_deser_fields( cx.expr_blk( cx.expr_call( span, - cx.expr_path(span, ~[ + cx.expr_path_global(span, ~[ cx.ident_of(~"std"), cx.ident_of(~"serialize"), cx.ident_of(~"Decodable"), @@ -1019,7 +1036,7 @@ fn mk_enum_deser_variant_nary( let expr_lambda = cx.lambda_expr( cx.expr_call( span, - cx.expr_path(span, ~[ + cx.expr_path_global(span, ~[ cx.ident_of(~"std"), cx.ident_of(~"serialize"), cx.ident_of(~"Decodable"), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cf994e0ea5224..dc774805ed3f6 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -8,12 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map::HashMap; -use parse::parser; -use diagnostic::span_handler; -use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom}; +use ast; use ast_util::dummy_sp; -use parse::token; +use codemap; +use codemap::{CodeMap, span, ExpnInfo, ExpandedFrom}; +use diagnostic::span_handler; +use ext; +use parse; +use parse::{parser, token}; + +use core::io; +use core::vec; +use std::map::HashMap; // new-style macro! tt code: // diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 1e7d27bee6e48..d63f14b57749a 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ast; +use codemap; use codemap::span; use ext::base::ext_ctxt; +use ext::build; + +use core::dvec; +use core::option; fn mk_expr(cx: ext_ctxt, sp: codemap::span, expr: ast::expr_) -> @ast::expr { @@ -55,10 +61,19 @@ fn mk_raw_path_(sp: span, -> @ast::path { @{ span: sp, global: false, idents: idents, rp: None, types: move types } } +fn mk_raw_path_global(sp: span, idents: ~[ast::ident]) -> @ast::path { + let p : @ast::path = @{span: sp, global: true, idents: idents, + rp: None, types: ~[]}; + return p; +} fn mk_path(cx: ext_ctxt, sp: span, idents: ~[ast::ident]) -> @ast::expr { mk_expr(cx, sp, ast::expr_path(mk_raw_path(sp, idents))) } +fn mk_path_global(cx: ext_ctxt, sp: span, idents: ~[ast::ident]) -> + @ast::expr { + mk_expr(cx, sp, ast::expr_path(mk_raw_path_global(sp, idents))) +} fn mk_access_(cx: ext_ctxt, sp: span, p: @ast::expr, m: ast::ident) -> @ast::expr { mk_expr(cx, sp, ast::expr_field(p, m, ~[])) @@ -80,6 +95,11 @@ fn mk_call(cx: ext_ctxt, sp: span, fn_path: ~[ast::ident], let pathexpr = mk_path(cx, sp, fn_path); return mk_call_(cx, sp, pathexpr, args); } +fn mk_call_global(cx: ext_ctxt, sp: span, fn_path: ~[ast::ident], + args: ~[@ast::expr]) -> @ast::expr { + let pathexpr = mk_path_global(cx, sp, fn_path); + return mk_call_(cx, sp, pathexpr, args); +} // e = expr, t = type fn mk_base_vec_e(cx: ext_ctxt, sp: span, exprs: ~[@ast::expr]) -> @ast::expr { @@ -244,6 +264,15 @@ fn mk_ty_path(cx: ext_ctxt, let ty = @{ id: cx.next_id(), node: move ty, span: span }; ty } +fn mk_ty_path_global(cx: ext_ctxt, + span: span, + idents: ~[ ast::ident ]) + -> @ast::Ty { + let ty = build::mk_raw_path_global(span, idents); + let ty = ast::ty_path(ty, cx.next_id()); + let ty = @{ id: cx.next_id(), node: move ty, span: span }; + ty +} fn mk_simple_ty_path(cx: ext_ctxt, span: span, ident: ast::ident) diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index d84d79082a4f8..4f88ffeeb0468 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -9,6 +9,7 @@ // except according to those terms. use ext::base::*; +use ext::base; fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) -> base::mac_result { diff --git a/src/libsyntax/ext/deriving.rs b/src/libsyntax/ext/deriving.rs index d1ba835a3e519..3cbc8f3834fd4 100644 --- a/src/libsyntax/ext/deriving.rs +++ b/src/libsyntax/ext/deriving.rs @@ -19,9 +19,13 @@ use ast::{struct_variant_kind, sty_by_ref, sty_region, tuple_variant_kind}; use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_rptr, unnamed_field}; use ast::{variant}; use ext::base::ext_ctxt; +use ext::build; use codemap::span; use parse::token::special_idents::clownshoes_extensions; +use core::dvec; +use core::uint; + enum Junction { Conjunction, Disjunction, @@ -202,7 +206,9 @@ fn create_derived_impl(cx: ext_ctxt, // Create the type parameters. let impl_ty_params = dvec::DVec(); for ty_params.each |ty_param| { - let bound = build::mk_ty_path(cx, span, trait_path.map(|x| *x)); + let bound = build::mk_ty_path_global(cx, + span, + trait_path.map(|x| *x)); let bounds = @~[ ty_param_bound(bound) ]; let impl_ty_param = build::mk_ty_param(cx, ty_param.ident, bounds); impl_ty_params.push(move impl_ty_param); @@ -212,7 +218,7 @@ fn create_derived_impl(cx: ext_ctxt, // Create the reference to the trait. let trait_path = { span: span, - global: false, + global: true, idents: trait_path.map(|x| *x), rp: None, types: ~[] diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index b5c55437d70b3..c07853a400bbc 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -14,8 +14,14 @@ * should all get sucked into either the compiler syntax extension plugin * interface. */ + use ext::base::*; +use ext::base; use ext::build::mk_uniq_str; + +use core::option; +use core::os; + export expand_syntax_ext; fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 41d5c8ee0bbd3..6666254e307b6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -8,17 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map::HashMap; - -use ast::{crate, expr_, expr_mac, mac_invoc_tt, - tt_delim, tt_tok, item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi}; -use fold::*; +use ast::{crate, expr_, expr_mac, mac_invoc_tt}; +use ast::{tt_delim, tt_tok, item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi}; +use ast; +use codemap::{span, ExpandedFrom}; use ext::base::*; +use fold::*; use parse::{parser, parse_expr_from_source_str, new_parser_from_tts}; - -use codemap::{span, ExpandedFrom}; - +use core::option; +use core::vec; +use std::map::HashMap; fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt, e: expr_, s: span, fld: ast_fold, @@ -276,18 +276,17 @@ fn core_macros() -> ~str { macro_rules! ignore (($($x:tt)*) => (())) macro_rules! error ( ($( $arg:expr ),+) => ( - log(core::error, fmt!( $($arg),+ )) )) + log(::core::error, fmt!( $($arg),+ )) )) macro_rules! warn ( ($( $arg:expr ),+) => ( - log(core::warn, fmt!( $($arg),+ )) )) + log(::core::warn, fmt!( $($arg),+ )) )) macro_rules! info ( ($( $arg:expr ),+) => ( - log(core::info, fmt!( $($arg),+ )) )) + log(::core::info, fmt!( $($arg),+ )) )) macro_rules! debug ( ($( $arg:expr ),+) => ( - log(core::debug, fmt!( $($arg),+ )) )) + log(::core::debug, fmt!( $($arg),+ )) )) macro_rules! die( ($msg: expr) => ( - core::sys::begin_unwind($msg, - file!().to_owned(), line!()) + ::core::sys::begin_unwind($msg, file!().to_owned(), line!()) ); () => ( die!(~\"explicit failure\") @@ -299,10 +298,10 @@ fn core_macros() -> ~str { { $c:ident: $in:ty -> $out:ty; } => { mod $c { - fn key(_x: @core::condition::Handler<$in,$out>) { } + fn key(_x: @::core::condition::Handler<$in,$out>) { } - pub const cond : core::condition::Condition<$in,$out> = - core::condition::Condition { + pub const cond : ::core::condition::Condition<$in,$out> = + ::core::condition::Condition { name: stringify!(c), key: key }; @@ -318,13 +317,13 @@ fn expand_crate(parse_sess: parse::parse_sess, let exts = syntax_expander_table(); let afp = default_ast_fold(); let cx: ext_ctxt = mk_ctxt(parse_sess, cfg); - let f_pre = - @{fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr), - fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod), - fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item), - fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt), - new_span: |a| new_span(cx, a), - .. *afp}; + let f_pre = @AstFoldFns { + fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr), + fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod), + fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item), + fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt), + new_span: |a| new_span(cx, a), + .. *afp}; let f = make_fold(f_pre); let cm = parse_expr_from_source_str(~"", @core_macros(), diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs index 2b5f95c4066da..b8a27096f7304 100644 --- a/src/libsyntax/ext/fmt.rs +++ b/src/libsyntax/ext/fmt.rs @@ -15,10 +15,14 @@ * should all get sucked into either the standard library extfmt module or the * compiler syntax extension plugin interface. */ -use extfmt::ct::*; -use ext::base::*; + +use ast; use codemap::span; +use ext::base::*; +use ext::base; use ext::build::*; +use extfmt::ct::*; + export expand_syntax_ext; fn expand_syntax_ext(cx: ext_ctxt, sp: span, tts: ~[ast::token_tree]) @@ -57,7 +61,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, } fn make_rt_path_expr(cx: ext_ctxt, sp: span, nm: @~str) -> @ast::expr { let path = make_path_vec(cx, nm); - return mk_path(cx, sp, path); + return mk_path_global(cx, sp, path); } // Produces an AST expression that represents a RT::conv record, // which tells the RT::conv* functions how to perform the conversion @@ -87,7 +91,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, let count_lit = mk_uint(cx, sp, c as uint); let count_is_path = make_path_vec(cx, @~"CountIs"); let count_is_args = ~[count_lit]; - return mk_call(cx, sp, count_is_path, count_is_args); + return mk_call_global(cx, sp, count_is_path, count_is_args); } _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion") } @@ -129,7 +133,7 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, let path = make_path_vec(cx, @fname); let cnv_expr = make_rt_conv_expr(cx, sp, cnv); let args = ~[cnv_expr, arg]; - return mk_call(cx, arg.span, path, args); + return mk_call_global(cx, arg.span, path, args); } fn make_new_conv(cx: ext_ctxt, sp: span, cnv: Conv, arg: @ast::expr) -> @@ -285,10 +289,11 @@ fn pieces_to_expr(cx: ext_ctxt, sp: span, } let arg_vec = mk_fixed_vec_e(cx, fmt_sp, piece_exprs); - return mk_call(cx, fmt_sp, - ~[cx.parse_sess().interner.intern(@~"str"), - cx.parse_sess().interner.intern(@~"concat")], - ~[arg_vec]); + return mk_call_global(cx, + fmt_sp, + ~[cx.parse_sess().interner.intern(@~"str"), + cx.parse_sess().interner.intern(@~"concat")], + ~[arg_vec]); } // // Local Variables: diff --git a/src/libsyntax/ext/log_syntax.rs b/src/libsyntax/ext/log_syntax.rs index 47096182fe848..563c56e02b506 100644 --- a/src/libsyntax/ext/log_syntax.rs +++ b/src/libsyntax/ext/log_syntax.rs @@ -8,8 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ast; +use codemap; use ext::base::*; -use io::WriterUtil; +use ext::base; +use print; + +use core::io::WriterUtil; +use core::option; fn expand_syntax_ext(cx: ext_ctxt, sp: codemap::span, tt: ~[ast::token_tree]) -> base::mac_result { diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 56f426e3853bf..7a87d909fe677 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -14,11 +14,16 @@ // something smarter. use ast::{ident, node_id}; +use ast; use ast_util::{ident_to_path, respan, dummy_sp}; +use ast_util; +use attr; use codemap::span; use ext::base::mk_ctxt; use ext::quote::rt::*; +use core::vec; + // Transitional reexports so qquote can find the paths it is looking for mod syntax { #[legacy_exports]; @@ -34,6 +39,14 @@ fn path(ids: ~[ident], span: span) -> @ast::path { types: ~[]} } +fn path_global(ids: ~[ident], span: span) -> @ast::path { + @{span: span, + global: true, + idents: ids, + rp: None, + types: ~[]} +} + trait append_types { fn add_ty(ty: @ast::Ty) -> @ast::path; fn add_tys(+tys: ~[@ast::Ty]) -> @ast::path; @@ -82,6 +95,7 @@ trait ext_ctxt_ast_builder { +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_vars_global(+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; @@ -303,4 +317,9 @@ impl ext_ctxt: ext_ctxt_ast_builder { ty_params.map(|p| self.ty_path_ast_builder( path(~[p.ident], dummy_sp()))) } + + fn ty_vars_global(+ty_params: ~[ast::ty_param]) -> ~[@ast::Ty] { + ty_params.map(|p| self.ty_path_ast_builder( + path(~[p.ident], dummy_sp()))) + } } diff --git a/src/libsyntax/ext/pipes/check.rs b/src/libsyntax/ext/pipes/check.rs index 7193a00950e28..8eecafa8fa43a 100644 --- a/src/libsyntax/ext/pipes/check.rs +++ b/src/libsyntax/ext/pipes/check.rs @@ -29,9 +29,10 @@ that. */ +use ast; use ext::base::ext_ctxt; - use ext::pipes::proto::{state, protocol, next_state}; +use ext::pipes::proto; impl ext_ctxt: proto::visitor<(), (), ()> { fn visit_proto(_proto: protocol, diff --git a/src/libsyntax/ext/pipes/liveness.rs b/src/libsyntax/ext/pipes/liveness.rs index 1323042eb6254..76749f6b2db83 100644 --- a/src/libsyntax/ext/pipes/liveness.rs +++ b/src/libsyntax/ext/pipes/liveness.rs @@ -37,6 +37,7 @@ updating the states using rule (2) until there are no changes. */ +use core::str; use std::bitv::{Bitv}; fn analyze(proto: protocol, _cx: ext_ctxt) { diff --git a/src/libsyntax/ext/pipes/mod.rs b/src/libsyntax/ext/pipes/mod.rs index 0a02bca88ca99..67b5c81ad2d82 100644 --- a/src/libsyntax/ext/pipes/mod.rs +++ b/src/libsyntax/ext/pipes/mod.rs @@ -43,14 +43,15 @@ FIXME (#3072) - This is still incomplete. */ +use ast; +use ast::tt_delim; use codemap::span; +use ext::base; use ext::base::ext_ctxt; -use ast::tt_delim; -use parse::lexer::{new_tt_reader, reader}; -use parse::parser::Parser; - use ext::pipes::parse_proto::proto_parser; use ext::pipes::proto::{visit, protocol}; +use parse::lexer::{new_tt_reader, reader}; +use parse::parser::Parser; #[legacy_exports] mod ast_builder; diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index c07170e5c3640..ef9c086e3f5c4 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -10,18 +10,19 @@ // A protocol compiler for Rust. -use to_str::ToStr; - -use dvec::DVec; - use ast::ident; use ast_util::dummy_sp; -use util::interner; use ext::base::ext_ctxt; -use parse::*; +use ext::pipes::ast_builder::{append_types, path, path_global}; use ext::pipes::proto::*; use ext::quote::rt::*; -use ext::pipes::ast_builder::{append_types, path}; +use parse::*; +use util::interner; + +use core::dvec::DVec; +use core::str; +use core::to_str::ToStr; +use core::vec; trait gen_send { fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item; @@ -59,13 +60,14 @@ impl message: gen_send { let pipe_ty = cx.ty_path_ast_builder( path(~[this.data_name()], span) - .add_tys(cx.ty_vars(this.ty_params))); + .add_tys(cx.ty_vars_global(this.ty_params))); let args_ast = vec::append( ~[cx.arg(cx.ident_of(~"pipe"), pipe_ty)], args_ast); let mut body = ~"{\n"; + body += fmt!("use super::%s;\n", self.name()); if this.proto.is_bounded() { let (sp, rp) = match (this.dir, next.dir) { @@ -76,11 +78,11 @@ impl message: gen_send { }; body += ~"let b = pipe.reuse_buffer();\n"; - body += fmt!("let %s = pipes::SendPacketBuffered(\ - ptr::addr_of(&(b.buffer.data.%s)));\n", + body += fmt!("let %s = ::pipes::SendPacketBuffered(\ + ::ptr::addr_of(&(b.buffer.data.%s)));\n", sp, next.name); - body += fmt!("let %s = pipes::RecvPacketBuffered(\ - ptr::addr_of(&(b.buffer.data.%s)));\n", + body += fmt!("let %s = ::pipes::RecvPacketBuffered(\ + ::ptr::addr_of(&(b.buffer.data.%s)));\n", rp, next.name); } else { @@ -91,24 +93,23 @@ impl message: gen_send { (recv, recv) => "(move c, move s)" }; - body += fmt!("let %s = pipes::entangle();\n", pat); + body += fmt!("let %s = ::pipes::entangle();\n", pat); } - body += fmt!("let message = %s::%s(%s);\n", - this.proto.name, + body += fmt!("let message = %s(%s);\n", self.name(), str::connect(vec::append_one( arg_names.map(|x| ~"move " + cx.str_of(*x)), ~"move s"), ~", ")); if !try { - body += fmt!("pipes::send(move pipe, move message);\n"); + body += fmt!("::pipes::send(move pipe, move message);\n"); // return the new channel body += ~"move c }"; } else { - body += fmt!("if pipes::send(move pipe, move message) {\n \ - pipes::rt::make_some(move c) \ - } else { pipes::rt::make_none() } }"); + body += fmt!("if ::pipes::send(move pipe, move message) {\n \ + ::pipes::rt::make_some(move c) \ + } else { ::pipes::rt::make_none() } }"); } let body = cx.parse_expr(body); @@ -142,7 +143,8 @@ impl message: gen_send { ~[cx.arg(cx.ident_of(~"pipe"), cx.ty_path_ast_builder( path(~[this.data_name()], span) - .add_tys(cx.ty_vars(this.ty_params))))], + .add_tys(cx.ty_vars_global( + this.ty_params))))], args_ast); let message_args = if arg_names.len() == 0 { @@ -154,18 +156,21 @@ impl message: gen_send { }; let mut body = ~"{ "; - body += fmt!("let message = %s::%s%s;\n", - this.proto.name, + body += fmt!("use super::%s;\n", self.name()); + body += fmt!("let message = %s%s;\n", self.name(), message_args); if !try { - body += fmt!("pipes::send(move pipe, move message);\n"); + body += fmt!("::pipes::send(move pipe, move message);\n"); body += ~" }"; } else { - body += fmt!("if pipes::send(move pipe, move message) { \ - pipes::rt::make_some(()) \ - } else { pipes::rt::make_none() } }"); + body += fmt!("if ::pipes::send(move pipe, move message) \ + { \ + ::pipes::rt::make_some(()) \ + } else { \ + ::pipes::rt::make_none() \ + } }"); } let body = cx.parse_expr(body); @@ -190,7 +195,7 @@ impl message: gen_send { 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()))) + .add_tys(cx.ty_vars_global(self.get_params()))) } } @@ -261,14 +266,14 @@ impl state: to_type_decls { self.data_name(), self.span, cx.ty_path_ast_builder( - path(~[cx.ident_of(~"pipes"), - cx.ident_of(dir.to_str() + ~"Packet")], + path_global(~[cx.ident_of(~"pipes"), + cx.ident_of(dir.to_str() + ~"Packet")], dummy_sp()) .add_ty(cx.ty_path_ast_builder( - path(~[cx.ident_of(self.proto.name), + path(~[cx.ident_of(~"super"), self.data_name()], dummy_sp()) - .add_tys(cx.ty_vars(self.ty_params))))), + .add_tys(cx.ty_vars_global(self.ty_params))))), self.ty_params)); } else { @@ -277,15 +282,15 @@ impl state: to_type_decls { self.data_name(), self.span, cx.ty_path_ast_builder( - path(~[cx.ident_of(~"pipes"), - cx.ident_of(dir.to_str() - + ~"PacketBuffered")], + path_global(~[cx.ident_of(~"pipes"), + cx.ident_of(dir.to_str() + + ~"PacketBuffered")], dummy_sp()) .add_tys(~[cx.ty_path_ast_builder( - path(~[cx.ident_of(self.proto.name), + path(~[cx.ident_of(~"super"), self.data_name()], - dummy_sp()) - .add_tys(cx.ty_vars(self.ty_params))), + dummy_sp()) + .add_tys(cx.ty_vars_global(self.ty_params))), self.proto.buffer_ty_path(cx)])), self.ty_params)); }; @@ -303,10 +308,10 @@ impl protocol: gen_init { let body = if !self.is_bounded() { match start_state.dir { - send => quote_expr!( pipes::entangle() ), + send => quote_expr!( ::pipes::entangle() ), recv => { quote_expr!({ - let (s, c) = pipes::entangle(); + let (s, c) = ::pipes::entangle(); (move c, move s) }) } @@ -338,7 +343,7 @@ impl protocol: gen_init { let fty = s.to_ty(ext_cx); ext_cx.field_imm(ext_cx.ident_of(s.name), quote_expr!( - pipes::mk_packet::<$fty>() + ::pipes::mk_packet::<$fty>() )) })) } @@ -347,7 +352,7 @@ impl protocol: gen_init { debug!("gen_init_bounded"); let buffer_fields = self.gen_buffer_init(ext_cx); let buffer = quote_expr!( - ~{header: pipes::BufferHeader(), + ~{header: ::pipes::BufferHeader(), data: $buffer_fields} ); @@ -358,12 +363,12 @@ impl protocol: gen_init { fmt!("data.%s.set_buffer_(buffer)", s.name))), ext_cx.parse_expr( - fmt!("ptr::addr_of(&(data.%s))", + fmt!("::ptr::addr_of(&(data.%s))", self.states[0].name)))); quote_expr!({ let buffer = $buffer; - do pipes::entangle_buffer(move buffer) |buffer, data| { + do ::pipes::entangle_buffer(move buffer) |buffer, data| { $entangle_body } }) @@ -381,7 +386,7 @@ impl protocol: gen_init { } cx.ty_path_ast_builder(path(~[cx.ident_of(~"__Buffer")], self.span) - .add_tys(cx.ty_vars(params))) + .add_tys(cx.ty_vars_global(params))) } fn gen_buffer_type(cx: ext_ctxt) -> @ast::item { @@ -395,7 +400,7 @@ impl protocol: gen_init { } } let ty = s.to_ty(cx); - let fty = quote_ty!( pipes::Packet<$ty> ); + let fty = quote_ty!( ::pipes::Packet<$ty> ); cx.ty_field_imm(cx.ident_of(s.name), fty) }; diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index b00a2aab69f13..a2673c481b11c 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use to_str::ToStr; -use dvec::DVec; - +use ast; use ext::pipes::ast_builder::{path, append_types}; +use core::cmp; +use core::dvec::DVec; +use core::to_str::ToStr; + enum direction { send, recv } impl direction : cmp::Eq { diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index c498c3407c28a..184093715c691 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -8,12 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use mod ast; -use mod parse::token; - +use ast; +use attr; use codemap::{span, BytePos}; use ext::base::ext_ctxt; +use ext::base; +use ext::build; use parse::token::*; +use parse::token; +use parse; + +use core::str; /** * @@ -27,6 +32,12 @@ use parse::token::*; */ pub mod rt { + use ast; + use parse; + use print::pprust; + + use core::str; + pub use ast::*; pub use parse::token::*; pub use parse::new_parser_from_tts; @@ -577,15 +588,15 @@ fn expand_parse_call(cx: ext_ctxt, id_ext(cx, ~"parse_sess")), ~[]); let new_parser_call = - build::mk_call(cx, sp, - ids_ext(cx, ~[~"syntax", - ~"ext", - ~"quote", - ~"rt", - ~"new_parser_from_tts"]), - ~[parse_sess_call(), - cfg_call(), - tts_expr]); + build::mk_call_global(cx, sp, + ids_ext(cx, ~[~"syntax", + ~"ext", + ~"quote", + ~"rt", + ~"new_parser_from_tts"]), + ~[parse_sess_call(), + cfg_call(), + tts_expr]); build::mk_call_(cx, sp, build::mk_access_(cx, sp, new_parser_call, diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index e407431568966..47c6ea8876eb3 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -8,10 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ext::base::*; +use codemap; use codemap::{span, Loc, FileMap}; -use print::pprust; +use ext::base::*; +use ext::base; use ext::build::{mk_base_vec_e, mk_uint, mk_u8, mk_base_str}; +use print::pprust; + +use core::io; +use core::result; +use core::str; +use core::vec; export expand_line; export expand_col; diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index 6bf7437e15277..c202778d0df59 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use ast; use codemap::span; +use ext::base; use ext::base::ext_ctxt; use ast::tt_delim; use parse::lexer::{new_tt_reader, reader}; diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ad4677942accd..724e2fc9dba63 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -9,19 +9,25 @@ // except according to those terms. // Earley-like parser for macros. -use parse::token; -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; -//import parse::common::parser_common; -use parse::common::*; //resolve bug? -use parse::parse_sess; -use dvec::DVec; use ast::{matcher, match_tok, match_seq, match_nonterminal, ident}; use ast_util::mk_sp; -use std::map::HashMap; use codemap::BytePos; +use codemap; +use parse::common::*; //resolve bug? +use parse::lexer::*; //resolve bug? +use parse::parse_sess; +use parse::parser::Parser; +use parse::token::{Token, EOF, to_str, nonterminal}; +use parse::token; + +use core::dvec::DVec; +use core::dvec; +use core::io; +use core::option; +use core::str; +use core::uint; +use core::vec; +use std::map::HashMap; /* This is an Earley-like parser, without support for in-grammar nonterminals, only by calling out to the main rust parser for named nonterminals (which it @@ -239,7 +245,7 @@ fn parse(sess: parse_sess, cfg: ast::crate_cfg, rdr: reader, ms: ~[matcher]) /* at end of sequence */ if idx >= len { - // can't move out of `alt`s, so: + // can't move out of `match`es, so: if is_some(ei.up) { // hack: a matcher sequence is repeating iff it has a // parent (the top level is just a container) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index e93f3d6e38b24..7386b3b67b9f5 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -8,19 +8,24 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use ext::base::{ext_ctxt, mac_result, mr_any, mr_def, normal_tt}; +use ast::{ident, matcher_, matcher, match_tok, match_nonterminal, match_seq}; +use ast::{tt_delim}; +use ast; +use ast_util::dummy_sp; use codemap::span; -use ast::{ident, matcher_, matcher, match_tok, - match_nonterminal, match_seq, tt_delim}; +use ext::base::{ext_ctxt, mac_result, mr_any, mr_def, normal_tt}; +use ext::base; +use ext::tt::macro_parser::{error}; +use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; +use ext::tt::macro_parser::{parse, parse_or_else, success, failure}; use parse::lexer::{new_tt_reader, reader}; -use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt}; use parse::parser::Parser; -use ext::tt::macro_parser::{parse, parse_or_else, success, failure, - named_match, matched_seq, matched_nonterminal, - error}; -use std::map::HashMap; use parse::token::special_idents; -use ast_util::dummy_sp; +use parse::token::{FAT_ARROW, SEMI, LBRACE, RBRACE, nt_matchers, nt_tt}; +use print; + +use core::io; +use std::map::HashMap; fn add_new_extension(cx: ext_ctxt, sp: span, name: ident, arg: ~[ast::token_tree]) -> base::mac_result { diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index a68482ea46b36..c1745fac710ac 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -8,11 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use diagnostic::span_handler; +use ast; use ast::{token_tree, tt_delim, tt_tok, tt_seq, tt_nonterminal,ident}; -use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; +use ast_util; use codemap::span; +use diagnostic::span_handler; +use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal}; use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident, ident_interner}; + +use core::option; +use core::vec; +use std; use std::map::HashMap; export tt_reader, new_tt_reader, dup_tt_reader, tt_next_token; diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 0b1ff4f56eced..c6b4920920aa2 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use codemap::span; use ast::*; +use ast; +use codemap::span; + +use core::option; +use core::vec; -export ast_fold_precursor; +export ast_fold_fns; export ast_fold; export default_ast_fold; export make_fold; @@ -28,6 +32,7 @@ export fold_ty_param; export fold_ty_params; export fold_fn_decl; export extensions; +export AstFoldFns; trait ast_fold { fn fold_crate(crate) -> crate; @@ -57,7 +62,7 @@ trait ast_fold { // We may eventually want to be able to fold over type parameters, too -type ast_fold_precursor = @{ +struct AstFoldFns { //unlike the others, item_ is non-trivial fold_crate: fn@(crate_, span, ast_fold) -> (crate_, span), fold_view_item: fn@(view_item_, ast_fold) -> view_item_, @@ -81,7 +86,10 @@ type ast_fold_precursor = @{ fold_local: fn@(local_, span, ast_fold) -> (local_, span), map_exprs: fn@(fn@(&&v: @expr) -> @expr, ~[@expr]) -> ~[@expr], new_id: fn@(node_id) -> node_id, - new_span: fn@(span) -> span}; + new_span: fn@(span) -> span +} + +type ast_fold_fns = @AstFoldFns; /* some little folds that probably aren't useful to have in ast_fold itself*/ @@ -625,8 +633,8 @@ fn noop_id(i: node_id) -> node_id { return i; } fn noop_span(sp: span) -> span { return sp; } -fn default_ast_fold() -> ast_fold_precursor { - return @{fold_crate: wrap(noop_fold_crate), +fn default_ast_fold() -> ast_fold_fns { + return @AstFoldFns {fold_crate: wrap(noop_fold_crate), fold_view_item: noop_fold_view_item, fold_foreign_item: noop_fold_foreign_item, fold_item: noop_fold_item, @@ -651,7 +659,7 @@ fn default_ast_fold() -> ast_fold_precursor { new_span: noop_span}; } -impl ast_fold_precursor: ast_fold { +impl ast_fold_fns: ast_fold { /* naturally, a macro to write these would be nice */ fn fold_crate(c: crate) -> crate { let (n, s) = (self.fold_crate)(c.node, c.span, self as ast_fold); @@ -757,7 +765,7 @@ impl ast_fold { } } -fn make_fold(afp: ast_fold_precursor) -> ast_fold { +fn make_fold(afp: ast_fold_fns) -> ast_fold { afp as ast_fold } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index a4bef47fdf290..a3fd069afbb8d 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use either::{Either, Left, Right}; +use ast; use ast_util::spanned; use parse::common::*; //resolve bug? +use parse::token; + +use core::either::{Either, Left, Right}; export parser_attr; diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index 0ff5c296125f0..7f57c77783366 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -12,6 +12,7 @@ Predicates on exprs and stmts that the pretty-printer and parser use */ +use ast; use ast_util::operator_prec; fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool { diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 22b40736748b5..d5365d5904198 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -8,11 +8,22 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use io::ReaderUtil; +use ast; +use codemap::{CodeMap, FileMap, CharPos}; +use diagnostic; +use parse::lexer::{is_whitespace, get_str_from, reader}; +use parse::lexer::{string_reader, bump, is_eof, nextch}; +use parse::lexer; +use parse::token; +use parse; use util::interner; -use parse::lexer::{string_reader, bump, is_eof, nextch, - is_whitespace, get_str_from, reader}; -use codemap::{FileMap, CharPos}; + +use core::cmp; +use core::io::ReaderUtil; +use core::io; +use core::str; +use core::uint; +use core::vec; export cmnt; export lit; @@ -72,7 +83,7 @@ fn strip_doc_comment_decoration(comment: ~str) -> ~str { // drop leftmost columns that contain only values in chars fn block_trim(lines: ~[~str], chars: ~str, max: Option) -> ~[~str] { - let mut i = max.get_default(uint::max_value); + let mut i = max.get_or_default(uint::max_value); for lines.each |line| { if line.trim().is_empty() { loop; diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 246a8fa9c7c55..ca0bbbb7369a0 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -8,10 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::map::{HashMap}; +use ast; use ast_util::spanned; -use parse::parser::Parser; use parse::lexer::reader; +use parse::parser::Parser; +use parse::token; + +use core::option; +use std::map::HashMap; type seq_sep = { sep: Option, diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index c4e34311b8898..c51f7e4dad667 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -8,10 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use diagnostic::span_handler; +use ast; +use ast_util; use codemap::{span, CodeMap, CharPos, BytePos}; -use ext::tt::transcribe::{tt_reader, new_tt_reader, dup_tt_reader, - tt_next_token}; +use codemap; +use diagnostic::span_handler; +use ext::tt::transcribe::{tt_next_token}; +use ext::tt::transcribe::{tt_reader, new_tt_reader, dup_tt_reader}; +use parse::token; + +use core::char; +use core::either; +use core::str; +use core::u64; + +use std; export reader, string_reader, new_string_reader, is_whitespace; export tt_reader, new_tt_reader; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 803135f7599e2..fb5c62501791c 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -12,6 +12,20 @@ #[legacy_exports]; +use ast::node_id; +use ast; +use codemap::{span, CodeMap, FileMap, CharPos, BytePos}; +use codemap; +use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter}; +use parse::attr::parser_attr; +use parse::lexer::{reader, string_reader}; +use parse::parser::Parser; +use parse::token::{ident_interner, mk_ident_interner}; +use util::interner; + +use core::io; +use core::result; + export parser; export common; export lexer; @@ -36,15 +50,6 @@ export parse_stmt_from_source_str; export parse_tts_from_source_str; export parse_from_source_str; -use ast::node_id; -use codemap::{span, CodeMap, FileMap, CharPos, BytePos}; -use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter}; -use parse::attr::parser_attr; -use parse::lexer::{reader, string_reader}; -use parse::parser::Parser; -use parse::token::{ident_interner, mk_ident_interner}; -use util::interner; - #[legacy_exports] mod lexer; diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 3db635f3b431d..6b73cf308a247 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -17,10 +17,17 @@ Obsolete syntax that becomes too hard to parse can be removed. */ -use codemap::span; use ast::{expr, expr_lit, lit_nil}; +use ast; use ast_util::{respan}; +use codemap::span; use parse::token::Token; +use parse::token; + +use core::cmp; +use core::option; +use core::str; +use core::to_bytes; /// The specific types of unsupported syntax pub enum ObsoleteSyntax { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2b83404e065e2..f32a782622a1f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8,76 +8,79 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use print::pprust::expr_to_str; - -use result::Result; -use either::{Either, Left, Right}; -use std::map::HashMap; -use parse::token::{can_begin_expr, is_ident, is_ident_or_path, is_plain_ident, - INTERPOLATED, special_idents}; -use codemap::{span,FssNone, BytePos}; -use util::interner::Interner; +use ast::{ProtoBox, ProtoUniq, provided, public, pure_fn, purity, re_static}; +use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer}; +use ast::{bind_by_value, bind_by_move, bitand, bitor, bitxor, blk}; +use ast::{blk_check_mode, box, by_copy, by_move, by_ref, by_val}; +use ast::{capture_clause, capture_item, crate, crate_cfg, decl, decl_item}; +use ast::{decl_local, default_blk, deref, div, enum_def, enum_variant_kind}; +use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again}; +use ast::{expr_assert, expr_assign, expr_assign_op, expr_binary, expr_block}; +use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body}; +use ast::{expr_fail, expr_field, expr_fn, expr_fn_block, expr_if, expr_index}; +use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac}; +use ast::{expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat}; +use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary}; +use ast::{expr_unary_move, expr_vec, expr_vstore, expr_vstore_mut_box}; +use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box}; +use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl}; +use ast::{expr_vstore_uniq, TyFn, Onceness, Once, Many}; +use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod}; +use ast::{ident, impure_fn, infer, inherited, item, item_, item_const}; +use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl}; +use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; +use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; +use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const}; +use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal}; +use ast::{match_seq, match_tok, method, mode, module_ns, mt, mul, mutability}; +use ast::{named_field, neg, noreturn, not, pat, pat_box, pat_enum, pat_ident}; +use ast::{pat_lit, pat_range, pat_rec, pat_region, pat_struct, pat_tup}; +use ast::{pat_uniq, pat_wild, path, private, Proto, ProtoBare, ProtoBorrowed}; +use ast::{re_self, re_anon, re_named, region, rem, required, ret_style}; +use ast::{return_val, self_ty, shl, shr, stmt, stmt_decl, stmt_expr}; +use ast::{stmt_semi, stmt_mac, struct_def, struct_field, struct_immutable}; +use ast::{struct_mutable, struct_variant_kind, subtract, sty_box, sty_by_ref}; +use ast::{sty_region, sty_static, sty_uniq, sty_value, token_tree}; +use ast::{trait_method, trait_ref, tt_delim, tt_seq, tt_tok, tt_nonterminal}; +use ast::{tuple_variant_kind, Ty, ty_, ty_bot, ty_box, ty_field, ty_fn}; +use ast::{ty_fixed_length_vec, type_value_ns, uniq, unnamed_field}; +use ast::{ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound}; +use ast::{ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec}; +use ast::{unsafe_blk, unsafe_fn, variant, view_item, view_item_}; +use ast::{view_item_export, view_item_import, view_item_use, view_path}; +use ast::{view_path_glob, view_path_list, view_path_simple, visibility}; +use ast::{vstore, vstore_box, vstore_fixed, vstore_slice, vstore_uniq}; +use ast; use ast_util::{spanned, respan, mk_sp, ident_to_path, operator_prec}; +use ast_util; +use classify; +use codemap::{span,FssNone, BytePos}; +use codemap; +use parse::attr::parser_attr; +use parse::common::{seq_sep_none, token_to_str}; +use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed}; use parse::lexer::reader; +use parse::obsolete::{ObsoleteClassTraits, ObsoleteModeInFnType}; +use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator}; +use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove}; +use parse::obsolete::{ObsoleteStructCtor, ObsoleteWith, ObsoleteClassMethod}; +use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds}; use parse::prec::{as_prec, token_to_binop}; -use parse::attr::parser_attr; -use parse::common::{seq_sep_trailing_disallowed, seq_sep_trailing_allowed, - seq_sep_none, token_to_str}; -use dvec::DVec; -use vec::{push}; -use parse::obsolete::{ - ObsoleteSyntax, - ObsoleteLowerCaseKindBounds, ObsoleteLet, - ObsoleteFieldTerminator, ObsoleteStructCtor, - ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits, - ObsoleteModeInFnType, ObsoleteMoveInit, ObsoleteBinaryMove, -}; -use ast::{_mod, add, arg, arm, attribute, - bind_by_ref, bind_infer, bind_by_value, bind_by_move, - bitand, bitor, bitxor, blk, blk_check_mode, box, by_copy, - by_move, by_ref, by_val, capture_clause, - capture_item, struct_immutable, struct_mutable, - crate, crate_cfg, decl, decl_item, decl_local, - default_blk, deref, div, enum_def, enum_variant_kind, expl, expr, - expr_, expr_addr_of, expr_match, expr_again, expr_assert, - expr_assign, expr_assign_op, expr_binary, expr_block, expr_break, - expr_call, expr_cast, expr_copy, expr_do_body, expr_fail, - expr_field, expr_fn, expr_fn_block, expr_if, expr_index, - expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac, - expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat, - expr_ret, expr_swap, expr_struct, expr_tup, expr_unary, - expr_unary_move, expr_vec, expr_vstore, expr_vstore_mut_box, - expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl, - foreign_item, foreign_item_const, foreign_item_fn, foreign_mod, - ident, impure_fn, infer, inherited, - item, item_, item_struct, item_const, item_enum, item_fn, - item_foreign_mod, item_impl, item_mac, item_mod, item_trait, - item_ty, lit, lit_, lit_bool, lit_float, lit_float_unsuffixed, - lit_int, lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, - m_const, m_imm, m_mutbl, mac_, - mac_invoc_tt, matcher, match_nonterminal, match_seq, - match_tok, method, mode, module_ns, mt, mul, mutability, - named_field, neg, noreturn, not, pat, pat_box, pat_enum, - pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct, - pat_tup, pat_uniq, pat_wild, path, private, Proto, ProtoBare, - ProtoBorrowed, ProtoBox, ProtoUniq, provided, public, pure_fn, - purity, re_static, re_self, re_anon, re_named, region, - rem, required, ret_style, return_val, self_ty, shl, shr, stmt, - stmt_decl, stmt_expr, stmt_semi, stmt_mac, 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, - 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_vec, - type_value_ns, uniq, unnamed_field, unsafe_blk, unsafe_fn, - variant, view_item, view_item_, view_item_export, - view_item_import, view_item_use, view_path, view_path_glob, - view_path_list, view_path_simple, visibility, vstore, vstore_box, - vstore_fixed, vstore_slice, vstore_uniq, - expr_vstore_fixed, expr_vstore_slice, expr_vstore_box, - expr_vstore_uniq, TyFn, Onceness, Once, Many}; +use parse::token::{can_begin_expr, is_ident, is_ident_or_path}; +use parse::token::{is_plain_ident, INTERPOLATED, special_idents}; +use parse::token; +use print::pprust::expr_to_str; +use util::interner::Interner; + +use core::cmp; +use core::dvec::DVec; +use core::dvec; +use core::either::{Either, Left, Right}; +use core::either; +use core::result::Result; +use core::vec::push; +use core::vec; +use std::map::HashMap; export Parser; @@ -195,7 +198,7 @@ fn Parser(sess: parse_sess, cfg: ast::crate_cfg, keywords: token::keyword_table(), strict_keywords: token::strict_keyword_table(), reserved_keywords: token::reserved_keyword_table(), - obsolete_set: std::map::HashMap(), + obsolete_set: HashMap(), mod_path_stack: ~[], } } @@ -937,7 +940,7 @@ impl Parser { } else if self.eat_keyword(~"loop") { return self.parse_loop_expr(); } else if self.eat_keyword(~"match") { - return self.parse_alt_expr(); + return self.parse_match_expr(); } else if self.eat_keyword(~"fn") { let opt_proto = self.parse_fn_ty_proto(); let proto = match opt_proto { @@ -1719,7 +1722,7 @@ impl Parser { return expr_rec(fields, base); } - fn parse_alt_expr() -> @expr { + fn parse_match_expr() -> @expr { let lo = self.last_span.lo; let discriminant = self.parse_expr(); self.expect(token::LBRACE); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 04e6e187dbb22..f286b15c7523e 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -8,8 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use util::interner; +use ast; +use ast_util; +use parse::token; use util::interner::Interner; +use util::interner; + +use core::cast; +use core::char; +use core::cmp; +use core::str; +use core::task; use std::map::HashMap; #[auto_encode] @@ -332,7 +341,7 @@ mod special_idents { } struct ident_interner { - priv interner: util::interner::Interner<@~str>, + priv interner: Interner<@~str>, } impl ident_interner { diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index d90341254cc34..c9d2abfe0cba3 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -8,8 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use io::WriterUtil; -use dvec::DVec; +use core::cmp; +use core::dvec::DVec; +use core::io::WriterUtil; +use core::io; +use core::str; +use core::vec; /* * This pretty-printer is a direct reimplementation of Philip Karlton's diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3b995addd62b3..f392dd66f0ba1 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -8,16 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use parse::{comments, lexer, token}; -use codemap::{CodeMap, BytePos}; -use print::pp::{break_offset, word, printer, space, zerobreak, hardbreak}; -use print::pp::{breaks, consistent, inconsistent, eof}; use ast::{required, provided}; +use ast; +use ast_util; use ast_util::{operator_prec}; -use dvec::DVec; +use attr; +use codemap::{CodeMap, BytePos}; +use codemap; +use diagnostic; use parse::classify::*; use parse::token::ident_interner; -use str::{push_str, push_char}; +use parse::token; +use parse::{comments, lexer, token}; +use parse; +use print::pp::{break_offset, word, printer, space, zerobreak, hardbreak}; +use print::pp::{breaks, consistent, inconsistent, eof}; +use print::pp; +use print::pprust; + +use core::char; +use core::dvec::DVec; +use core::io; +use core::option; +use core::str::{push_str, push_char}; +use core::str; +use core::u64; +use core::vec; // The ps is stored here to prevent recursive type. enum ann_node { @@ -26,11 +42,14 @@ enum ann_node { node_expr(ps, @ast::expr), node_pat(ps, @ast::pat), } -type pp_ann = {pre: fn@(ann_node), post: fn@(ann_node)}; +struct pp_ann { + pre: fn@(ann_node), + post: fn@(ann_node) +} fn no_ann() -> pp_ann { fn ignore(_node: ann_node) { } - return {pre: ignore, post: ignore}; + return pp_ann {pre: ignore, post: ignore}; } type ps = @@ -67,7 +86,7 @@ fn rust_printer(writer: io::Writer, intr: @ident_interner) -> ps { } const indent_unit: uint = 4u; -const alt_indent_unit: uint = 2u; +const match_indent_unit: uint = 2u; const default_columns: uint = 78u; @@ -1235,7 +1254,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { print_block(s, (*blk)); } ast::expr_match(expr, ref arms) => { - cbox(s, alt_indent_unit); + cbox(s, match_indent_unit); ibox(s, 4); word_nbsp(s, ~"match"); print_expr(s, expr); @@ -1244,7 +1263,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { let len = (*arms).len(); for (*arms).eachi |i, arm| { space(s.s); - cbox(s, alt_indent_unit); + cbox(s, match_indent_unit); ibox(s, 0u); let mut first = true; for arm.pats.each |p| { @@ -1277,7 +1296,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { ast::expr_block(ref blk) => { // the block will close the pattern's ibox print_block_unclosed_indent( - s, (*blk), alt_indent_unit); + s, (*blk), match_indent_unit); } _ => { end(s); // close the ibox for the pattern @@ -1294,10 +1313,10 @@ fn print_expr(s: ps, &&expr: @ast::expr) { } } else { // the block will close the pattern's ibox - print_block_unclosed_indent(s, arm.body, alt_indent_unit); + print_block_unclosed_indent(s, arm.body, match_indent_unit); } } - bclose_(s, expr.span, alt_indent_unit); + bclose_(s, expr.span, match_indent_unit); } ast::expr_fn(proto, decl, ref body, cap_clause) => { // containing cbox, will be closed by print-block at } diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 687504b873e37..0777269f8f7fc 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -16,8 +16,6 @@ #[crate_type = "lib"]; -#[no_core]; - #[legacy_modes]; #[legacy_exports]; @@ -26,11 +24,13 @@ #[allow(deprecated_mode)]; #[warn(deprecated_pattern)]; -extern mod core(vers = "0.6"); -extern mod std(vers = "0.6"); +#[no_core]; +extern mod core(vers = "0.6"); use core::*; +extern mod std(vers = "0.6"); + pub mod syntax { pub use ext; pub use parse; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9a47edfeb05a6..d668e6c274fce 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -8,9 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use ast::*; +use ast; +use ast_util; use codemap::span; +use parse; + +use core::option; +use core::vec; // Context-passing AST walker. Each overridden visit method has full control // over what happens with its node, it can do its own traversal of the node's @@ -52,51 +57,56 @@ fn tps_of_fn(fk: fn_kind) -> ~[ty_param] { } } -type visitor = - @{visit_mod: fn@(_mod, span, node_id, E, vt), - visit_view_item: fn@(@view_item, E, vt), - visit_foreign_item: fn@(@foreign_item, E, vt), - visit_item: fn@(@item, E, vt), - visit_local: fn@(@local, E, vt), - visit_block: fn@(ast::blk, E, vt), - visit_stmt: fn@(@stmt, E, vt), - visit_arm: fn@(arm, E, vt), - visit_pat: fn@(@pat, E, vt), - 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_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), - visit_trait_method: fn@(trait_method, E, vt), - visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E, - vt), - visit_struct_field: fn@(@struct_field, E, vt), - visit_struct_method: fn@(@method, E, vt)}; +struct Visitor { + visit_mod: fn@(_mod, span, node_id, E, vt), + visit_view_item: fn@(@view_item, E, vt), + visit_foreign_item: fn@(@foreign_item, E, vt), + visit_item: fn@(@item, E, vt), + visit_local: fn@(@local, E, vt), + visit_block: fn@(ast::blk, E, vt), + visit_stmt: fn@(@stmt, E, vt), + visit_arm: fn@(arm, E, vt), + visit_pat: fn@(@pat, E, vt), + 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_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), + visit_trait_method: fn@(trait_method, E, vt), + visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id, E, + vt), + visit_struct_field: fn@(@struct_field, E, vt), + visit_struct_method: fn@(@method, E, vt) +} + +type visitor = @Visitor; fn default_visitor() -> visitor { - return @{visit_mod: |a,b,c,d,e|visit_mod::(a, b, c, d, e), - visit_view_item: |a,b,c|visit_view_item::(a, b, c), - visit_foreign_item: |a,b,c|visit_foreign_item::(a, b, c), - visit_item: |a,b,c|visit_item::(a, b, c), - visit_local: |a,b,c|visit_local::(a, b, c), - visit_block: |a,b,c|visit_block::(a, b, c), - visit_stmt: |a,b,c|visit_stmt::(a, b, c), - visit_arm: |a,b,c|visit_arm::(a, b, c), - visit_pat: |a,b,c|visit_pat::(a, b, c), - visit_decl: |a,b,c|visit_decl::(a, b, c), - visit_expr: |a,b,c|visit_expr::(a, b, c), - visit_expr_post: |_a,_b,_c| (), - visit_ty: |a,b,c|skip_ty::(a, b, c), - visit_ty_params: |a,b,c|visit_ty_params::(a, b, c), - visit_fn: |a,b,c,d,e,f,g|visit_fn::(a, b, c, d, e, f, g), - visit_ty_method: |a,b,c|visit_ty_method::(a, b, c), - visit_trait_method: |a,b,c|visit_trait_method::(a, b, c), - visit_struct_def: |a,b,c,d,e,f|visit_struct_def::(a, b, c, - d, e, f), - visit_struct_field: |a,b,c|visit_struct_field::(a, b, c), - visit_struct_method: |a,b,c|visit_struct_method::(a, b, c)}; + return @Visitor { + visit_mod: |a,b,c,d,e|visit_mod::(a, b, c, d, e), + visit_view_item: |a,b,c|visit_view_item::(a, b, c), + visit_foreign_item: |a,b,c|visit_foreign_item::(a, b, c), + visit_item: |a,b,c|visit_item::(a, b, c), + visit_local: |a,b,c|visit_local::(a, b, c), + visit_block: |a,b,c|visit_block::(a, b, c), + visit_stmt: |a,b,c|visit_stmt::(a, b, c), + visit_arm: |a,b,c|visit_arm::(a, b, c), + visit_pat: |a,b,c|visit_pat::(a, b, c), + visit_decl: |a,b,c|visit_decl::(a, b, c), + visit_expr: |a,b,c|visit_expr::(a, b, c), + visit_expr_post: |_a,_b,_c| (), + visit_ty: |a,b,c|skip_ty::(a, b, c), + visit_ty_params: |a,b,c|visit_ty_params::(a, b, c), + visit_fn: |a,b,c,d,e,f,g|visit_fn::(a, b, c, d, e, f, g), + visit_ty_method: |a,b,c|visit_ty_method::(a, b, c), + visit_trait_method: |a,b,c|visit_trait_method::(a, b, c), + visit_struct_def: |a,b,c,d,e,f|visit_struct_def::(a, b, c, + d, e, f), + visit_struct_field: |a,b,c|visit_struct_field::(a, b, c), + visit_struct_method: |a,b,c|visit_struct_method::(a, b, c) + }; } fn visit_crate(c: crate, e: E, v: vt) { @@ -492,43 +502,46 @@ fn visit_arm(a: arm, e: E, v: vt) { // Simpler, non-context passing interface. Always walks the whole tree, simply // calls the given functions on the nodes. -type simple_visitor = - @{visit_mod: fn@(_mod, span, node_id), - visit_view_item: fn@(@view_item), - visit_foreign_item: fn@(@foreign_item), - visit_item: fn@(@item), - visit_local: fn@(@local), - visit_block: fn@(ast::blk), - visit_stmt: fn@(@stmt), - visit_arm: fn@(arm), - visit_pat: fn@(@pat), - visit_decl: fn@(@decl), - visit_expr: fn@(@expr), - visit_expr_post: fn@(@expr), - 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), - visit_trait_method: fn@(trait_method), - visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id), - visit_struct_field: fn@(@struct_field), - visit_struct_method: fn@(@method)}; +struct SimpleVisitor { + visit_mod: fn@(_mod, span, node_id), + visit_view_item: fn@(@view_item), + visit_foreign_item: fn@(@foreign_item), + visit_item: fn@(@item), + visit_local: fn@(@local), + visit_block: fn@(ast::blk), + visit_stmt: fn@(@stmt), + visit_arm: fn@(arm), + visit_pat: fn@(@pat), + visit_decl: fn@(@decl), + visit_expr: fn@(@expr), + visit_expr_post: fn@(@expr), + 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), + visit_trait_method: fn@(trait_method), + visit_struct_def: fn@(@struct_def, ident, ~[ty_param], node_id), + visit_struct_field: fn@(@struct_field), + visit_struct_method: fn@(@method) +} + +type simple_visitor = @SimpleVisitor; fn simple_ignore_ty(_t: @Ty) {} -fn default_simple_visitor() -> simple_visitor { - return @{visit_mod: fn@(_m: _mod, _sp: span, _id: node_id) { }, - visit_view_item: fn@(_vi: @view_item) { }, - visit_foreign_item: fn@(_ni: @foreign_item) { }, - visit_item: fn@(_i: @item) { }, - visit_local: fn@(_l: @local) { }, - visit_block: fn@(_b: ast::blk) { }, - visit_stmt: fn@(_s: @stmt) { }, - visit_arm: fn@(_a: arm) { }, - visit_pat: fn@(_p: @pat) { }, - visit_decl: fn@(_d: @decl) { }, - visit_expr: fn@(_e: @expr) { }, - visit_expr_post: fn@(_e: @expr) { }, +fn default_simple_visitor() -> @SimpleVisitor { + return @SimpleVisitor {visit_mod: |_m: _mod, _sp: span, _id: node_id| { }, + visit_view_item: |_vi: @view_item| { }, + visit_foreign_item: |_ni: @foreign_item| { }, + visit_item: |_i: @item| { }, + visit_local: |_l: @local| { }, + visit_block: |_b: ast::blk| { }, + visit_stmt: |_s: @stmt| { }, + visit_arm: |_a: arm| { }, + visit_pat: |_p: @pat| { }, + visit_decl: |_d: @decl| { }, + visit_expr: |_e: @expr| { }, + visit_expr_post: |_e: @expr| { }, visit_ty: simple_ignore_ty, visit_ty_params: fn@(_ps: ~[ty_param]) {}, visit_fn: fn@(_fk: fn_kind, _d: fn_decl, _b: blk, _sp: span, @@ -633,37 +646,37 @@ fn mk_simple_visitor(v: simple_visitor) -> vt<()> { f(m); visit_struct_method(m, e, v); } - return mk_vt(@{visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e), - visit_view_item: |a,b,c| - v_view_item(v.visit_view_item, a, b, c), - visit_foreign_item: - |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c), - visit_item: |a,b,c|v_item(v.visit_item, a, b, c), - visit_local: |a,b,c|v_local(v.visit_local, a, b, c), - visit_block: |a,b,c|v_block(v.visit_block, a, b, c), - visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c), - visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c), - visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c), - visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c), - visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c), - visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post, - a, b, c), - visit_ty: visit_ty, - visit_ty_params: |a,b,c| - v_ty_params(v.visit_ty_params, a, b, c), - visit_fn: |a,b,c,d,e,f,g| - v_fn(v.visit_fn, a, b, c, d, e, f, g), - visit_ty_method: |a,b,c| - v_ty_method(v.visit_ty_method, a, b, c), - visit_trait_method: |a,b,c| - v_trait_method(v.visit_trait_method, a, b, c), - visit_struct_def: |a,b,c,d,e,f| - v_struct_def(v.visit_struct_def, a, b, c, d, e, f), - visit_struct_field: |a,b,c| - v_struct_field(v.visit_struct_field, a, b, c), - visit_struct_method: |a,b,c| - v_struct_method(v.visit_struct_method, a, b, c) - }); + return mk_vt(@Visitor { + visit_mod: |a,b,c,d,e|v_mod(v.visit_mod, a, b, c, d, e), + visit_view_item: |a,b,c| v_view_item(v.visit_view_item, a, b, c), + visit_foreign_item: + |a,b,c|v_foreign_item(v.visit_foreign_item, a, b, c), + visit_item: |a,b,c|v_item(v.visit_item, a, b, c), + visit_local: |a,b,c|v_local(v.visit_local, a, b, c), + visit_block: |a,b,c|v_block(v.visit_block, a, b, c), + visit_stmt: |a,b,c|v_stmt(v.visit_stmt, a, b, c), + visit_arm: |a,b,c|v_arm(v.visit_arm, a, b, c), + visit_pat: |a,b,c|v_pat(v.visit_pat, a, b, c), + visit_decl: |a,b,c|v_decl(v.visit_decl, a, b, c), + visit_expr: |a,b,c|v_expr(v.visit_expr, a, b, c), + visit_expr_post: |a,b,c| v_expr_post(v.visit_expr_post, + a, b, c), + visit_ty: visit_ty, + visit_ty_params: |a,b,c| + v_ty_params(v.visit_ty_params, a, b, c), + visit_fn: |a,b,c,d,e,f,g| + v_fn(v.visit_fn, a, b, c, d, e, f, g), + visit_ty_method: |a,b,c| + v_ty_method(v.visit_ty_method, a, b, c), + visit_trait_method: |a,b,c| + v_trait_method(v.visit_trait_method, a, b, c), + visit_struct_def: |a,b,c,d,e,f| + v_struct_def(v.visit_struct_def, a, b, c, d, e, f), + visit_struct_field: |a,b,c| + v_struct_field(v.visit_struct_field, a, b, c), + visit_struct_method: |a,b,c| + v_struct_method(v.visit_struct_method, a, b, c) + }); } // Local Variables: diff --git a/src/rt/bigint/bigint.h b/src/rt/bigint/bigint.h deleted file mode 100644 index b4c48f0376c9f..0000000000000 --- a/src/rt/bigint/bigint.h +++ /dev/null @@ -1,294 +0,0 @@ -/* bigint.h - include file for bigint package -** -** This library lets you do math on arbitrarily large integers. It's -** pretty fast - compared with the multi-precision routines in the "bc" -** calculator program, these routines are between two and twelve times faster, -** except for division which is maybe half as fast. -** -** The calling convention is a little unusual. There's a basic problem -** with writing a math library in a language that doesn't do automatic -** garbage collection - what do you do about intermediate results? -** You'd like to be able to write code like this: -** -** d = bi_sqrt( bi_add( bi_multiply( x, x ), bi_multiply( y, y ) ) ); -** -** That works fine when the numbers being passed back and forth are -** actual values - ints, floats, or even fixed-size structs. However, -** when the numbers can be any size, as in this package, then you have -** to pass them around as pointers to dynamically-allocated objects. -** Those objects have to get de-allocated after you are done with them. -** But how do you de-allocate the intermediate results in a complicated -** multiple-call expression like the above? -** -** There are two common solutions to this problem. One, switch all your -** code to a language that provides automatic garbage collection, for -** example Java. This is a fine idea and I recommend you do it wherever -** it's feasible. Two, change your routines to use a calling convention -** that prevents people from writing multiple-call expressions like that. -** The resulting code will be somewhat clumsy-looking, but it will work -** just fine. -** -** This package uses a third method, which I haven't seen used anywhere -** before. It's simple: each number can be used precisely once, after -** which it is automatically de-allocated. This handles the anonymous -** intermediate values perfectly. Named values still need to be copied -** and freed explicitly. Here's the above example using this convention: -** -** d = bi_sqrt( bi_add( -** bi_multiply( bi_copy( x ), bi_copy( x ) ), -** bi_multiply( bi_copy( y ), bi_copy( y ) ) ) ); -** bi_free( x ); -** bi_free( y ); -** -** Or, since the package contains a square routine, you could just write: -** -** d = bi_sqrt( bi_add( bi_square( x ), bi_square( y ) ) ); -** -** This time the named values are only being used once, so you don't -** have to copy and free them. -** -** This really works, however you do have to be very careful when writing -** your code. If you leave out a bi_copy() and use a value more than once, -** you'll get a runtime error about "zero refs" and a SIGFPE. Run your -** code in a debugger, get a backtrace to see where the call was, and then -** eyeball the code there to see where you need to add the bi_copy(). -** -** -** Copyright � 2000 by Jef Poskanzer . -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. -*/ - - -/* Type definition for bigints - it's an opaque type, the real definition -** is in bigint.c. -*/ -typedef void* bigint; - - -/* Some convenient pre-initialized numbers. These are all permanent, -** so you can use them as many times as you want without calling bi_copy(). -*/ -extern bigint bi_0, bi_1, bi_2, bi_10, bi_m1, bi_maxint, bi_minint; - - -/* Initialize the bigint package. You must call this when your program -** starts up. -*/ -void bi_initialize( void ); - -/* Shut down the bigint package. You should call this when your program -** exits. It's not actually required, but it does do some consistency -** checks which help keep your program bug-free, so you really ought -** to call it. -*/ -void bi_terminate( void ); - -/* Run in unsafe mode, skipping most runtime checks. Slightly faster. -** Once your code is debugged you can add this call after bi_initialize(). -*/ -void bi_no_check( void ); - -/* Make a copy of a bigint. You must call this if you want to use a -** bigint more than once. (Or you can make the bigint permanent.) -** Note that this routine is very cheap - all it actually does is -** increment a reference counter. -*/ -bigint bi_copy( bigint bi ); - -/* Make a bigint permanent, so it doesn't get automatically freed when -** used as an operand. -*/ -void bi_permanent( bigint bi ); - -/* Undo bi_permanent(). The next use will free the bigint. */ -void bi_depermanent( bigint bi ); - -/* Explicitly free a bigint. Normally bigints get freed automatically -** when they are used as an operand. This routine lets you free one -** without using it. If the bigint is permanent, this doesn't do -** anything, you have to depermanent it first. -*/ -void bi_free( bigint bi ); - -/* Compare two bigints. Returns -1, 0, or 1. */ -int bi_compare( bigint bia, bigint bib ); - -/* Convert an int to a bigint. */ -bigint int_to_bi( int i ); - -/* Convert a string to a bigint. */ -bigint str_to_bi( char* str ); - -/* Convert a bigint to an int. SIGFPE on overflow. */ -int bi_to_int( bigint bi ); - -/* Write a bigint to a file. */ -void bi_print( FILE* f, bigint bi ); - -/* Read a bigint from a file. */ -bigint bi_scan( FILE* f ); - - -/* Operations on a bigint and a regular int. */ - -/* Add an int to a bigint. */ -bigint bi_int_add( bigint bi, int i ); - -/* Subtract an int from a bigint. */ -bigint bi_int_subtract( bigint bi, int i ); - -/* Multiply a bigint by an int. */ -bigint bi_int_multiply( bigint bi, int i ); - -/* Divide a bigint by an int. SIGFPE on divide-by-zero. */ -bigint bi_int_divide( bigint binumer, int denom ); - -/* Take the remainder of a bigint by an int, with an int result. -** SIGFPE if m is zero. -*/ -int bi_int_rem( bigint bi, int m ); - -/* Take the modulus of a bigint by an int, with an int result. -** Note that mod is not rem: mod is always within [0..m), while -** rem can be negative. SIGFPE if m is zero or negative. -*/ -int bi_int_mod( bigint bi, int m ); - - -/* Basic operations on two bigints. */ - -/* Add two bigints. */ -bigint bi_add( bigint bia, bigint bib ); - -/* Subtract bib from bia. */ -bigint bi_subtract( bigint bia, bigint bib ); - -/* Multiply two bigints. */ -bigint bi_multiply( bigint bia, bigint bib ); - -/* Divide one bigint by another. SIGFPE on divide-by-zero. */ -bigint bi_divide( bigint binumer, bigint bidenom ); - -/* Binary division of one bigint by another. SIGFPE on divide-by-zero. -** This is here just for testing. It's about five times slower than -** regular division. -*/ -bigint bi_binary_divide( bigint binumer, bigint bidenom ); - -/* Take the remainder of one bigint by another. SIGFPE if bim is zero. */ -bigint bi_rem( bigint bia, bigint bim ); - -/* Take the modulus of one bigint by another. Note that mod is not rem: -** mod is always within [0..bim), while rem can be negative. SIGFPE if -** bim is zero or negative. -*/ -bigint bi_mod( bigint bia, bigint bim ); - - -/* Some less common operations. */ - -/* Negate a bigint. */ -bigint bi_negate( bigint bi ); - -/* Absolute value of a bigint. */ -bigint bi_abs( bigint bi ); - -/* Divide a bigint in half. */ -bigint bi_half( bigint bi ); - -/* Multiply a bigint by two. */ -bigint bi_double( bigint bi ); - -/* Square a bigint. */ -bigint bi_square( bigint bi ); - -/* Raise bi to the power of biexp. SIGFPE if biexp is negative. */ -bigint bi_power( bigint bi, bigint biexp ); - -/* Integer square root. */ -bigint bi_sqrt( bigint bi ); - -/* Factorial. */ -bigint bi_factorial( bigint bi ); - - -/* Some predicates. */ - -/* 1 if the bigint is odd, 0 if it's even. */ -int bi_is_odd( bigint bi ); - -/* 1 if the bigint is even, 0 if it's odd. */ -int bi_is_even( bigint bi ); - -/* 1 if the bigint equals zero, 0 if it's nonzero. */ -int bi_is_zero( bigint bi ); - -/* 1 if the bigint equals one, 0 otherwise. */ -int bi_is_one( bigint bi ); - -/* 1 if the bigint is less than zero, 0 if it's zero or greater. */ -int bi_is_negative( bigint bi ); - - -/* Now we get into the esoteric number-theory stuff used for cryptography. */ - -/* Modular exponentiation. Much faster than bi_mod(bi_power(bi,biexp),bim). -** Also, biexp can be negative. -*/ -bigint bi_mod_power( bigint bi, bigint biexp, bigint bim ); - -/* Modular inverse. mod( bi * modinv(bi), bim ) == 1. SIGFPE if bi is not -** relatively prime to bim. -*/ -bigint bi_mod_inverse( bigint bi, bigint bim ); - -/* Produce a random number in the half-open interval [0..bi). You need -** to have called srandom() before using this. -*/ -bigint bi_random( bigint bi ); - -/* Greatest common divisor of two bigints. Euclid's algorithm. */ -bigint bi_gcd( bigint bim, bigint bin ); - -/* Greatest common divisor of two bigints, plus the corresponding multipliers. -** Extended Euclid's algorithm. -*/ -bigint bi_egcd( bigint bim, bigint bin, bigint* bim_mul, bigint* bin_mul ); - -/* Least common multiple of two bigints. */ -bigint bi_lcm( bigint bia, bigint bib ); - -/* The Jacobi symbol. SIGFPE if bib is even. */ -bigint bi_jacobi( bigint bia, bigint bib ); - -/* Probabalistic prime checking. A non-zero return means the probability -** that bi is prime is at least 1 - 1/2 ^ certainty. -*/ -int bi_is_probable_prime( bigint bi, int certainty ); - -/* Random probabilistic prime with the specified number of bits. */ -bigint bi_generate_prime( int bits, int certainty ); - -/* Number of bits in the number. The log base 2, approximately. */ -int bi_bits( bigint bi ); diff --git a/src/rt/bigint/bigint_ext.cpp b/src/rt/bigint/bigint_ext.cpp deleted file mode 100644 index 66d79106f48d4..0000000000000 --- a/src/rt/bigint/bigint_ext.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* bigint_ext - external portion of large integer package -** -** Copyright � 2000 by Jef Poskanzer . -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include - -#include "bigint.h" -#include "low_primes.h" - - -bigint bi_0, bi_1, bi_2, bi_10, bi_m1, bi_maxint, bi_minint; - - -/* Forwards. */ -static void print_pos( FILE* f, bigint bi ); - - -bigint -str_to_bi( char* str ) - { - int sign; - bigint biR; - - sign = 1; - if ( *str == '-' ) - { - sign = -1; - ++str; - } - for ( biR = bi_0; *str >= '0' && *str <= '9'; ++str ) - biR = bi_int_add( bi_int_multiply( biR, 10 ), *str - '0' ); - if ( sign == -1 ) - biR = bi_negate( biR ); - return biR; - } - - -void -bi_print( FILE* f, bigint bi ) - { - if ( bi_is_negative( bi_copy( bi ) ) ) - { - putc( '-', f ); - bi = bi_negate( bi ); - } - print_pos( f, bi ); - } - - -bigint -bi_scan( FILE* f ) - { - int sign; - int c; - bigint biR; - - sign = 1; - c = getc( f ); - if ( c == '-' ) - sign = -1; - else - ungetc( c, f ); - - biR = bi_0; - for (;;) - { - c = getc( f ); - if ( c < '0' || c > '9' ) - break; - biR = bi_int_add( bi_int_multiply( biR, 10 ), c - '0' ); - } - - if ( sign == -1 ) - biR = bi_negate( biR ); - return biR; - } - - -static void -print_pos( FILE* f, bigint bi ) - { - if ( bi_compare( bi_copy( bi ), bi_10 ) >= 0 ) - print_pos( f, bi_int_divide( bi_copy( bi ), 10 ) ); - putc( bi_int_mod( bi, 10 ) + '0', f ); - } - - -int -bi_int_mod( bigint bi, int m ) - { - int r; - - if ( m <= 0 ) - { - (void) fprintf( stderr, "bi_int_mod: zero or negative modulus\n" ); - (void) kill( getpid(), SIGFPE ); - } - r = bi_int_rem( bi, m ); - if ( r < 0 ) - r += m; - return r; - } - - -bigint -bi_rem( bigint bia, bigint bim ) - { - return bi_subtract( - bia, bi_multiply( bi_divide( bi_copy( bia ), bi_copy( bim ) ), bim ) ); - } - - -bigint -bi_mod( bigint bia, bigint bim ) - { - bigint biR; - - if ( bi_compare( bi_copy( bim ), bi_0 ) <= 0 ) - { - (void) fprintf( stderr, "bi_mod: zero or negative modulus\n" ); - (void) kill( getpid(), SIGFPE ); - } - biR = bi_rem( bia, bi_copy( bim ) ); - if ( bi_is_negative( bi_copy( biR ) ) ) - biR = bi_add( biR, bim ); - else - bi_free( bim ); - return biR; - } - - -bigint -bi_square( bigint bi ) - { - bigint biR; - - biR = bi_multiply( bi_copy( bi ), bi_copy( bi ) ); - bi_free( bi ); - return biR; - } - - -bigint -bi_power( bigint bi, bigint biexp ) - { - bigint biR; - - if ( bi_is_negative( bi_copy( biexp ) ) ) - { - (void) fprintf( stderr, "bi_power: negative exponent\n" ); - (void) kill( getpid(), SIGFPE ); - } - biR = bi_1; - for (;;) - { - if ( bi_is_odd( bi_copy( biexp ) ) ) - biR = bi_multiply( biR, bi_copy( bi ) ); - biexp = bi_half( biexp ); - if ( bi_compare( bi_copy( biexp ), bi_0 ) <= 0 ) - break; - bi = bi_multiply( bi_copy( bi ), bi ); - } - bi_free( bi ); - bi_free( biexp ); - return biR; - } - - -bigint -bi_factorial( bigint bi ) - { - bigint biR; - - biR = bi_1; - while ( bi_compare( bi_copy( bi ), bi_1 ) > 0 ) - { - biR = bi_multiply( biR, bi_copy( bi ) ); - bi = bi_int_subtract( bi, 1 ); - } - bi_free( bi ); - return biR; - } - - -int -bi_is_even( bigint bi ) - { - return ! bi_is_odd( bi ); - } - - -bigint -bi_mod_power( bigint bi, bigint biexp, bigint bim ) - { - int invert; - bigint biR; - - invert = 0; - if ( bi_is_negative( bi_copy( biexp ) ) ) - { - biexp = bi_negate( biexp ); - invert = 1; - } - - biR = bi_1; - for (;;) - { - if ( bi_is_odd( bi_copy( biexp ) ) ) - biR = bi_mod( bi_multiply( biR, bi_copy( bi ) ), bi_copy( bim ) ); - biexp = bi_half( biexp ); - if ( bi_compare( bi_copy( biexp ), bi_0 ) <= 0 ) - break; - bi = bi_mod( bi_multiply( bi_copy( bi ), bi ), bi_copy( bim ) ); - } - bi_free( bi ); - bi_free( biexp ); - - if ( invert ) - biR = bi_mod_inverse( biR, bim ); - else - bi_free( bim ); - return biR; - } - - -bigint -bi_mod_inverse( bigint bi, bigint bim ) - { - bigint gcd, mul0, mul1; - - gcd = bi_egcd( bi_copy( bim ), bi, &mul0, &mul1 ); - - /* Did we get gcd == 1? */ - if ( ! bi_is_one( gcd ) ) - { - (void) fprintf( stderr, "bi_mod_inverse: not relatively prime\n" ); - (void) kill( getpid(), SIGFPE ); - } - - bi_free( mul0 ); - return bi_mod( mul1, bim ); - } - - -/* Euclid's algorithm. */ -bigint -bi_gcd( bigint bim, bigint bin ) - { - bigint bit; - - bim = bi_abs( bim ); - bin = bi_abs( bin ); - while ( ! bi_is_zero( bi_copy( bin ) ) ) - { - bit = bi_mod( bim, bi_copy( bin ) ); - bim = bin; - bin = bit; - } - bi_free( bin ); - return bim; - } - - -/* Extended Euclidean algorithm. */ -bigint -bi_egcd( bigint bim, bigint bin, bigint* bim_mul, bigint* bin_mul ) - { - bigint a0, b0, c0, a1, b1, c1, q, t; - - if ( bi_is_negative( bi_copy( bim ) ) ) - { - bigint biR; - - biR = bi_egcd( bi_negate( bim ), bin, &t, bin_mul ); - *bim_mul = bi_negate( t ); - return biR; - } - if ( bi_is_negative( bi_copy( bin ) ) ) - { - bigint biR; - - biR = bi_egcd( bim, bi_negate( bin ), bim_mul, &t ); - *bin_mul = bi_negate( t ); - return biR; - } - - a0 = bi_1; b0 = bi_0; c0 = bim; - a1 = bi_0; b1 = bi_1; c1 = bin; - - while ( ! bi_is_zero( bi_copy( c1 ) ) ) - { - q = bi_divide( bi_copy( c0 ), bi_copy( c1 ) ); - t = a0; - a0 = bi_copy( a1 ); - a1 = bi_subtract( t, bi_multiply( bi_copy( q ), a1 ) ); - t = b0; - b0 = bi_copy( b1 ); - b1 = bi_subtract( t, bi_multiply( bi_copy( q ), b1 ) ); - t = c0; - c0 = bi_copy( c1 ); - c1 = bi_subtract( t, bi_multiply( bi_copy( q ), c1 ) ); - bi_free( q ); - } - - bi_free( a1 ); - bi_free( b1 ); - bi_free( c1 ); - *bim_mul = a0; - *bin_mul = b0; - return c0; - } - - -bigint -bi_lcm( bigint bia, bigint bib ) - { - bigint biR; - - biR = bi_divide( - bi_multiply( bi_copy( bia ), bi_copy( bib ) ), - bi_gcd( bi_copy( bia ), bi_copy( bib ) ) ); - bi_free( bia ); - bi_free( bib ); - return biR; - } - - -/* The Jacobi symbol. */ -bigint -bi_jacobi( bigint bia, bigint bib ) - { - bigint biR; - - if ( bi_is_even( bi_copy( bib ) ) ) - { - (void) fprintf( stderr, "bi_jacobi: don't know how to compute Jacobi(n, even)\n" ); - (void) kill( getpid(), SIGFPE ); - } - - if ( bi_compare( bi_copy( bia ), bi_copy( bib ) ) >= 0 ) - return bi_jacobi( bi_mod( bia, bi_copy( bib ) ), bib ); - - if ( bi_is_zero( bi_copy( bia ) ) || bi_is_one( bi_copy( bia ) ) ) - { - bi_free( bib ); - return bia; - } - - if ( bi_compare( bi_copy( bia ), bi_2 ) == 0 ) - { - bi_free( bia ); - switch ( bi_int_mod( bib, 8 ) ) - { - case 1: case 7: - return bi_1; - case 3: case 5: - return bi_m1; - } - } - - if ( bi_is_even( bi_copy( bia ) ) ) - { - biR = bi_multiply( - bi_jacobi( bi_2, bi_copy( bib ) ), - bi_jacobi( bi_half( bia ), bi_copy( bib ) ) ); - bi_free( bib ); - return biR; - } - - if ( bi_int_mod( bi_copy( bia ), 4 ) == 3 && - bi_int_mod( bi_copy( bib ), 4 ) == 3 ) - return bi_negate( bi_jacobi( bib, bia ) ); - else - return bi_jacobi( bib, bia ); - } - - -/* Probabalistic prime checking. */ -int -bi_is_probable_prime( bigint bi, int certainty ) - { - int i, p; - bigint bim1; - - /* First do trial division by a list of small primes. This eliminates - ** many candidates. - */ - for ( i = 0; i < sizeof(low_primes)/sizeof(*low_primes); ++i ) - { - p = low_primes[i]; - switch ( bi_compare( int_to_bi( p ), bi_copy( bi ) ) ) - { - case 0: - bi_free( bi ); - return 1; - case 1: - bi_free( bi ); - return 0; - } - if ( bi_int_mod( bi_copy( bi ), p ) == 0 ) - { - bi_free( bi ); - return 0; - } - } - - /* Now do the probabilistic tests. */ - bim1 = bi_int_subtract( bi_copy( bi ), 1 ); - for ( i = 0; i < certainty; ++i ) - { - bigint a, j, jac; - - /* Pick random test number. */ - a = bi_random( bi_copy( bi ) ); - - /* Decide whether to run the Fermat test or the Solovay-Strassen - ** test. The Fermat test is fast but lets some composite numbers - ** through. Solovay-Strassen runs slower but is more certain. - ** So the compromise here is we run the Fermat test a couple of - ** times to quickly reject most composite numbers, and then do - ** the rest of the iterations with Solovay-Strassen so nothing - ** slips through. - */ - if ( i < 2 && certainty >= 5 ) - { - /* Fermat test. Note that this is not state of the art. There's a - ** class of numbers called Carmichael numbers which are composite - ** but look prime to this test - it lets them slip through no - ** matter how many reps you run. However, it's nice and fast so - ** we run it anyway to help quickly reject most of the composites. - */ - if ( ! bi_is_one( bi_mod_power( bi_copy( a ), bi_copy( bim1 ), bi_copy( bi ) ) ) ) - { - bi_free( bi ); - bi_free( bim1 ); - bi_free( a ); - return 0; - } - } - else - { - /* GCD test. This rarely hits, but we need it for Solovay-Strassen. */ - if ( ! bi_is_one( bi_gcd( bi_copy( bi ), bi_copy( a ) ) ) ) - { - bi_free( bi ); - bi_free( bim1 ); - bi_free( a ); - return 0; - } - - /* Solovay-Strassen test. First compute pseudo Jacobi. */ - j = bi_mod_power( - bi_copy( a ), bi_half( bi_copy( bim1 ) ), bi_copy( bi ) ); - if ( bi_compare( bi_copy( j ), bi_copy( bim1 ) ) == 0 ) - { - bi_free( j ); - j = bi_m1; - } - - /* Now compute real Jacobi. */ - jac = bi_jacobi( bi_copy( a ), bi_copy( bi ) ); - - /* If they're not equal, the number is definitely composite. */ - if ( bi_compare( j, jac ) != 0 ) - { - bi_free( bi ); - bi_free( bim1 ); - bi_free( a ); - return 0; - } - } - - bi_free( a ); - } - - bi_free( bim1 ); - - bi_free( bi ); - return 1; - } - - -bigint -bi_generate_prime( int bits, int certainty ) - { - bigint bimo2, bip; - int i, inc = 0; - - bimo2 = bi_power( bi_2, int_to_bi( bits - 1 ) ); - for (;;) - { - bip = bi_add( bi_random( bi_copy( bimo2 ) ), bi_copy( bimo2 ) ); - /* By shoving the candidate numbers up to the next highest multiple - ** of six plus or minus one, we pre-eliminate all multiples of - ** two and/or three. - */ - switch ( bi_int_mod( bi_copy( bip ), 6 ) ) - { - case 0: inc = 4; bip = bi_int_add( bip, 1 ); break; - case 1: inc = 4; break; - case 2: inc = 2; bip = bi_int_add( bip, 3 ); break; - case 3: inc = 2; bip = bi_int_add( bip, 2 ); break; - case 4: inc = 2; bip = bi_int_add( bip, 1 ); break; - case 5: inc = 2; break; - } - /* Starting from the generated random number, check a bunch of - ** numbers in sequence. This is just to avoid calls to bi_random(), - ** which is more expensive than a simple add. - */ - for ( i = 0; i < 1000; ++i ) /* arbitrary */ - { - if ( bi_is_probable_prime( bi_copy( bip ), certainty ) ) - { - bi_free( bimo2 ); - return bip; - } - bip = bi_int_add( bip, inc ); - inc = 6 - inc; - } - /* We ran through the whole sequence and didn't find a prime. - ** Shrug, just try a different random starting point. - */ - bi_free( bip ); - } - } diff --git a/src/rt/bigint/bigint_int.cpp b/src/rt/bigint/bigint_int.cpp deleted file mode 100644 index 194ddcb56002b..0000000000000 --- a/src/rt/bigint/bigint_int.cpp +++ /dev/null @@ -1,1428 +0,0 @@ -/* bigint - internal portion of large integer package -** -** Copyright � 2000 by Jef Poskanzer . -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. -*/ - -#include -#include -#include -#include -#include -#include - -#include "bigint.h" - -#define max(a,b) ((a)>(b)?(a):(b)) -#define min(a,b) ((a)<(b)?(a):(b)) - -/* MAXINT and MININT extracted from , which gives a warning -** message if included. -*/ -#define BITSPERBYTE 8 -#define BITS(type) (BITSPERBYTE * (int)sizeof(type)) -#define INTBITS BITS(int) -#define MININT (1 << (INTBITS - 1)) -#define MAXINT (~MININT) - - -/* The package represents arbitrary-precision integers as a sign and a sum -** of components multiplied by successive powers of the basic radix, i.e.: -** -** sign * ( comp0 + comp1 * radix + comp2 * radix^2 + comp3 * radix^3 ) -** -** To make good use of the computer's word size, the radix is chosen -** to be a power of two. It could be chosen to be the full word size, -** however this would require a lot of finagling in the middle of the -** algorithms to get the inter-word overflows right. That would slow things -** down. Instead, the radix is chosen to be *half* the actual word size. -** With just a little care, this means the words can hold all intermediate -** values, and the overflows can be handled all at once at the end, in a -** normalization step. This simplifies the coding enormously, and is probably -** somewhat faster to run. The cost is that numbers use twice as much -** storage as they would with the most efficient representation, but storage -** is cheap. -** -** A few more notes on the representation: -** -** - The sign is always 1 or -1, never 0. The number 0 is represented -** with a sign of 1. -** - The components are signed numbers, to allow for negative intermediate -** values. After normalization, all components are >= 0 and the sign is -** updated. -*/ - -/* Type definition for bigints. */ -typedef int64_t comp; /* should be the largest signed int type you have */ -struct _real_bigint { - int refs; - struct _real_bigint* next; - int num_comps, max_comps; - int sign; - comp* comps; - }; -typedef struct _real_bigint* real_bigint; - - -#undef DUMP - - -#define PERMANENT 123456789 - -static comp bi_radix, bi_radix_o2; -static int bi_radix_sqrt, bi_comp_bits; - -static real_bigint active_list, free_list; -static int active_count, free_count; -static int check_level; - - -/* Forwards. */ -static bigint regular_multiply( real_bigint bia, real_bigint bib ); -static bigint multi_divide( bigint binumer, real_bigint bidenom ); -static bigint multi_divide2( bigint binumer, real_bigint bidenom ); -static void more_comps( real_bigint bi, int n ); -static real_bigint alloc( int num_comps ); -static real_bigint clone( real_bigint bi ); -static void normalize( real_bigint bi ); -static void check( real_bigint bi ); -static void double_check( void ); -static void triple_check( void ); -#ifdef DUMP -static void dump( char* str, bigint bi ); -#endif /* DUMP */ -static int csqrt( comp c ); -static int cbits( comp c ); - - -void -bi_initialize( void ) - { - /* Set the radix. This does not actually have to be a power of - ** two, that's just the most efficient value. It does have to - ** be even for bi_half() to work. - */ - bi_radix = 1; - bi_radix <<= BITS(comp) / 2 - 1; - - /* Halve the radix. Only used by bi_half(). */ - bi_radix_o2 = bi_radix >> 1; - - /* Take the square root of the radix. Only used by bi_divide(). */ - bi_radix_sqrt = csqrt( bi_radix ); - - /* Figure out how many bits in a component. Only used by bi_bits(). */ - bi_comp_bits = cbits( bi_radix - 1 ); - - /* Init various globals. */ - active_list = (real_bigint) 0; - active_count = 0; - free_list = (real_bigint) 0; - free_count = 0; - - /* This can be 0 through 3. */ - check_level = 3; - - /* Set up some convenient bigints. */ - bi_0 = int_to_bi( 0 ); bi_permanent( bi_0 ); - bi_1 = int_to_bi( 1 ); bi_permanent( bi_1 ); - bi_2 = int_to_bi( 2 ); bi_permanent( bi_2 ); - bi_10 = int_to_bi( 10 ); bi_permanent( bi_10 ); - bi_m1 = int_to_bi( -1 ); bi_permanent( bi_m1 ); - bi_maxint = int_to_bi( MAXINT ); bi_permanent( bi_maxint ); - bi_minint = int_to_bi( MININT ); bi_permanent( bi_minint ); - } - - -void -bi_terminate( void ) - { - real_bigint p, pn; - - bi_depermanent( bi_0 ); bi_free( bi_0 ); - bi_depermanent( bi_1 ); bi_free( bi_1 ); - bi_depermanent( bi_2 ); bi_free( bi_2 ); - bi_depermanent( bi_10 ); bi_free( bi_10 ); - bi_depermanent( bi_m1 ); bi_free( bi_m1 ); - bi_depermanent( bi_maxint ); bi_free( bi_maxint ); - bi_depermanent( bi_minint ); bi_free( bi_minint ); - - if ( active_count != 0 ) - (void) fprintf( - stderr, "bi_terminate: there were %d un-freed bigints\n", - active_count ); - if ( check_level >= 2 ) - double_check(); - if ( check_level >= 3 ) - { - triple_check(); - for ( p = active_list; p != (bigint) 0; p = pn ) - { - pn = p->next; - free( p->comps ); - free( p ); - } - } - for ( p = free_list; p != (bigint) 0; p = pn ) - { - pn = p->next; - free( p->comps ); - free( p ); - } - } - - -void -bi_no_check( void ) - { - check_level = 0; - } - - -bigint -bi_copy( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - - check( bi ); - if ( bi->refs != PERMANENT ) - ++bi->refs; - return bi; - } - - -void -bi_permanent( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - - check( bi ); - if ( check_level >= 1 && bi->refs != 1 ) - { - (void) fprintf( stderr, "bi_permanent: refs was not 1\n" ); - (void) kill( getpid(), SIGFPE ); - } - bi->refs = PERMANENT; - } - - -void -bi_depermanent( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - - check( bi ); - if ( check_level >= 1 && bi->refs != PERMANENT ) - { - (void) fprintf( stderr, "bi_depermanent: bigint was not permanent\n" ); - (void) kill( getpid(), SIGFPE ); - } - bi->refs = 1; - } - - -void -bi_free( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - - check( bi ); - if ( bi->refs == PERMANENT ) - return; - --bi->refs; - if ( bi->refs > 0 ) - return; - if ( check_level >= 3 ) - { - /* The active list only gets maintained at check levels 3 or higher. */ - real_bigint* nextP; - for ( nextP = &active_list; *nextP != (real_bigint) 0; nextP = &((*nextP)->next) ) - if ( *nextP == bi ) - { - *nextP = bi->next; - break; - } - } - --active_count; - bi->next = free_list; - free_list = bi; - ++free_count; - if ( check_level >= 1 && active_count < 0 ) - { - (void) fprintf( stderr, - "bi_free: active_count went negative - double-freed bigint?\n" ); - (void) kill( getpid(), SIGFPE ); - } - } - - -int -bi_compare( bigint obia, bigint obib ) - { - real_bigint bia = (real_bigint) obia; - real_bigint bib = (real_bigint) obib; - int r, c; - - check( bia ); - check( bib ); - - /* First check for pointer equality. */ - if ( bia == bib ) - r = 0; - else - { - /* Compare signs. */ - if ( bia->sign > bib->sign ) - r = 1; - else if ( bia->sign < bib->sign ) - r = -1; - /* Signs are the same. Check the number of components. */ - else if ( bia->num_comps > bib->num_comps ) - r = bia->sign; - else if ( bia->num_comps < bib->num_comps ) - r = -bia->sign; - else - { - /* Same number of components. Compare starting from the high end - ** and working down. - */ - r = 0; /* if we complete the loop, the numbers are equal */ - for ( c = bia->num_comps - 1; c >= 0; --c ) - { - if ( bia->comps[c] > bib->comps[c] ) - { r = bia->sign; break; } - else if ( bia->comps[c] < bib->comps[c] ) - { r = -bia->sign; break; } - } - } - } - - bi_free( bia ); - bi_free( bib ); - return r; - } - - -bigint -int_to_bi( int i ) - { - real_bigint biR; - - biR = alloc( 1 ); - biR->sign = 1; - biR->comps[0] = i; - normalize( biR ); - check( biR ); - return biR; - } - - -int -bi_to_int( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - comp v, m; - int c, r; - - check( bi ); - if ( bi_compare( bi_copy( bi ), bi_maxint ) > 0 || - bi_compare( bi_copy( bi ), bi_minint ) < 0 ) - { - (void) fprintf( stderr, "bi_to_int: overflow\n" ); - (void) kill( getpid(), SIGFPE ); - } - v = 0; - m = 1; - for ( c = 0; c < bi->num_comps; ++c ) - { - v += bi->comps[c] * m; - m *= bi_radix; - } - r = (int) ( bi->sign * v ); - bi_free( bi ); - return r; - } - - -bigint -bi_int_add( bigint obi, int i ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - - check( bi ); - biR = clone( bi ); - if ( biR->sign == 1 ) - biR->comps[0] += i; - else - biR->comps[0] -= i; - normalize( biR ); - check( biR ); - return biR; - } - - -bigint -bi_int_subtract( bigint obi, int i ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - - check( bi ); - biR = clone( bi ); - if ( biR->sign == 1 ) - biR->comps[0] -= i; - else - biR->comps[0] += i; - normalize( biR ); - check( biR ); - return biR; - } - - -bigint -bi_int_multiply( bigint obi, int i ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - int c; - - check( bi ); - biR = clone( bi ); - if ( i < 0 ) - { - i = -i; - biR->sign = -biR->sign; - } - for ( c = 0; c < biR->num_comps; ++c ) - biR->comps[c] *= i; - normalize( biR ); - check( biR ); - return biR; - } - - -bigint -bi_int_divide( bigint obinumer, int denom ) - { - real_bigint binumer = (real_bigint) obinumer; - real_bigint biR; - int c; - comp r; - - check( binumer ); - if ( denom == 0 ) - { - (void) fprintf( stderr, "bi_int_divide: divide by zero\n" ); - (void) kill( getpid(), SIGFPE ); - } - biR = clone( binumer ); - if ( denom < 0 ) - { - denom = -denom; - biR->sign = -biR->sign; - } - r = 0; - for ( c = biR->num_comps - 1; c >= 0; --c ) - { - r = r * bi_radix + biR->comps[c]; - biR->comps[c] = r / denom; - r = r % denom; - } - normalize( biR ); - check( biR ); - return biR; - } - - -int -bi_int_rem( bigint obi, int m ) - { - real_bigint bi = (real_bigint) obi; - comp rad_r, r; - int c; - - check( bi ); - if ( m == 0 ) - { - (void) fprintf( stderr, "bi_int_rem: divide by zero\n" ); - (void) kill( getpid(), SIGFPE ); - } - if ( m < 0 ) - m = -m; - rad_r = 1; - r = 0; - for ( c = 0; c < bi->num_comps; ++c ) - { - r = ( r + bi->comps[c] * rad_r ) % m; - rad_r = ( rad_r * bi_radix ) % m; - } - if ( bi->sign < 1 ) - r = -r; - bi_free( bi ); - return (int) r; - } - - -bigint -bi_add( bigint obia, bigint obib ) - { - real_bigint bia = (real_bigint) obia; - real_bigint bib = (real_bigint) obib; - real_bigint biR; - int c; - - check( bia ); - check( bib ); - biR = clone( bia ); - more_comps( biR, max( biR->num_comps, bib->num_comps ) ); - for ( c = 0; c < bib->num_comps; ++c ) - if ( biR->sign == bib->sign ) - biR->comps[c] += bib->comps[c]; - else - biR->comps[c] -= bib->comps[c]; - bi_free( bib ); - normalize( biR ); - check( biR ); - return biR; - } - - -bigint -bi_subtract( bigint obia, bigint obib ) - { - real_bigint bia = (real_bigint) obia; - real_bigint bib = (real_bigint) obib; - real_bigint biR; - int c; - - check( bia ); - check( bib ); - biR = clone( bia ); - more_comps( biR, max( biR->num_comps, bib->num_comps ) ); - for ( c = 0; c < bib->num_comps; ++c ) - if ( biR->sign == bib->sign ) - biR->comps[c] -= bib->comps[c]; - else - biR->comps[c] += bib->comps[c]; - bi_free( bib ); - normalize( biR ); - check( biR ); - return biR; - } - - -/* Karatsuba multiplication. This is supposedly O(n^1.59), better than -** regular multiplication for large n. The define below sets the crossover -** point - below that we use regular multiplication, above it we -** use Karatsuba. Note that Karatsuba is a recursive algorithm, so -** all Karatsuba calls involve regular multiplications as the base -** steps. -*/ -#define KARATSUBA_THRESH 12 -bigint -bi_multiply( bigint obia, bigint obib ) - { - real_bigint bia = (real_bigint) obia; - real_bigint bib = (real_bigint) obib; - - check( bia ); - check( bib ); - if ( min( bia->num_comps, bib->num_comps ) < KARATSUBA_THRESH ) - return regular_multiply( bia, bib ); - else - { - /* The factors are large enough that Karatsuba multiplication - ** is a win. The basic idea here is you break each factor up - ** into two parts, like so: - ** i * r^n + j k * r^n + l - ** r is the radix we're representing numbers with, so this - ** breaking up just means shuffling components around, no - ** math required. With regular multiplication the product - ** would be: - ** ik * r^(n*2) + ( il + jk ) * r^n + jl - ** That's four sub-multiplies and one addition, not counting the - ** radix-shifting. With Karatsuba, you instead do: - ** ik * r^(n*2) + ( (i+j)(k+l) - ik - jl ) * r^n + jl - ** This is only three sub-multiplies. The number of adds - ** (and subtracts) increases to four, but those run in linear time - ** so they are cheap. The sub-multiplies are accomplished by - ** recursive calls, eventually reducing to regular multiplication. - */ - int n, c; - real_bigint bi_i, bi_j, bi_k, bi_l; - real_bigint bi_ik, bi_mid, bi_jl; - - n = ( max( bia->num_comps, bib->num_comps ) + 1 ) / 2; - bi_i = alloc( n ); - bi_j = alloc( n ); - bi_k = alloc( n ); - bi_l = alloc( n ); - for ( c = 0; c < n; ++c ) - { - if ( c + n < bia->num_comps ) - bi_i->comps[c] = bia->comps[c + n]; - else - bi_i->comps[c] = 0; - if ( c < bia->num_comps ) - bi_j->comps[c] = bia->comps[c]; - else - bi_j->comps[c] = 0; - if ( c + n < bib->num_comps ) - bi_k->comps[c] = bib->comps[c + n]; - else - bi_k->comps[c] = 0; - if ( c < bib->num_comps ) - bi_l->comps[c] = bib->comps[c]; - else - bi_l->comps[c] = 0; - } - bi_i->sign = bi_j->sign = bi_k->sign = bi_l->sign = 1; - normalize( bi_i ); - normalize( bi_j ); - normalize( bi_k ); - normalize( bi_l ); - bi_ik = bi_multiply( bi_copy( bi_i ), bi_copy( bi_k ) ); - bi_jl = bi_multiply( bi_copy( bi_j ), bi_copy( bi_l ) ); - bi_mid = bi_subtract( - bi_subtract( - bi_multiply( bi_add( bi_i, bi_j ), bi_add( bi_k, bi_l ) ), - bi_copy( bi_ik ) ), - bi_copy( bi_jl ) ); - more_comps( - bi_jl, max( bi_mid->num_comps + n, bi_ik->num_comps + n * 2 ) ); - for ( c = 0; c < bi_mid->num_comps; ++c ) - bi_jl->comps[c + n] += bi_mid->comps[c]; - for ( c = 0; c < bi_ik->num_comps; ++c ) - bi_jl->comps[c + n * 2] += bi_ik->comps[c]; - bi_free( bi_ik ); - bi_free( bi_mid ); - bi_jl->sign = bia->sign * bib->sign; - bi_free( bia ); - bi_free( bib ); - normalize( bi_jl ); - check( bi_jl ); - return bi_jl; - } - } - - -/* Regular O(n^2) multiplication. */ -static bigint -regular_multiply( real_bigint bia, real_bigint bib ) - { - real_bigint biR; - int new_comps, c1, c2; - - check( bia ); - check( bib ); - biR = clone( bi_0 ); - new_comps = bia->num_comps + bib->num_comps; - more_comps( biR, new_comps ); - for ( c1 = 0; c1 < bia->num_comps; ++c1 ) - { - for ( c2 = 0; c2 < bib->num_comps; ++c2 ) - biR->comps[c1 + c2] += bia->comps[c1] * bib->comps[c2]; - /* Normalize after each inner loop to avoid overflowing any - ** components. But be sure to reset biR's components count, - ** in case a previous normalization lowered it. - */ - biR->num_comps = new_comps; - normalize( biR ); - } - check( biR ); - if ( ! bi_is_zero( bi_copy( biR ) ) ) - biR->sign = bia->sign * bib->sign; - bi_free( bia ); - bi_free( bib ); - return biR; - } - - -/* The following three routines implement a multi-precision divide method -** that I haven't seen used anywhere else. It is not quite as fast as -** the standard divide method, but it is a lot simpler. In fact it's -** about as simple as the binary shift-and-subtract method, which goes -** about five times slower than this. -** -** The method assumes you already have multi-precision multiply and subtract -** routines, and also a multi-by-single precision divide routine. The latter -** is used to generate approximations, which are then checked and corrected -** using the former. The result converges to the correct value by about -** 16 bits per loop. -*/ - -/* Public routine to divide two arbitrary numbers. */ -bigint -bi_divide( bigint binumer, bigint obidenom ) - { - real_bigint bidenom = (real_bigint) obidenom; - int sign; - bigint biquotient; - - /* Check signs and trivial cases. */ - sign = 1; - switch ( bi_compare( bi_copy( bidenom ), bi_0 ) ) - { - case 0: - (void) fprintf( stderr, "bi_divide: divide by zero\n" ); - (void) kill( getpid(), SIGFPE ); - case -1: - sign *= -1; - bidenom = bi_negate( bidenom ); - break; - } - switch ( bi_compare( bi_copy( binumer ), bi_0 ) ) - { - case 0: - bi_free( binumer ); - bi_free( bidenom ); - return bi_0; - case -1: - sign *= -1; - binumer = bi_negate( binumer ); - break; - } - switch ( bi_compare( bi_copy( binumer ), bi_copy( bidenom ) ) ) - { - case -1: - bi_free( binumer ); - bi_free( bidenom ); - return bi_0; - case 0: - bi_free( binumer ); - bi_free( bidenom ); - if ( sign == 1 ) - return bi_1; - else - return bi_m1; - } - - /* Is the denominator small enough to do an int divide? */ - if ( bidenom->num_comps == 1 ) - { - /* Win! */ - biquotient = bi_int_divide( binumer, bidenom->comps[0] ); - bi_free( bidenom ); - } - else - { - /* No, we have to do a full multi-by-multi divide. */ - biquotient = multi_divide( binumer, bidenom ); - } - - if ( sign == -1 ) - biquotient = bi_negate( biquotient ); - return biquotient; - } - - -/* Divide two multi-precision positive numbers. */ -static bigint -multi_divide( bigint binumer, real_bigint bidenom ) - { - /* We use a successive approximation method that is kind of like a - ** continued fraction. The basic approximation is to do an int divide - ** by the high-order component of the denominator. Then we correct - ** based on the remainder from that. - ** - ** However, if the high-order component is too small, this doesn't - ** work well. In particular, if the high-order component is 1 it - ** doesn't work at all. Easily fixed, though - if the component - ** is too small, increase it! - */ - if ( bidenom->comps[bidenom->num_comps-1] < bi_radix_sqrt ) - { - /* We use the square root of the radix as the threshhold here - ** because that's the largest value guaranteed to not make the - ** high-order component overflow and become too small again. - ** - ** We increase binumer along with bidenom to keep the end result - ** the same. - */ - binumer = bi_int_multiply( binumer, bi_radix_sqrt ); - bidenom = bi_int_multiply( bidenom, bi_radix_sqrt ); - } - - /* Now start the recursion. */ - return multi_divide2( binumer, bidenom ); - } - - -/* Divide two multi-precision positive conditioned numbers. */ -static bigint -multi_divide2( bigint binumer, real_bigint bidenom ) - { - real_bigint biapprox; - bigint birem, biquotient; - int c, o; - - /* Figure out the approximate quotient. Since we're dividing by only - ** the top component of the denominator, which is less than or equal to - ** the full denominator, the result is guaranteed to be greater than or - ** equal to the correct quotient. - */ - o = bidenom->num_comps - 1; - biapprox = bi_int_divide( bi_copy( binumer ), bidenom->comps[o] ); - /* And downshift the result to get the approximate quotient. */ - for ( c = o; c < biapprox->num_comps; ++c ) - biapprox->comps[c - o] = biapprox->comps[c]; - biapprox->num_comps -= o; - - /* Find the remainder from the approximate quotient. */ - birem = bi_subtract( - bi_multiply( bi_copy( biapprox ), bi_copy( bidenom ) ), binumer ); - - /* If the remainder is negative, zero, or in fact any value less - ** than bidenom, then we have the correct quotient and we're done. - */ - if ( bi_compare( bi_copy( birem ), bi_copy( bidenom ) ) < 0 ) - { - biquotient = biapprox; - bi_free( birem ); - bi_free( bidenom ); - } - else - { - /* The real quotient is now biapprox - birem / bidenom. We still - ** have to do a divide. However, birem is smaller than binumer, - ** so the next divide will go faster. We do the divide by - ** recursion. Since this is tail-recursion or close to it, we - ** could probably re-arrange things and make it a non-recursive - ** loop, but the overhead of recursion is small and the bookkeeping - ** is simpler this way. - ** - ** Note that since the sub-divide uses the same denominator, it - ** doesn't have to adjust the values again - the high-order component - ** will still be good. - */ - biquotient = bi_subtract( biapprox, multi_divide2( birem, bidenom ) ); - } - - return biquotient; - } - - -/* Binary division - about five times slower than the above. */ -bigint -bi_binary_divide( bigint binumer, bigint obidenom ) - { - real_bigint bidenom = (real_bigint) obidenom; - int sign; - bigint biquotient; - - /* Check signs and trivial cases. */ - sign = 1; - switch ( bi_compare( bi_copy( bidenom ), bi_0 ) ) - { - case 0: - (void) fprintf( stderr, "bi_divide: divide by zero\n" ); - (void) kill( getpid(), SIGFPE ); - case -1: - sign *= -1; - bidenom = bi_negate( bidenom ); - break; - } - switch ( bi_compare( bi_copy( binumer ), bi_0 ) ) - { - case 0: - bi_free( binumer ); - bi_free( bidenom ); - return bi_0; - case -1: - sign *= -1; - binumer = bi_negate( binumer ); - break; - } - switch ( bi_compare( bi_copy( binumer ), bi_copy( bidenom ) ) ) - { - case -1: - bi_free( binumer ); - bi_free( bidenom ); - return bi_0; - case 0: - bi_free( binumer ); - bi_free( bidenom ); - if ( sign == 1 ) - return bi_1; - else - return bi_m1; - } - - /* Is the denominator small enough to do an int divide? */ - if ( bidenom->num_comps == 1 ) - { - /* Win! */ - biquotient = bi_int_divide( binumer, bidenom->comps[0] ); - bi_free( bidenom ); - } - else - { - /* No, we have to do a full multi-by-multi divide. */ - int num_bits, den_bits, i; - - num_bits = bi_bits( bi_copy( binumer ) ); - den_bits = bi_bits( bi_copy( bidenom ) ); - bidenom = bi_multiply( bidenom, bi_power( bi_2, int_to_bi( num_bits - den_bits ) ) ); - biquotient = bi_0; - for ( i = den_bits; i <= num_bits; ++i ) - { - biquotient = bi_double( biquotient ); - if ( bi_compare( bi_copy( binumer ), bi_copy( bidenom ) ) >= 0 ) - { - biquotient = bi_int_add( biquotient, 1 ); - binumer = bi_subtract( binumer, bi_copy( bidenom ) ); - } - bidenom = bi_half( bidenom ); - } - bi_free( binumer ); - bi_free( bidenom ); - } - - if ( sign == -1 ) - biquotient = bi_negate( biquotient ); - return biquotient; - } - - -bigint -bi_negate( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - - check( bi ); - biR = clone( bi ); - biR->sign = -biR->sign; - check( biR ); - return biR; - } - - -bigint -bi_abs( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - - check( bi ); - biR = clone( bi ); - biR->sign = 1; - check( biR ); - return biR; - } - - -bigint -bi_half( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - int c; - - check( bi ); - /* This depends on the radix being even. */ - biR = clone( bi ); - for ( c = 0; c < biR->num_comps; ++c ) - { - if ( biR->comps[c] & 1 ) - if ( c > 0 ) - biR->comps[c - 1] += bi_radix_o2; - biR->comps[c] = biR->comps[c] >> 1; - } - /* Avoid normalization. */ - if ( biR->num_comps > 1 && biR->comps[biR->num_comps-1] == 0 ) - --biR->num_comps; - check( biR ); - return biR; - } - - -bigint -bi_double( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - real_bigint biR; - int c; - - check( bi ); - biR = clone( bi ); - for ( c = biR->num_comps - 1; c >= 0; --c ) - { - biR->comps[c] = biR->comps[c] << 1; - if ( biR->comps[c] >= bi_radix ) - { - if ( c + 1 >= biR->num_comps ) - more_comps( biR, biR->num_comps + 1 ); - biR->comps[c] -= bi_radix; - biR->comps[c + 1] += 1; - } - } - check( biR ); - return biR; - } - - -/* Find integer square root by Newton's method. */ -bigint -bi_sqrt( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - bigint biR, biR2, bidiff; - - switch ( bi_compare( bi_copy( bi ), bi_0 ) ) - { - case -1: - (void) fprintf( stderr, "bi_sqrt: imaginary result\n" ); - (void) kill( getpid(), SIGFPE ); - case 0: - return bi; - } - if ( bi_is_one( bi_copy( bi ) ) ) - return bi; - - /* Newton's method converges reasonably fast, but it helps to have - ** a good initial guess. We can make a *very* good initial guess - ** by taking the square root of the top component times the square - ** root of the radix part. Both of those are easy to compute. - */ - biR = bi_int_multiply( - bi_power( int_to_bi( bi_radix_sqrt ), int_to_bi( bi->num_comps - 1 ) ), - csqrt( bi->comps[bi->num_comps - 1] ) ); - - /* Now do the Newton loop until we have the answer. */ - for (;;) - { - biR2 = bi_divide( bi_copy( bi ), bi_copy( biR ) ); - bidiff = bi_subtract( bi_copy( biR ), bi_copy( biR2 ) ); - if ( bi_is_zero( bi_copy( bidiff ) ) || - bi_compare( bi_copy( bidiff ), bi_m1 ) == 0 ) - { - bi_free( bi ); - bi_free( bidiff ); - bi_free( biR2 ); - return biR; - } - if ( bi_is_one( bi_copy( bidiff ) ) ) - { - bi_free( bi ); - bi_free( bidiff ); - bi_free( biR ); - return biR2; - } - bi_free( bidiff ); - biR = bi_half( bi_add( biR, biR2 ) ); - } - } - - -int -bi_is_odd( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - int r; - - check( bi ); - r = bi->comps[0] & 1; - bi_free( bi ); - return r; - } - - -int -bi_is_zero( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - int r; - - check( bi ); - r = ( bi->sign == 1 && bi->num_comps == 1 && bi->comps[0] == 0 ); - bi_free( bi ); - return r; - } - - -int -bi_is_one( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - int r; - - check( bi ); - r = ( bi->sign == 1 && bi->num_comps == 1 && bi->comps[0] == 1 ); - bi_free( bi ); - return r; - } - - -int -bi_is_negative( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - int r; - - check( bi ); - r = ( bi->sign == -1 ); - bi_free( bi ); - return r; - } - - -bigint -bi_random( bigint bi ) - { - real_bigint biR; - int c; - - biR = bi_multiply( bi_copy( bi ), bi_copy( bi ) ); - for ( c = 0; c < biR->num_comps; ++c ) - biR->comps[c] = random(); - normalize( biR ); - biR = bi_mod( biR, bi ); - return biR; - } - - -int -bi_bits( bigint obi ) - { - real_bigint bi = (real_bigint) obi; - int bits; - - bits = - bi_comp_bits * ( bi->num_comps - 1 ) + - cbits( bi->comps[bi->num_comps - 1] ); - bi_free( bi ); - return bits; - } - - -/* Allocate and zero more components. Does not consume bi, of course. */ -static void -more_comps( real_bigint bi, int n ) - { - if ( n > bi->max_comps ) - { - bi->max_comps = max( bi->max_comps * 2, n ); - bi->comps = (comp*) realloc( - (void*) bi->comps, bi->max_comps * sizeof(comp) ); - if ( bi->comps == (comp*) 0 ) - { - (void) fprintf( stderr, "out of memory\n" ); - exit( 1 ); - } - } - for ( ; bi->num_comps < n; ++bi->num_comps ) - bi->comps[bi->num_comps] = 0; - } - - -/* Make a new empty bigint. Fills in everything except sign and the -** components. -*/ -static real_bigint -alloc( int num_comps ) - { - real_bigint biR; - - /* Can we recycle an old bigint? */ - if ( free_list != (real_bigint) 0 ) - { - biR = free_list; - free_list = biR->next; - --free_count; - if ( check_level >= 1 && biR->refs != 0 ) - { - (void) fprintf( stderr, "alloc: refs was not 0\n" ); - (void) kill( getpid(), SIGFPE ); - } - more_comps( biR, num_comps ); - } - else - { - /* No free bigints available - create a new one. */ - biR = (real_bigint) malloc( sizeof(struct _real_bigint) ); - if ( biR == (real_bigint) 0 ) - { - (void) fprintf( stderr, "out of memory\n" ); - exit( 1 ); - } - biR->comps = (comp*) malloc( num_comps * sizeof(comp) ); - if ( biR->comps == (comp*) 0 ) - { - (void) fprintf( stderr, "out of memory\n" ); - exit( 1 ); - } - biR->max_comps = num_comps; - } - biR->num_comps = num_comps; - biR->refs = 1; - if ( check_level >= 3 ) - { - /* The active list only gets maintained at check levels 3 or higher. */ - biR->next = active_list; - active_list = biR; - } - else - biR->next = (real_bigint) 0; - ++active_count; - return biR; - } - - -/* Make a modifiable copy of bi. DOES consume bi. */ -static real_bigint -clone( real_bigint bi ) - { - real_bigint biR; - int c; - - /* Very clever optimization. */ - if ( bi->refs != PERMANENT && bi->refs == 1 ) - return bi; - - biR = alloc( bi->num_comps ); - biR->sign = bi->sign; - for ( c = 0; c < bi->num_comps; ++c ) - biR->comps[c] = bi->comps[c]; - bi_free( bi ); - return biR; - } - - -/* Put bi into normal form. Does not consume bi, of course. -** -** Normal form is: -** - All components >= 0 and < bi_radix. -** - Leading 0 components removed. -** - Sign either 1 or -1. -** - The number zero represented by a single 0 component and a sign of 1. -*/ -static void -normalize( real_bigint bi ) - { - int c; - - /* Borrow for negative components. Got to be careful with the math here: - ** -9 / 10 == 0 -9 % 10 == -9 - ** -10 / 10 == -1 -10 % 10 == 0 - ** -11 / 10 == -1 -11 % 10 == -1 - */ - for ( c = 0; c < bi->num_comps - 1; ++c ) - if ( bi->comps[c] < 0 ) - { - bi->comps[c+1] += bi->comps[c] / bi_radix - 1; - bi->comps[c] = bi->comps[c] % bi_radix; - if ( bi->comps[c] != 0 ) - bi->comps[c] += bi_radix; - else - bi->comps[c+1] += 1; - } - /* Is the top component negative? */ - if ( bi->comps[bi->num_comps - 1] < 0 ) - { - /* Switch the sign of the number, and fix up the components. */ - bi->sign = -bi->sign; - for ( c = 0; c < bi->num_comps - 1; ++c ) - { - bi->comps[c] = bi_radix - bi->comps[c]; - bi->comps[c + 1] += 1; - } - bi->comps[bi->num_comps - 1] = -bi->comps[bi->num_comps - 1]; - } - - /* Carry for components larger than the radix. */ - for ( c = 0; c < bi->num_comps; ++c ) - if ( bi->comps[c] >= bi_radix ) - { - if ( c + 1 >= bi->num_comps ) - more_comps( bi, bi->num_comps + 1 ); - bi->comps[c+1] += bi->comps[c] / bi_radix; - bi->comps[c] = bi->comps[c] % bi_radix; - } - - /* Trim off any leading zero components. */ - for ( ; bi->num_comps > 1 && bi->comps[bi->num_comps-1] == 0; --bi->num_comps ) - ; - - /* Check for -0. */ - if ( bi->num_comps == 1 && bi->comps[0] == 0 && bi->sign == -1 ) - bi->sign = 1; - } - - -static void -check( real_bigint bi ) - { - if ( check_level == 0 ) - return; - if ( bi->refs == 0 ) - { - (void) fprintf( stderr, "check: zero refs in bigint\n" ); - (void) kill( getpid(), SIGFPE ); - } - if ( bi->refs < 0 ) - { - (void) fprintf( stderr, "check: negative refs in bigint\n" ); - (void) kill( getpid(), SIGFPE ); - } - if ( check_level < 3 ) - { - /* At check levels less than 3, active bigints have a zero next. */ - if ( bi->next != (real_bigint) 0 ) - { - (void) fprintf( - stderr, "check: attempt to use a bigint from the free list\n" ); - (void) kill( getpid(), SIGFPE ); - } - } - else - { - /* At check levels 3 or higher, active bigints must be on the active - ** list. - */ - real_bigint p; - - for ( p = active_list; p != (real_bigint) 0; p = p->next ) - if ( p == bi ) - break; - if ( p == (real_bigint) 0 ) - { - (void) fprintf( stderr, - "check: attempt to use a bigint not on the active list\n" ); - (void) kill( getpid(), SIGFPE ); - } - } - if ( check_level >= 2 ) - double_check(); - if ( check_level >= 3 ) - triple_check(); - } - - -static void -double_check( void ) - { - real_bigint p; - int c; - - for ( p = free_list, c = 0; p != (real_bigint) 0; p = p->next, ++c ) - if ( p->refs != 0 ) - { - (void) fprintf( stderr, - "double_check: found a non-zero ref on the free list\n" ); - (void) kill( getpid(), SIGFPE ); - } - if ( c != free_count ) - { - (void) fprintf( stderr, - "double_check: free_count is %d but the free list has %d items\n", - free_count, c ); - (void) kill( getpid(), SIGFPE ); - } - } - - -static void -triple_check( void ) - { - real_bigint p; - int c; - - for ( p = active_list, c = 0; p != (real_bigint) 0; p = p->next, ++c ) - if ( p->refs == 0 ) - { - (void) fprintf( stderr, - "triple_check: found a zero ref on the active list\n" ); - (void) kill( getpid(), SIGFPE ); - } - if ( c != active_count ) - { - (void) fprintf( stderr, - "triple_check: active_count is %d but active_list has %d items\n", - free_count, c ); - (void) kill( getpid(), SIGFPE ); - } - } - - -#ifdef DUMP -/* Debug routine to dump out a complete bigint. Does not consume bi. */ -static void -dump( char* str, bigint obi ) - { - int c; - real_bigint bi = (real_bigint) obi; - - (void) fprintf( stdout, "dump %s at 0x%08x:\n", str, (unsigned int) bi ); - (void) fprintf( stdout, " refs: %d\n", bi->refs ); - (void) fprintf( stdout, " next: 0x%08x\n", (unsigned int) bi->next ); - (void) fprintf( stdout, " num_comps: %d\n", bi->num_comps ); - (void) fprintf( stdout, " max_comps: %d\n", bi->max_comps ); - (void) fprintf( stdout, " sign: %d\n", bi->sign ); - for ( c = bi->num_comps - 1; c >= 0; --c ) - (void) fprintf( stdout, " comps[%d]: %11lld (0x%016llx)\n", c, (long long) bi->comps[c], (long long) bi->comps[c] ); - (void) fprintf( stdout, " print: " ); - bi_print( stdout, bi_copy( bi ) ); - (void) fprintf( stdout, "\n" ); - } -#endif /* DUMP */ - - -/* Trivial square-root routine so that we don't have to link in the math lib. */ -static int -csqrt( comp c ) - { - comp r, r2, diff; - - if ( c < 0 ) - { - (void) fprintf( stderr, "csqrt: imaginary result\n" ); - (void) kill( getpid(), SIGFPE ); - } - - r = c / 2; - for (;;) - { - r2 = c / r; - diff = r - r2; - if ( diff == 0 || diff == -1 ) - return (int) r; - if ( diff == 1 ) - return (int) r2; - r = ( r + r2 ) / 2; - } - } - - -/* Figure out how many bits are in a number. */ -static int -cbits( comp c ) - { - int b; - - for ( b = 0; c != 0; ++b ) - c >>= 1; - return b; - } diff --git a/src/rt/bigint/low_primes.h b/src/rt/bigint/low_primes.h deleted file mode 100644 index c9d3df0b3f403..0000000000000 --- a/src/rt/bigint/low_primes.h +++ /dev/null @@ -1,1069 +0,0 @@ -/* Primes up to 100000. */ -static long low_primes[] = { - 2, 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, 61, - 67, 71, 73, 79, 83, 89, 97, 101, 103, - 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, - 199, 211, 223, 227, 229, 233, 239, 241, 251, - 257, 263, 269, 271, 277, 281, 283, 293, 307, - 311, 313, 317, 331, 337, 347, 349, 353, 359, - 367, 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, 463, - 467, 479, 487, 491, 499, 503, 509, 521, 523, - 541, 547, 557, 563, 569, 571, 577, 587, 593, - 599, 601, 607, 613, 617, 619, 631, 641, 643, - 647, 653, 659, 661, 673, 677, 683, 691, 701, - 709, 719, 727, 733, 739, 743, 751, 757, 761, - 769, 773, 787, 797, 809, 811, 821, 823, 827, - 829, 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, 953, - 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, - 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, - 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, - 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, - 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, - 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, - 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, - 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, - 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, - 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, - 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, - 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, - 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, - 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, - 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, - 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, - 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, - 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, - 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, - 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, - 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, - 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, - 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, - 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, - 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, - 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, - 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, - 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, - 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, - 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, - 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, - 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, - 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, - 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, - 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, - 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, - 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, - 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, - 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, - 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, - 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, - 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, - 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, - 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, - 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, - 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, - 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, - 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, - 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, - 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, - 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, - 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, - 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, - 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, - 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, - 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, - 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, - 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, - 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, - 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, - 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, - 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, - 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, - 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, - 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, - 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, - 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, - 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, - 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, - 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, - 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, - 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, - 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, - 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, - 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, - 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, - 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, - 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, - 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, - 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, - 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, - 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, - 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, - 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, - 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, - 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, - 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, - 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, - 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, - 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, - 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, - 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, - 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, - 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, - 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, - 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, - 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, - 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, - 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, - 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, - 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, - 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, - 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, - 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, - 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, - 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, - 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, - 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, - 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, - 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, - 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, - 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, - 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, - 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, - 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, - 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, - 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039, - 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, - 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, - 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, - 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, - 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, - 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, - 10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, - 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, 10709, - 10711, 10723, 10729, 10733, 10739, 10753, 10771, 10781, 10789, - 10799, 10831, 10837, 10847, 10853, 10859, 10861, 10867, 10883, - 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973, - 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, - 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, - 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, - 11251, 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, - 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, 11411, - 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, - 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, - 11597, 11617, 11621, 11633, 11657, 11677, 11681, 11689, 11699, - 11701, 11717, 11719, 11731, 11743, 11777, 11779, 11783, 11789, - 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, 11863, - 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939, - 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, - 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, - 12109, 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, - 12203, 12211, 12227, 12239, 12241, 12251, 12253, 12263, 12269, - 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347, 12373, - 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, - 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, - 12517, 12527, 12539, 12541, 12547, 12553, 12569, 12577, 12583, - 12589, 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, - 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 12743, - 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, - 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, - 12923, 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, - 13003, 13007, 13009, 13033, 13037, 13043, 13049, 13063, 13093, - 13099, 13103, 13109, 13121, 13127, 13147, 13151, 13159, 13163, - 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241, 13249, - 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, - 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, - 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, 13523, - 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627, - 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, - 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, - 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, - 13877, 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, - 13933, 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, - 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, 14149, - 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243, 14249, - 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, - 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, - 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 14533, - 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, - 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, - 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, - 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, - 14831, 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, - 14923, 14929, 14939, 14947, 14951, 14957, 14969, 14983, 15013, - 15017, 15031, 15053, 15061, 15073, 15077, 15083, 15091, 15101, - 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173, 15187, - 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, - 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, - 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, - 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, - 15497, 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, - 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661, - 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, - 15749, 15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, - 15817, 15823, 15859, 15877, 15881, 15887, 15889, 15901, 15907, - 15913, 15919, 15923, 15937, 15959, 15971, 15973, 15991, 16001, - 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, - 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, - 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, - 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, - 16381, 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, - 16477, 16481, 16487, 16493, 16519, 16529, 16547, 16553, 16561, - 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651, - 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, - 16747, 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, - 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, 16931, - 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, 17021, - 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099, - 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, - 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, - 17317, 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, - 17387, 17389, 17393, 17401, 17417, 17419, 17431, 17443, 17449, - 17467, 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, - 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609, - 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, - 17729, 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, - 17827, 17837, 17839, 17851, 17863, 17881, 17891, 17903, 17909, - 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 17977, - 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, - 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, - 18143, 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, - 18229, 18233, 18251, 18253, 18257, 18269, 18287, 18289, 18301, - 18307, 18311, 18313, 18329, 18341, 18353, 18367, 18371, 18379, - 18397, 18401, 18413, 18427, 18433, 18439, 18443, 18451, 18457, - 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541, - 18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679, - 18691, 18701, 18713, 18719, 18731, 18743, 18749, 18757, 18773, - 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 18911, - 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, - 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, - 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, - 19213, 19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289, - 19301, 19309, 19319, 19333, 19373, 19379, 19381, 19387, 19391, - 19403, 19417, 19421, 19423, 19427, 19429, 19433, 19441, 19447, - 19457, 19463, 19469, 19471, 19477, 19483, 19489, 19501, 19507, - 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597, - 19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717, - 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801, - 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, - 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, - 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, - 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129, - 20143, 20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, - 20231, 20233, 20249, 20261, 20269, 20287, 20297, 20323, 20327, - 20333, 20341, 20347, 20353, 20357, 20359, 20369, 20389, 20393, - 20399, 20407, 20411, 20431, 20441, 20443, 20477, 20479, 20483, - 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593, - 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, - 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, - 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, - 20897, 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, - 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023, 21031, - 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, - 21149, 21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211, - 21221, 21227, 21247, 21269, 21277, 21283, 21313, 21317, 21319, - 21323, 21341, 21347, 21377, 21379, 21383, 21391, 21397, 21401, - 21407, 21419, 21433, 21467, 21481, 21487, 21491, 21493, 21499, - 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569, - 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, - 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, - 21751, 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, - 21839, 21841, 21851, 21859, 21863, 21871, 21881, 21893, 21911, - 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003, 22013, - 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079, - 22091, 22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153, - 22157, 22159, 22171, 22189, 22193, 22229, 22247, 22259, 22271, - 22273, 22277, 22279, 22283, 22291, 22303, 22307, 22343, 22349, - 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 22447, - 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, - 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, - 22643, 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, - 22721, 22727, 22739, 22741, 22751, 22769, 22777, 22783, 22787, - 22807, 22811, 22817, 22853, 22859, 22861, 22871, 22877, 22901, - 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993, 23003, - 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, - 23059, 23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, - 23159, 23167, 23173, 23189, 23197, 23201, 23203, 23209, 23227, - 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 23327, - 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, - 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, - 23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, - 23627, 23629, 23633, 23663, 23669, 23671, 23677, 23687, 23689, - 23719, 23741, 23743, 23747, 23753, 23761, 23767, 23773, 23789, - 23801, 23813, 23819, 23827, 23831, 23833, 23857, 23869, 23873, - 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929, 23957, - 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, - 24043, 24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103, - 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179, - 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, - 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, - 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, - 24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, - 24623, 24631, 24659, 24671, 24677, 24683, 24691, 24697, 24709, - 24733, 24749, 24763, 24767, 24781, 24793, 24799, 24809, 24821, - 24841, 24847, 24851, 24859, 24877, 24889, 24907, 24917, 24919, - 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989, 25013, - 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117, - 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, - 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, - 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, - 25391, 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, - 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583, - 25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657, - 25667, 25673, 25679, 25693, 25703, 25717, 25733, 25741, 25747, - 25759, 25763, 25771, 25793, 25799, 25801, 25819, 25841, 25847, - 25849, 25867, 25873, 25889, 25903, 25913, 25919, 25931, 25933, - 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003, 26017, - 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, - 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, - 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, - 26297, 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, - 26393, 26399, 26407, 26417, 26423, 26431, 26437, 26449, 26459, - 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573, - 26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, - 26687, 26693, 26699, 26701, 26711, 26713, 26717, 26723, 26729, - 26731, 26737, 26759, 26777, 26783, 26801, 26813, 26821, 26833, - 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, 26903, - 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993, - 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, - 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, - 27211, 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, - 27299, 27329, 27337, 27361, 27367, 27397, 27407, 27409, 27427, - 27431, 27437, 27449, 27457, 27479, 27481, 27487, 27509, 27527, - 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631, - 27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, - 27739, 27743, 27749, 27751, 27763, 27767, 27773, 27779, 27791, - 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, 27851, - 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953, - 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, - 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, - 28151, 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, - 28279, 28283, 28289, 28297, 28307, 28309, 28319, 28349, 28351, - 28387, 28393, 28403, 28409, 28411, 28429, 28433, 28439, 28447, - 28463, 28477, 28493, 28499, 28513, 28517, 28537, 28541, 28547, - 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607, - 28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663, - 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, 28753, - 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843, - 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, - 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, - 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, - 29153, 29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221, - 29231, 29243, 29251, 29269, 29287, 29297, 29303, 29311, 29327, - 29333, 29339, 29347, 29363, 29383, 29387, 29389, 29399, 29401, - 29411, 29423, 29429, 29437, 29443, 29453, 29473, 29483, 29501, - 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599, - 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, - 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 29833, - 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, - 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, - 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, - 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203, - 30211, 30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307, - 30313, 30319, 30323, 30341, 30347, 30367, 30389, 30391, 30403, - 30427, 30431, 30449, 30467, 30469, 30491, 30493, 30497, 30509, - 30517, 30529, 30539, 30553, 30557, 30559, 30577, 30593, 30631, - 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703, - 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, - 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, - 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, - 30983, 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, - 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153, 31159, - 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237, - 31247, 31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319, - 31321, 31327, 31333, 31337, 31357, 31379, 31387, 31391, 31393, - 31397, 31469, 31477, 31481, 31489, 31511, 31513, 31517, 31531, - 31541, 31543, 31547, 31567, 31573, 31583, 31601, 31607, 31627, - 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723, - 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, - 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, - 31973, 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, - 32059, 32063, 32069, 32077, 32083, 32089, 32099, 32117, 32119, - 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203, 32213, - 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309, - 32321, 32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371, - 32377, 32381, 32401, 32411, 32413, 32423, 32429, 32441, 32443, - 32467, 32479, 32491, 32497, 32503, 32507, 32531, 32533, 32537, - 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 32611, - 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, - 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, - 32831, 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, - 32933, 32939, 32941, 32957, 32969, 32971, 32983, 32987, 32993, - 32999, 33013, 33023, 33029, 33037, 33049, 33053, 33071, 33073, - 33083, 33091, 33107, 33113, 33119, 33149, 33151, 33161, 33179, - 33181, 33191, 33199, 33203, 33211, 33223, 33247, 33287, 33289, - 33301, 33311, 33317, 33329, 33331, 33343, 33347, 33349, 33353, - 33359, 33377, 33391, 33403, 33409, 33413, 33427, 33457, 33461, - 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, 33547, - 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, - 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, - 33713, 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, - 33791, 33797, 33809, 33811, 33827, 33829, 33851, 33857, 33863, - 33871, 33889, 33893, 33911, 33923, 33931, 33937, 33941, 33961, - 33967, 33997, 34019, 34031, 34033, 34039, 34057, 34061, 34123, - 34127, 34129, 34141, 34147, 34157, 34159, 34171, 34183, 34211, - 34213, 34217, 34231, 34253, 34259, 34261, 34267, 34273, 34283, - 34297, 34301, 34303, 34313, 34319, 34327, 34337, 34351, 34361, - 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, 34469, - 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, - 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, - 34649, 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, - 34729, 34739, 34747, 34757, 34759, 34763, 34781, 34807, 34819, - 34841, 34843, 34847, 34849, 34871, 34877, 34883, 34897, 34913, - 34919, 34939, 34949, 34961, 34963, 34981, 35023, 35027, 35051, - 35053, 35059, 35069, 35081, 35083, 35089, 35099, 35107, 35111, - 35117, 35129, 35141, 35149, 35153, 35159, 35171, 35201, 35221, - 35227, 35251, 35257, 35267, 35279, 35281, 35291, 35311, 35317, - 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, 35407, - 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, - 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, - 35593, 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, - 35753, 35759, 35771, 35797, 35801, 35803, 35809, 35831, 35837, - 35839, 35851, 35863, 35869, 35879, 35897, 35899, 35911, 35923, - 35933, 35951, 35963, 35969, 35977, 35983, 35993, 35999, 36007, - 36011, 36013, 36017, 36037, 36061, 36067, 36073, 36083, 36097, - 36107, 36109, 36131, 36137, 36151, 36161, 36187, 36191, 36209, - 36217, 36229, 36241, 36251, 36263, 36269, 36277, 36293, 36299, - 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 36389, - 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, - 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, - 36587, 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, - 36683, 36691, 36697, 36709, 36713, 36721, 36739, 36749, 36761, - 36767, 36779, 36781, 36787, 36791, 36793, 36809, 36821, 36833, - 36847, 36857, 36871, 36877, 36887, 36899, 36901, 36913, 36919, - 36923, 36929, 36931, 36943, 36947, 36973, 36979, 36997, 37003, - 37013, 37019, 37021, 37039, 37049, 37057, 37061, 37087, 37097, - 37117, 37123, 37139, 37159, 37171, 37181, 37189, 37199, 37201, - 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, 37313, - 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, - 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, - 37507, 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, - 37571, 37573, 37579, 37589, 37591, 37607, 37619, 37633, 37643, - 37649, 37657, 37663, 37691, 37693, 37699, 37717, 37747, 37781, - 37783, 37799, 37811, 37813, 37831, 37847, 37853, 37861, 37871, - 37879, 37889, 37897, 37907, 37951, 37957, 37963, 37967, 37987, - 37991, 37993, 37997, 38011, 38039, 38047, 38053, 38069, 38083, - 38113, 38119, 38149, 38153, 38167, 38177, 38183, 38189, 38197, - 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, 38287, - 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, - 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, - 38543, 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, - 38629, 38639, 38651, 38653, 38669, 38671, 38677, 38693, 38699, - 38707, 38711, 38713, 38723, 38729, 38737, 38747, 38749, 38767, - 38783, 38791, 38803, 38821, 38833, 38839, 38851, 38861, 38867, - 38873, 38891, 38903, 38917, 38921, 38923, 38933, 38953, 38959, - 38971, 38977, 38993, 39019, 39023, 39041, 39043, 39047, 39079, - 39089, 39097, 39103, 39107, 39113, 39119, 39133, 39139, 39157, - 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, 39229, - 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, - 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, - 39419, 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, - 39521, 39541, 39551, 39563, 39569, 39581, 39607, 39619, 39623, - 39631, 39659, 39667, 39671, 39679, 39703, 39709, 39719, 39727, - 39733, 39749, 39761, 39769, 39779, 39791, 39799, 39821, 39827, - 39829, 39839, 39841, 39847, 39857, 39863, 39869, 39877, 39883, - 39887, 39901, 39929, 39937, 39953, 39971, 39979, 39983, 39989, - 40009, 40013, 40031, 40037, 40039, 40063, 40087, 40093, 40099, - 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, 40177, - 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, - 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, - 40433, 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, - 40529, 40531, 40543, 40559, 40577, 40583, 40591, 40597, 40609, - 40627, 40637, 40639, 40693, 40697, 40699, 40709, 40739, 40751, - 40759, 40763, 40771, 40787, 40801, 40813, 40819, 40823, 40829, - 40841, 40847, 40849, 40853, 40867, 40879, 40883, 40897, 40903, - 40927, 40933, 40939, 40949, 40961, 40973, 40993, 41011, 41017, - 41023, 41039, 41047, 41051, 41057, 41077, 41081, 41113, 41117, - 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 41189, - 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, - 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, - 41387, 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, - 41491, 41507, 41513, 41519, 41521, 41539, 41543, 41549, 41579, - 41593, 41597, 41603, 41609, 41611, 41617, 41621, 41627, 41641, - 41647, 41651, 41659, 41669, 41681, 41687, 41719, 41729, 41737, - 41759, 41761, 41771, 41777, 41801, 41809, 41813, 41843, 41849, - 41851, 41863, 41879, 41887, 41893, 41897, 41903, 41911, 41927, - 41941, 41947, 41953, 41957, 41959, 41969, 41981, 41983, 41999, - 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 42083, - 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, - 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, - 42283, 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, - 42373, 42379, 42391, 42397, 42403, 42407, 42409, 42433, 42437, - 42443, 42451, 42457, 42461, 42463, 42467, 42473, 42487, 42491, - 42499, 42509, 42533, 42557, 42569, 42571, 42577, 42589, 42611, - 42641, 42643, 42649, 42667, 42677, 42683, 42689, 42697, 42701, - 42703, 42709, 42719, 42727, 42737, 42743, 42751, 42767, 42773, - 42787, 42793, 42797, 42821, 42829, 42839, 42841, 42853, 42859, - 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, 42961, - 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, - 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, - 43189, 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, - 43313, 43319, 43321, 43331, 43391, 43397, 43399, 43403, 43411, - 43427, 43441, 43451, 43457, 43481, 43487, 43499, 43517, 43541, - 43543, 43573, 43577, 43579, 43591, 43597, 43607, 43609, 43613, - 43627, 43633, 43649, 43651, 43661, 43669, 43691, 43711, 43717, - 43721, 43753, 43759, 43777, 43781, 43783, 43787, 43789, 43793, - 43801, 43853, 43867, 43889, 43891, 43913, 43933, 43943, 43951, - 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, 44021, - 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, - 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, - 44201, 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, - 44273, 44279, 44281, 44293, 44351, 44357, 44371, 44381, 44383, - 44389, 44417, 44449, 44453, 44483, 44491, 44497, 44501, 44507, - 44519, 44531, 44533, 44537, 44543, 44549, 44563, 44579, 44587, - 44617, 44621, 44623, 44633, 44641, 44647, 44651, 44657, 44683, - 44687, 44699, 44701, 44711, 44729, 44741, 44753, 44771, 44773, - 44777, 44789, 44797, 44809, 44819, 44839, 44843, 44851, 44867, - 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, 44959, - 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, - 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, - 45181, 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, - 45293, 45307, 45317, 45319, 45329, 45337, 45341, 45343, 45361, - 45377, 45389, 45403, 45413, 45427, 45433, 45439, 45481, 45491, - 45497, 45503, 45523, 45533, 45541, 45553, 45557, 45569, 45587, - 45589, 45599, 45613, 45631, 45641, 45659, 45667, 45673, 45677, - 45691, 45697, 45707, 45737, 45751, 45757, 45763, 45767, 45779, - 45817, 45821, 45823, 45827, 45833, 45841, 45853, 45863, 45869, - 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, 45989, - 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, - 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, - 46199, 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, - 46307, 46309, 46327, 46337, 46349, 46351, 46381, 46399, 46411, - 46439, 46441, 46447, 46451, 46457, 46471, 46477, 46489, 46499, - 46507, 46511, 46523, 46549, 46559, 46567, 46573, 46589, 46591, - 46601, 46619, 46633, 46639, 46643, 46649, 46663, 46679, 46681, - 46687, 46691, 46703, 46723, 46727, 46747, 46751, 46757, 46769, - 46771, 46807, 46811, 46817, 46819, 46829, 46831, 46853, 46861, - 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 46997, - 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, - 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, - 47221, 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, - 47309, 47317, 47339, 47351, 47353, 47363, 47381, 47387, 47389, - 47407, 47417, 47419, 47431, 47441, 47459, 47491, 47497, 47501, - 47507, 47513, 47521, 47527, 47533, 47543, 47563, 47569, 47581, - 47591, 47599, 47609, 47623, 47629, 47639, 47653, 47657, 47659, - 47681, 47699, 47701, 47711, 47713, 47717, 47737, 47741, 47743, - 47777, 47779, 47791, 47797, 47807, 47809, 47819, 47837, 47843, - 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, 47947, - 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, - 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, - 48179, 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, - 48281, 48299, 48311, 48313, 48337, 48341, 48353, 48371, 48383, - 48397, 48407, 48409, 48413, 48437, 48449, 48463, 48473, 48479, - 48481, 48487, 48491, 48497, 48523, 48527, 48533, 48539, 48541, - 48563, 48571, 48589, 48593, 48611, 48619, 48623, 48647, 48649, - 48661, 48673, 48677, 48679, 48731, 48733, 48751, 48757, 48761, - 48767, 48779, 48781, 48787, 48799, 48809, 48817, 48821, 48823, - 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, 48947, - 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, - 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, - 49123, 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, - 49207, 49211, 49223, 49253, 49261, 49277, 49279, 49297, 49307, - 49331, 49333, 49339, 49363, 49367, 49369, 49391, 49393, 49409, - 49411, 49417, 49429, 49433, 49451, 49459, 49463, 49477, 49481, - 49499, 49523, 49529, 49531, 49537, 49547, 49549, 49559, 49597, - 49603, 49613, 49627, 49633, 49639, 49663, 49667, 49669, 49681, - 49697, 49711, 49727, 49739, 49741, 49747, 49757, 49783, 49787, - 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, 49871, - 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, - 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, - 50069, 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, - 50131, 50147, 50153, 50159, 50177, 50207, 50221, 50227, 50231, - 50261, 50263, 50273, 50287, 50291, 50311, 50321, 50329, 50333, - 50341, 50359, 50363, 50377, 50383, 50387, 50411, 50417, 50423, - 50441, 50459, 50461, 50497, 50503, 50513, 50527, 50539, 50543, - 50549, 50551, 50581, 50587, 50591, 50593, 50599, 50627, 50647, - 50651, 50671, 50683, 50707, 50723, 50741, 50753, 50767, 50773, - 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, 50873, - 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, - 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, - 51109, 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, - 51199, 51203, 51217, 51229, 51239, 51241, 51257, 51263, 51283, - 51287, 51307, 51329, 51341, 51343, 51347, 51349, 51361, 51383, - 51407, 51413, 51419, 51421, 51427, 51431, 51437, 51439, 51449, - 51461, 51473, 51479, 51481, 51487, 51503, 51511, 51517, 51521, - 51539, 51551, 51563, 51577, 51581, 51593, 51599, 51607, 51613, - 51631, 51637, 51647, 51659, 51673, 51679, 51683, 51691, 51713, - 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 51817, - 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, - 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, - 52009, 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, - 52121, 52127, 52147, 52153, 52163, 52177, 52181, 52183, 52189, - 52201, 52223, 52237, 52249, 52253, 52259, 52267, 52289, 52291, - 52301, 52313, 52321, 52361, 52363, 52369, 52379, 52387, 52391, - 52433, 52453, 52457, 52489, 52501, 52511, 52517, 52529, 52541, - 52543, 52553, 52561, 52567, 52571, 52579, 52583, 52609, 52627, - 52631, 52639, 52667, 52673, 52691, 52697, 52709, 52711, 52721, - 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 52817, - 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, - 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, - 53017, 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, - 53113, 53117, 53129, 53147, 53149, 53161, 53171, 53173, 53189, - 53197, 53201, 53231, 53233, 53239, 53267, 53269, 53279, 53281, - 53299, 53309, 53323, 53327, 53353, 53359, 53377, 53381, 53401, - 53407, 53411, 53419, 53437, 53441, 53453, 53479, 53503, 53507, - 53527, 53549, 53551, 53569, 53591, 53593, 53597, 53609, 53611, - 53617, 53623, 53629, 53633, 53639, 53653, 53657, 53681, 53693, - 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, 53791, - 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, - 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, - 53993, 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, - 54101, 54121, 54133, 54139, 54151, 54163, 54167, 54181, 54193, - 54217, 54251, 54269, 54277, 54287, 54293, 54311, 54319, 54323, - 54331, 54347, 54361, 54367, 54371, 54377, 54401, 54403, 54409, - 54413, 54419, 54421, 54437, 54443, 54449, 54469, 54493, 54497, - 54499, 54503, 54517, 54521, 54539, 54541, 54547, 54559, 54563, - 54577, 54581, 54583, 54601, 54617, 54623, 54629, 54631, 54647, - 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, 54767, - 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, - 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, - 54983, 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, - 55079, 55103, 55109, 55117, 55127, 55147, 55163, 55171, 55201, - 55207, 55213, 55217, 55219, 55229, 55243, 55249, 55259, 55291, - 55313, 55331, 55333, 55337, 55339, 55343, 55351, 55373, 55381, - 55399, 55411, 55439, 55441, 55457, 55469, 55487, 55501, 55511, - 55529, 55541, 55547, 55579, 55589, 55603, 55609, 55619, 55621, - 55631, 55633, 55639, 55661, 55663, 55667, 55673, 55681, 55691, - 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, 55799, - 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, - 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, - 55949, 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, - 56081, 56087, 56093, 56099, 56101, 56113, 56123, 56131, 56149, - 56167, 56171, 56179, 56197, 56207, 56209, 56237, 56239, 56249, - 56263, 56267, 56269, 56299, 56311, 56333, 56359, 56369, 56377, - 56383, 56393, 56401, 56417, 56431, 56437, 56443, 56453, 56467, - 56473, 56477, 56479, 56489, 56501, 56503, 56509, 56519, 56527, - 56531, 56533, 56543, 56569, 56591, 56597, 56599, 56611, 56629, - 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, 56713, - 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, - 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, - 56909, 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, - 56983, 56989, 56993, 56999, 57037, 57041, 57047, 57059, 57073, - 57077, 57089, 57097, 57107, 57119, 57131, 57139, 57143, 57149, - 57163, 57173, 57179, 57191, 57193, 57203, 57221, 57223, 57241, - 57251, 57259, 57269, 57271, 57283, 57287, 57301, 57329, 57331, - 57347, 57349, 57367, 57373, 57383, 57389, 57397, 57413, 57427, - 57457, 57467, 57487, 57493, 57503, 57527, 57529, 57557, 57559, - 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 57667, - 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, - 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, - 57839, 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, - 57943, 57947, 57973, 57977, 57991, 58013, 58027, 58031, 58043, - 58049, 58057, 58061, 58067, 58073, 58099, 58109, 58111, 58129, - 58147, 58151, 58153, 58169, 58171, 58189, 58193, 58199, 58207, - 58211, 58217, 58229, 58231, 58237, 58243, 58271, 58309, 58313, - 58321, 58337, 58363, 58367, 58369, 58379, 58391, 58393, 58403, - 58411, 58417, 58427, 58439, 58441, 58451, 58453, 58477, 58481, - 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, 58603, - 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, - 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, - 58889, 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, - 58963, 58967, 58979, 58991, 58997, 59009, 59011, 59021, 59023, - 59029, 59051, 59053, 59063, 59069, 59077, 59083, 59093, 59107, - 59113, 59119, 59123, 59141, 59149, 59159, 59167, 59183, 59197, - 59207, 59209, 59219, 59221, 59233, 59239, 59243, 59263, 59273, - 59281, 59333, 59341, 59351, 59357, 59359, 59369, 59377, 59387, - 59393, 59399, 59407, 59417, 59419, 59441, 59443, 59447, 59453, - 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, 59561, - 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, - 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, - 59747, 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, - 59879, 59887, 59921, 59929, 59951, 59957, 59971, 59981, 59999, - 60013, 60017, 60029, 60037, 60041, 60077, 60083, 60089, 60091, - 60101, 60103, 60107, 60127, 60133, 60139, 60149, 60161, 60167, - 60169, 60209, 60217, 60223, 60251, 60257, 60259, 60271, 60289, - 60293, 60317, 60331, 60337, 60343, 60353, 60373, 60383, 60397, - 60413, 60427, 60443, 60449, 60457, 60493, 60497, 60509, 60521, - 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, 60631, - 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, - 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, - 60811, 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, - 60917, 60919, 60923, 60937, 60943, 60953, 60961, 61001, 61007, - 61027, 61031, 61043, 61051, 61057, 61091, 61099, 61121, 61129, - 61141, 61151, 61153, 61169, 61211, 61223, 61231, 61253, 61261, - 61283, 61291, 61297, 61331, 61333, 61339, 61343, 61357, 61363, - 61379, 61381, 61403, 61409, 61417, 61441, 61463, 61469, 61471, - 61483, 61487, 61493, 61507, 61511, 61519, 61543, 61547, 61553, - 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, 61637, - 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, - 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, - 61861, 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, - 61979, 61981, 61987, 61991, 62003, 62011, 62017, 62039, 62047, - 62053, 62057, 62071, 62081, 62099, 62119, 62129, 62131, 62137, - 62141, 62143, 62171, 62189, 62191, 62201, 62207, 62213, 62219, - 62233, 62273, 62297, 62299, 62303, 62311, 62323, 62327, 62347, - 62351, 62383, 62401, 62417, 62423, 62459, 62467, 62473, 62477, - 62483, 62497, 62501, 62507, 62533, 62539, 62549, 62563, 62581, - 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 62659, - 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, - 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, - 62903, 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, - 62987, 62989, 63029, 63031, 63059, 63067, 63073, 63079, 63097, - 63103, 63113, 63127, 63131, 63149, 63179, 63197, 63199, 63211, - 63241, 63247, 63277, 63281, 63299, 63311, 63313, 63317, 63331, - 63337, 63347, 63353, 63361, 63367, 63377, 63389, 63391, 63397, - 63409, 63419, 63421, 63439, 63443, 63463, 63467, 63473, 63487, - 63493, 63499, 63521, 63527, 63533, 63541, 63559, 63577, 63587, - 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 63649, - 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, - 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, - 63809, 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, - 63913, 63929, 63949, 63977, 63997, 64007, 64013, 64019, 64033, - 64037, 64063, 64067, 64081, 64091, 64109, 64123, 64151, 64153, - 64157, 64171, 64187, 64189, 64217, 64223, 64231, 64237, 64271, - 64279, 64283, 64301, 64303, 64319, 64327, 64333, 64373, 64381, - 64399, 64403, 64433, 64439, 64451, 64453, 64483, 64489, 64499, - 64513, 64553, 64567, 64577, 64579, 64591, 64601, 64609, 64613, - 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, 64709, - 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, - 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, - 64937, 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, - 65053, 65063, 65071, 65089, 65099, 65101, 65111, 65119, 65123, - 65129, 65141, 65147, 65167, 65171, 65173, 65179, 65183, 65203, - 65213, 65239, 65257, 65267, 65269, 65287, 65293, 65309, 65323, - 65327, 65353, 65357, 65371, 65381, 65393, 65407, 65413, 65419, - 65423, 65437, 65447, 65449, 65479, 65497, 65519, 65521, 65537, - 65539, 65543, 65551, 65557, 65563, 65579, 65581, 65587, 65599, - 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, 65687, - 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, - 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, - 65867, 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, - 65981, 65983, 65993, 66029, 66037, 66041, 66047, 66067, 66071, - 66083, 66089, 66103, 66107, 66109, 66137, 66161, 66169, 66173, - 66179, 66191, 66221, 66239, 66271, 66293, 66301, 66337, 66343, - 66347, 66359, 66361, 66373, 66377, 66383, 66403, 66413, 66431, - 66449, 66457, 66463, 66467, 66491, 66499, 66509, 66523, 66529, - 66533, 66541, 66553, 66569, 66571, 66587, 66593, 66601, 66617, - 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, 66733, - 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, - 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, - 66943, 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, - 67043, 67049, 67057, 67061, 67073, 67079, 67103, 67121, 67129, - 67139, 67141, 67153, 67157, 67169, 67181, 67187, 67189, 67211, - 67213, 67217, 67219, 67231, 67247, 67261, 67271, 67273, 67289, - 67307, 67339, 67343, 67349, 67369, 67391, 67399, 67409, 67411, - 67421, 67427, 67429, 67433, 67447, 67453, 67477, 67481, 67489, - 67493, 67499, 67511, 67523, 67531, 67537, 67547, 67559, 67567, - 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, 67679, - 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, - 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, - 67867, 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, - 67957, 67961, 67967, 67979, 67987, 67993, 68023, 68041, 68053, - 68059, 68071, 68087, 68099, 68111, 68113, 68141, 68147, 68161, - 68171, 68207, 68209, 68213, 68219, 68227, 68239, 68261, 68279, - 68281, 68311, 68329, 68351, 68371, 68389, 68399, 68437, 68443, - 68447, 68449, 68473, 68477, 68483, 68489, 68491, 68501, 68507, - 68521, 68531, 68539, 68543, 68567, 68581, 68597, 68611, 68633, - 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, 68729, - 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, - 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, - 68917, 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, - 69031, 69061, 69067, 69073, 69109, 69119, 69127, 69143, 69149, - 69151, 69163, 69191, 69193, 69197, 69203, 69221, 69233, 69239, - 69247, 69257, 69259, 69263, 69313, 69317, 69337, 69341, 69371, - 69379, 69383, 69389, 69401, 69403, 69427, 69431, 69439, 69457, - 69463, 69467, 69473, 69481, 69491, 69493, 69497, 69499, 69539, - 69557, 69593, 69623, 69653, 69661, 69677, 69691, 69697, 69709, - 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, 69827, - 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, - 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, - 70039, 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, - 70123, 70139, 70141, 70157, 70163, 70177, 70181, 70183, 70199, - 70201, 70207, 70223, 70229, 70237, 70241, 70249, 70271, 70289, - 70297, 70309, 70313, 70321, 70327, 70351, 70373, 70379, 70381, - 70393, 70423, 70429, 70439, 70451, 70457, 70459, 70481, 70487, - 70489, 70501, 70507, 70529, 70537, 70549, 70571, 70573, 70583, - 70589, 70607, 70619, 70621, 70627, 70639, 70657, 70663, 70667, - 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, 70823, - 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, - 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, - 70981, 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, - 71081, 71089, 71119, 71129, 71143, 71147, 71153, 71161, 71167, - 71171, 71191, 71209, 71233, 71237, 71249, 71257, 71261, 71263, - 71287, 71293, 71317, 71327, 71329, 71333, 71339, 71341, 71347, - 71353, 71359, 71363, 71387, 71389, 71399, 71411, 71413, 71419, - 71429, 71437, 71443, 71453, 71471, 71473, 71479, 71483, 71503, - 71527, 71537, 71549, 71551, 71563, 71569, 71593, 71597, 71633, - 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, 71719, - 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, - 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, - 71933, 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, - 72019, 72031, 72043, 72047, 72053, 72073, 72077, 72089, 72091, - 72101, 72103, 72109, 72139, 72161, 72167, 72169, 72173, 72211, - 72221, 72223, 72227, 72229, 72251, 72253, 72269, 72271, 72277, - 72287, 72307, 72313, 72337, 72341, 72353, 72367, 72379, 72383, - 72421, 72431, 72461, 72467, 72469, 72481, 72493, 72497, 72503, - 72533, 72547, 72551, 72559, 72577, 72613, 72617, 72623, 72643, - 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, 72707, - 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, - 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, - 72923, 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, - 73009, 73013, 73019, 73037, 73039, 73043, 73061, 73063, 73079, - 73091, 73121, 73127, 73133, 73141, 73181, 73189, 73237, 73243, - 73259, 73277, 73291, 73303, 73309, 73327, 73331, 73351, 73361, - 73363, 73369, 73379, 73387, 73417, 73421, 73433, 73453, 73459, - 73471, 73477, 73483, 73517, 73523, 73529, 73547, 73553, 73561, - 73571, 73583, 73589, 73597, 73607, 73609, 73613, 73637, 73643, - 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, 73727, - 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, - 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, - 73973, 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, - 74093, 74099, 74101, 74131, 74143, 74149, 74159, 74161, 74167, - 74177, 74189, 74197, 74201, 74203, 74209, 74219, 74231, 74257, - 74279, 74287, 74293, 74297, 74311, 74317, 74323, 74353, 74357, - 74363, 74377, 74381, 74383, 74411, 74413, 74419, 74441, 74449, - 74453, 74471, 74489, 74507, 74509, 74521, 74527, 74531, 74551, - 74561, 74567, 74573, 74587, 74597, 74609, 74611, 74623, 74653, - 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, 74747, - 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, - 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, - 74929, 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, - 75041, 75079, 75083, 75109, 75133, 75149, 75161, 75167, 75169, - 75181, 75193, 75209, 75211, 75217, 75223, 75227, 75239, 75253, - 75269, 75277, 75289, 75307, 75323, 75329, 75337, 75347, 75353, - 75367, 75377, 75389, 75391, 75401, 75403, 75407, 75431, 75437, - 75479, 75503, 75511, 75521, 75527, 75533, 75539, 75541, 75553, - 75557, 75571, 75577, 75583, 75611, 75617, 75619, 75629, 75641, - 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, 75721, - 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, - 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, - 75979, 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, - 76079, 76081, 76091, 76099, 76103, 76123, 76129, 76147, 76157, - 76159, 76163, 76207, 76213, 76231, 76243, 76249, 76253, 76259, - 76261, 76283, 76289, 76303, 76333, 76343, 76367, 76369, 76379, - 76387, 76403, 76421, 76423, 76441, 76463, 76471, 76481, 76487, - 76493, 76507, 76511, 76519, 76537, 76541, 76543, 76561, 76579, - 76597, 76603, 76607, 76631, 76649, 76651, 76667, 76673, 76679, - 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, 76801, - 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, - 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, - 77023, 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, - 77141, 77153, 77167, 77171, 77191, 77201, 77213, 77237, 77239, - 77243, 77249, 77261, 77263, 77267, 77269, 77279, 77291, 77317, - 77323, 77339, 77347, 77351, 77359, 77369, 77377, 77383, 77417, - 77419, 77431, 77447, 77471, 77477, 77479, 77489, 77491, 77509, - 77513, 77521, 77527, 77543, 77549, 77551, 77557, 77563, 77569, - 77573, 77587, 77591, 77611, 77617, 77621, 77641, 77647, 77659, - 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, 77731, - 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, - 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, - 77977, 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, - 78079, 78101, 78121, 78137, 78139, 78157, 78163, 78167, 78173, - 78179, 78191, 78193, 78203, 78229, 78233, 78241, 78259, 78277, - 78283, 78301, 78307, 78311, 78317, 78341, 78347, 78367, 78401, - 78427, 78437, 78439, 78467, 78479, 78487, 78497, 78509, 78511, - 78517, 78539, 78541, 78553, 78569, 78571, 78577, 78583, 78593, - 78607, 78623, 78643, 78649, 78653, 78691, 78697, 78707, 78713, - 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, 78809, - 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, - 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, - 79063, 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, - 79159, 79181, 79187, 79193, 79201, 79229, 79231, 79241, 79259, - 79273, 79279, 79283, 79301, 79309, 79319, 79333, 79337, 79349, - 79357, 79367, 79379, 79393, 79397, 79399, 79411, 79423, 79427, - 79433, 79451, 79481, 79493, 79531, 79537, 79549, 79559, 79561, - 79579, 79589, 79601, 79609, 79613, 79621, 79627, 79631, 79633, - 79657, 79669, 79687, 79691, 79693, 79697, 79699, 79757, 79769, - 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, 79843, - 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, - 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, - 80051, 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, - 80167, 80173, 80177, 80191, 80207, 80209, 80221, 80231, 80233, - 80239, 80251, 80263, 80273, 80279, 80287, 80309, 80317, 80329, - 80341, 80347, 80363, 80369, 80387, 80407, 80429, 80447, 80449, - 80471, 80473, 80489, 80491, 80513, 80527, 80537, 80557, 80567, - 80599, 80603, 80611, 80621, 80627, 80629, 80651, 80657, 80669, - 80671, 80677, 80681, 80683, 80687, 80701, 80713, 80737, 80747, - 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, 80819, - 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, - 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, - 81023, 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, - 81097, 81101, 81119, 81131, 81157, 81163, 81173, 81181, 81197, - 81199, 81203, 81223, 81233, 81239, 81281, 81283, 81293, 81299, - 81307, 81331, 81343, 81349, 81353, 81359, 81371, 81373, 81401, - 81409, 81421, 81439, 81457, 81463, 81509, 81517, 81527, 81533, - 81547, 81551, 81553, 81559, 81563, 81569, 81611, 81619, 81629, - 81637, 81647, 81649, 81667, 81671, 81677, 81689, 81701, 81703, - 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, 81817, - 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, - 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, - 82009, 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, - 82129, 82139, 82141, 82153, 82163, 82171, 82183, 82189, 82193, - 82207, 82217, 82219, 82223, 82231, 82237, 82241, 82261, 82267, - 82279, 82301, 82307, 82339, 82349, 82351, 82361, 82373, 82387, - 82393, 82421, 82457, 82463, 82469, 82471, 82483, 82487, 82493, - 82499, 82507, 82529, 82531, 82549, 82559, 82561, 82567, 82571, - 82591, 82601, 82609, 82613, 82619, 82633, 82651, 82657, 82699, - 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, 82787, - 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, - 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, - 83047, 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, - 83137, 83177, 83203, 83207, 83219, 83221, 83227, 83231, 83233, - 83243, 83257, 83267, 83269, 83273, 83299, 83311, 83339, 83341, - 83357, 83383, 83389, 83399, 83401, 83407, 83417, 83423, 83431, - 83437, 83443, 83449, 83459, 83471, 83477, 83497, 83537, 83557, - 83561, 83563, 83579, 83591, 83597, 83609, 83617, 83621, 83639, - 83641, 83653, 83663, 83689, 83701, 83717, 83719, 83737, 83761, - 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, 83873, - 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, - 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, - 84127, 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, - 84211, 84221, 84223, 84229, 84239, 84247, 84263, 84299, 84307, - 84313, 84317, 84319, 84347, 84349, 84377, 84389, 84391, 84401, - 84407, 84421, 84431, 84437, 84443, 84449, 84457, 84463, 84467, - 84481, 84499, 84503, 84509, 84521, 84523, 84533, 84551, 84559, - 84589, 84629, 84631, 84649, 84653, 84659, 84673, 84691, 84697, - 84701, 84713, 84719, 84731, 84737, 84751, 84761, 84787, 84793, - 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, 84919, - 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, - 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, - 85121, 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, - 85229, 85237, 85243, 85247, 85259, 85297, 85303, 85313, 85331, - 85333, 85361, 85363, 85369, 85381, 85411, 85427, 85429, 85439, - 85447, 85451, 85453, 85469, 85487, 85513, 85517, 85523, 85531, - 85549, 85571, 85577, 85597, 85601, 85607, 85619, 85621, 85627, - 85639, 85643, 85661, 85667, 85669, 85691, 85703, 85711, 85717, - 85733, 85751, 85781, 85793, 85817, 85819, 85829, 85831, 85837, - 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, 85991, - 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, - 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, - 86197, 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, - 86287, 86291, 86293, 86297, 86311, 86323, 86341, 86351, 86353, - 86357, 86369, 86371, 86381, 86389, 86399, 86413, 86423, 86441, - 86453, 86461, 86467, 86477, 86491, 86501, 86509, 86531, 86533, - 86539, 86561, 86573, 86579, 86587, 86599, 86627, 86629, 86677, - 86689, 86693, 86711, 86719, 86729, 86743, 86753, 86767, 86771, - 86783, 86813, 86837, 86843, 86851, 86857, 86861, 86869, 86923, - 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, 87011, - 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, - 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, - 87223, 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, - 87317, 87323, 87337, 87359, 87383, 87403, 87407, 87421, 87427, - 87433, 87443, 87473, 87481, 87491, 87509, 87511, 87517, 87523, - 87539, 87541, 87547, 87553, 87557, 87559, 87583, 87587, 87589, - 87613, 87623, 87629, 87631, 87641, 87643, 87649, 87671, 87679, - 87683, 87691, 87697, 87701, 87719, 87721, 87739, 87743, 87751, - 87767, 87793, 87797, 87803, 87811, 87833, 87853, 87869, 87877, - 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, 87973, - 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, - 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, - 88259, 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, - 88397, 88411, 88423, 88427, 88463, 88469, 88471, 88493, 88499, - 88513, 88523, 88547, 88589, 88591, 88607, 88609, 88643, 88651, - 88657, 88661, 88663, 88667, 88681, 88721, 88729, 88741, 88747, - 88771, 88789, 88793, 88799, 88801, 88807, 88811, 88813, 88817, - 88819, 88843, 88853, 88861, 88867, 88873, 88883, 88897, 88903, - 88919, 88937, 88951, 88969, 88993, 88997, 89003, 89009, 89017, - 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, 89101, - 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, - 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, - 89317, 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, - 89417, 89431, 89443, 89449, 89459, 89477, 89491, 89501, 89513, - 89519, 89521, 89527, 89533, 89561, 89563, 89567, 89591, 89597, - 89599, 89603, 89611, 89627, 89633, 89653, 89657, 89659, 89669, - 89671, 89681, 89689, 89753, 89759, 89767, 89779, 89783, 89797, - 89809, 89819, 89821, 89833, 89839, 89849, 89867, 89891, 89897, - 89899, 89909, 89917, 89923, 89939, 89959, 89963, 89977, 89983, - 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, 90053, - 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, - 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, - 90239, 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, - 90371, 90373, 90379, 90397, 90401, 90403, 90407, 90437, 90439, - 90469, 90473, 90481, 90499, 90511, 90523, 90527, 90529, 90533, - 90547, 90583, 90599, 90617, 90619, 90631, 90641, 90647, 90659, - 90677, 90679, 90697, 90703, 90709, 90731, 90749, 90787, 90793, - 90803, 90821, 90823, 90833, 90841, 90847, 90863, 90887, 90901, - 90907, 90911, 90917, 90931, 90947, 90971, 90977, 90989, 90997, - 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, 91127, - 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, - 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, - 91303, 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, - 91397, 91411, 91423, 91433, 91453, 91457, 91459, 91463, 91493, - 91499, 91513, 91529, 91541, 91571, 91573, 91577, 91583, 91591, - 91621, 91631, 91639, 91673, 91691, 91703, 91711, 91733, 91753, - 91757, 91771, 91781, 91801, 91807, 91811, 91813, 91823, 91837, - 91841, 91867, 91873, 91909, 91921, 91939, 91943, 91951, 91957, - 91961, 91967, 91969, 91997, 92003, 92009, 92033, 92041, 92051, - 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, 92177, - 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, - 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, - 92363, 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, - 92419, 92431, 92459, 92461, 92467, 92479, 92489, 92503, 92507, - 92551, 92557, 92567, 92569, 92581, 92593, 92623, 92627, 92639, - 92641, 92647, 92657, 92669, 92671, 92681, 92683, 92693, 92699, - 92707, 92717, 92723, 92737, 92753, 92761, 92767, 92779, 92789, - 92791, 92801, 92809, 92821, 92831, 92849, 92857, 92861, 92863, - 92867, 92893, 92899, 92921, 92927, 92941, 92951, 92957, 92959, - 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, 93089, - 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, - 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, - 93281, 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, - 93377, 93383, 93407, 93419, 93427, 93463, 93479, 93481, 93487, - 93491, 93493, 93497, 93503, 93523, 93529, 93553, 93557, 93559, - 93563, 93581, 93601, 93607, 93629, 93637, 93683, 93701, 93703, - 93719, 93739, 93761, 93763, 93787, 93809, 93811, 93827, 93851, - 93871, 93887, 93889, 93893, 93901, 93911, 93913, 93923, 93937, - 93941, 93949, 93967, 93971, 93979, 93983, 93997, 94007, 94009, - 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, 94117, - 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, - 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, - 94349, 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, - 94441, 94447, 94463, 94477, 94483, 94513, 94529, 94531, 94541, - 94543, 94547, 94559, 94561, 94573, 94583, 94597, 94603, 94613, - 94621, 94649, 94651, 94687, 94693, 94709, 94723, 94727, 94747, - 94771, 94777, 94781, 94789, 94793, 94811, 94819, 94823, 94837, - 94841, 94847, 94849, 94873, 94889, 94903, 94907, 94933, 94949, - 94951, 94961, 94993, 94999, 95003, 95009, 95021, 95027, 95063, - 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, 95131, - 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, - 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, - 95317, 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, - 95429, 95441, 95443, 95461, 95467, 95471, 95479, 95483, 95507, - 95527, 95531, 95539, 95549, 95561, 95569, 95581, 95597, 95603, - 95617, 95621, 95629, 95633, 95651, 95701, 95707, 95713, 95717, - 95723, 95731, 95737, 95747, 95773, 95783, 95789, 95791, 95801, - 95803, 95813, 95819, 95857, 95869, 95873, 95881, 95891, 95911, - 95917, 95923, 95929, 95947, 95957, 95959, 95971, 95987, 95989, - 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, 96137, - 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, - 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, - 96331, 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, - 96457, 96461, 96469, 96479, 96487, 96493, 96497, 96517, 96527, - 96553, 96557, 96581, 96587, 96589, 96601, 96643, 96661, 96667, - 96671, 96697, 96703, 96731, 96737, 96739, 96749, 96757, 96763, - 96769, 96779, 96787, 96797, 96799, 96821, 96823, 96827, 96847, - 96851, 96857, 96893, 96907, 96911, 96931, 96953, 96959, 96973, - 96979, 96989, 96997, 97001, 97003, 97007, 97021, 97039, 97073, - 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, 97171, - 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, - 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, - 97429, 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, - 97547, 97549, 97553, 97561, 97571, 97577, 97579, 97583, 97607, - 97609, 97613, 97649, 97651, 97673, 97687, 97711, 97729, 97771, - 97777, 97787, 97789, 97813, 97829, 97841, 97843, 97847, 97849, - 97859, 97861, 97871, 97879, 97883, 97919, 97927, 97931, 97943, - 97961, 97967, 97973, 97987, 98009, 98011, 98017, 98041, 98047, - 98057, 98081, 98101, 98123, 98129, 98143, 98179, 98207, 98213, - 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, 98321, - 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, - 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, - 98507, 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, - 98627, 98639, 98641, 98663, 98669, 98689, 98711, 98713, 98717, - 98729, 98731, 98737, 98773, 98779, 98801, 98807, 98809, 98837, - 98849, 98867, 98869, 98873, 98887, 98893, 98897, 98899, 98909, - 98911, 98927, 98929, 98939, 98947, 98953, 98963, 98981, 98993, - 98999, 99013, 99017, 99023, 99041, 99053, 99079, 99083, 99089, - 99103, 99109, 99119, 99131, 99133, 99137, 99139, 99149, 99173, - 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, 99277, - 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, - 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, - 99529, 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, - 99623, 99643, 99661, 99667, 99679, 99689, 99707, 99709, 99713, - 99719, 99721, 99733, 99761, 99767, 99787, 99793, 99809, 99817, - 99823, 99829, 99833, 99839, 99859, 99871, 99877, 99881, 99901, - 99907, 99923, 99929, 99961, 99971, 99989, 99991, - }; diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp index f6b061a5bbc63..e56ce6dd2637f 100644 --- a/src/rt/rust_sched_loop.cpp +++ b/src/rt/rust_sched_loop.cpp @@ -100,6 +100,7 @@ rust_sched_loop::kill_all_tasks() { size_t rust_sched_loop::number_of_live_tasks() { + lock.must_have_lock(); return running_tasks.length() + blocked_tasks.length(); } @@ -148,14 +149,10 @@ rust_sched_loop::release_task(rust_task *task) { rust_task * rust_sched_loop::schedule_task() { lock.must_have_lock(); - assert(this); if (running_tasks.length() > 0) { size_t k = isaac_rand(&rctx); - // Look around for a runnable task, starting at k. - for(size_t j = 0; j < running_tasks.length(); ++j) { - size_t i = (j + k) % running_tasks.length(); - return (rust_task *)running_tasks[i]; - } + size_t i = k % running_tasks.length(); + return (rust_task *)running_tasks[i]; } return NULL; } diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index c916de111235c..8197d9c5450e8 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -158,8 +158,7 @@ upcall_s_exchange_malloc(s_exchange_malloc_args *args) { LOG_UPCALL_ENTRY(task); size_t total_size = get_box_size(args->size, args->td->align); - // FIXME--does this have to be calloc? (Issue #2682) - void *p = task->kernel->calloc(total_size, "exchange malloc"); + void *p = task->kernel->malloc(total_size, "exchange malloc"); rust_opaque_box *header = static_cast(p); header->ref_count = -1; // This is not ref counted @@ -234,8 +233,7 @@ upcall_s_malloc(s_malloc_args *args) { LOG_UPCALL_ENTRY(task); LOG(task, mem, "upcall malloc(0x%" PRIxPTR ")", args->td); - // FIXME--does this have to be calloc? (Issue #2682) - rust_opaque_box *box = task->boxed.calloc(args->td, args->size); + rust_opaque_box *box = task->boxed.malloc(args->td, args->size); void *body = box_body(box); debug::maybe_track_origin(task, box); diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index bb00f04a6f976..b01294062a627 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -281,7 +281,7 @@ void *RustMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name, if (Name == "mknod") return (void*)(intptr_t)&mknod; #endif - if (Name == "__morestack") return &__morestack; + if (Name == "__morestack" || Name == "___morestack") return &__morestack; const char *NameStr = Name.c_str(); diff --git a/src/test/auxiliary/cci_capture_clause.rs b/src/test/auxiliary/cci_capture_clause.rs index a558de3387629..c22047287e624 100644 --- a/src/test/auxiliary/cci_capture_clause.rs +++ b/src/test/auxiliary/cci_capture_clause.rs @@ -8,13 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[legacy_exports]; - -export foo; - use core::oldcomm::*; -fn foo(x: T) -> Port { +pub fn foo(x: T) -> Port { let p = Port(); let c = Chan(&p); do task::spawn() |copy c, copy x| { diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs index 032a01178f3bb..1225e2fe8a747 100644 --- a/src/test/auxiliary/cci_class_cast.rs +++ b/src/test/auxiliary/cci_class_cast.rs @@ -8,21 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[legacy_exports]; +use core::to_str::*; -use to_str::*; -use to_str::ToStr; - -mod kitty { - #[legacy_exports]; - -struct cat { - priv mut meows : uint, - mut how_hungry : int, - name : ~str, -} +pub mod kitty { + pub struct cat { + priv mut meows : uint, + mut how_hungry : int, + name : ~str, + } - impl cat : ToStr { + pub impl cat : ToStr { pure fn to_str() -> ~str { copy self.name } } @@ -37,7 +32,7 @@ struct cat { } - impl cat { + pub impl cat { fn speak() { self.meow(); } fn eat() -> bool { @@ -52,14 +47,14 @@ struct cat { } } } -fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { - cat { - meows: in_x, - how_hungry: in_y, - name: in_name - } -} + pub fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { + cat { + meows: in_x, + how_hungry: in_y, + name: in_name + } + } } diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs index d55302481a9ca..291a506c4ebb0 100644 --- a/src/test/auxiliary/cci_nested_lib.rs +++ b/src/test/auxiliary/cci_nested_lib.rs @@ -14,7 +14,7 @@ use dvec::DVec; type entry = {key: A, value: B}; -type alist = { eq_fn: fn@(A,A) -> bool, data: DVec> }; +struct alist { eq_fn: fn@(A,A) -> bool, data: DVec> } fn alist_add(lst: alist, k: A, v: B) { lst.data.push({key:k, value:v}); @@ -31,12 +31,12 @@ fn alist_get(lst: alist, k: A) -> B { #[inline] fn new_int_alist() -> alist { fn eq_int(&&a: int, &&b: int) -> bool { a == b } - return {eq_fn: eq_int, data: DVec()}; + return alist {eq_fn: eq_int, data: DVec()}; } #[inline] fn new_int_alist_2() -> alist { #[inline] fn eq_int(&&a: int, &&b: int) -> bool { a == b } - return {eq_fn: eq_int, data: DVec()}; + return alist {eq_fn: eq_int, data: DVec()}; } diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs index 71425659584fd..197ad8402349b 100644 --- a/src/test/auxiliary/issue-2631-a.rs +++ b/src/test/auxiliary/issue-2631-a.rs @@ -10,17 +10,15 @@ #[link(name = "req")]; #[crate_type = "lib"]; -#[legacy_exports]; extern mod std; -use dvec::*; -use dvec::DVec; +use core::dvec::*; use std::map::HashMap; -type header_map = HashMap<~str, @DVec<@~str>>; +pub type header_map = HashMap<~str, @DVec<@~str>>; // the unused ty param is necessary so this gets monomorphized -fn request(req: header_map) { +pub fn request(req: header_map) { let _x = copy *(copy *req.get(~"METHOD"))[0u]; } diff --git a/src/test/auxiliary/noexporttypelib.rs b/src/test/auxiliary/noexporttypelib.rs index 57e2e53ac7255..4e9e3688ecdbf 100644 --- a/src/test/auxiliary/noexporttypelib.rs +++ b/src/test/auxiliary/noexporttypelib.rs @@ -8,7 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[legacy_exports]; -export foo; type oint = Option; -fn foo() -> oint { Some(3) } +pub fn foo() -> oint { Some(3) } diff --git a/src/test/auxiliary/static-methods-crate.rs b/src/test/auxiliary/static-methods-crate.rs index 0ae0423e6be69..530309536d9df 100644 --- a/src/test/auxiliary/static-methods-crate.rs +++ b/src/test/auxiliary/static-methods-crate.rs @@ -12,10 +12,8 @@ vers = "0.1")]; #[crate_type = "lib"]; -#[legacy_exports]; -export read, readMaybe; -trait read { +pub trait read { static fn readMaybe(s: ~str) -> Option; } @@ -35,7 +33,7 @@ impl bool: read { } } -fn read(s: ~str) -> T { +pub fn read(s: ~str) -> T { match read::readMaybe(s) { Some(x) => x, _ => fail ~"read failed!" diff --git a/src/test/auxiliary/static_fn_inline_xc_aux.rs b/src/test/auxiliary/static_fn_inline_xc_aux.rs index c85ff320bc82d..2a1cce54783fa 100644 --- a/src/test/auxiliary/static_fn_inline_xc_aux.rs +++ b/src/test/auxiliary/static_fn_inline_xc_aux.rs @@ -16,7 +16,7 @@ pub mod num { } pub mod float { - impl float: num::Num2 { + impl float: ::num::Num2 { #[inline] static pure fn from_int2(n: int) -> float { return n as float; } } diff --git a/src/test/auxiliary/static_fn_trait_xc_aux.rs b/src/test/auxiliary/static_fn_trait_xc_aux.rs index e67d46553cfc2..40659da8dae1b 100644 --- a/src/test/auxiliary/static_fn_trait_xc_aux.rs +++ b/src/test/auxiliary/static_fn_trait_xc_aux.rs @@ -5,7 +5,7 @@ pub mod num { } pub mod float { - impl float: num::Num2 { + impl float: ::num::Num2 { static pure fn from_int2(n: int) -> float { return n as float; } } -} \ No newline at end of file +} diff --git a/src/test/auxiliary/test_comm.rs b/src/test/auxiliary/test_comm.rs index 0ae2dc5340e27..72000f2f0a9f0 100644 --- a/src/test/auxiliary/test_comm.rs +++ b/src/test/auxiliary/test_comm.rs @@ -13,12 +13,8 @@ Could probably be more minimal. */ -#[legacy_exports]; -use libc::size_t; - -export port; -export recv; +use core::libc::size_t; /** @@ -28,12 +24,12 @@ export recv; * transmitted. If a port value is copied, both copies refer to the same * port. Ports may be associated with multiple `chan`s. */ -enum port { +pub enum port { port_t(@port_ptr) } /// Constructs a port -fn port() -> port { +pub fn port() -> port { port_t(@port_ptr(rustrt::new_port(sys::size_of::() as size_t))) } @@ -74,11 +70,11 @@ fn port_ptr(po: *rust_port) -> port_ptr { * Receive from a port. If no data is available on the port then the * task will block until data becomes available. */ -fn recv(p: port) -> T { recv_((**p).po) } +pub fn recv(p: port) -> T { recv_((**p).po) } /// Receive on a raw port pointer -fn recv_(p: *rust_port) -> T { +pub fn recv_(p: *rust_port) -> T { let yield = 0; let yieldp = ptr::addr_of(&yield); let mut res; diff --git a/src/test/bench/core-map.rs b/src/test/bench/core-map.rs index 04c224211b1b8..83ca9fd06c9ed 100644 --- a/src/test/bench/core-map.rs +++ b/src/test/bench/core-map.rs @@ -16,9 +16,9 @@ extern mod std; use std::map; -use mutable::Mut; -use send_map::linear::*; -use io::WriterUtil; +use core::mutable::Mut; +use core::send_map::linear::*; +use core::io::WriterUtil; struct Results { sequential_ints: float, @@ -185,4 +185,4 @@ fn main() { rng, num_keys, &mut results); write_results("libstd::map::hashmap", &results); } -} \ No newline at end of file +} diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs index bd5ce036bb2fd..45fec9edeb96d 100644 --- a/src/test/bench/graph500-bfs.rs +++ b/src/test/bench/graph500-bfs.rs @@ -25,9 +25,9 @@ use std::map::HashMap; use std::deque; use std::deque::Deque; use std::par; -use io::WriterUtil; -use oldcomm::*; -use int::abs; +use core::io::WriterUtil; +use core::oldcomm::*; +use core::int::abs; type node_id = i64; type graph = ~[~[node_id]]; diff --git a/src/test/bench/msgsend-ring.rs b/src/test/bench/msgsend-ring.rs index 62226a1c44de1..43b20ed2db41b 100644 --- a/src/test/bench/msgsend-ring.rs +++ b/src/test/bench/msgsend-ring.rs @@ -14,7 +14,8 @@ // that things will look really good once we get that lock out of the // message path. -use oldcomm::*; +use core::oldcomm::*; +use core::oldcomm; extern mod std; use std::time; diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs index f85d6f6fdaaac..6133f9befcf3f 100644 --- a/src/test/bench/shootout-mandelbrot.rs +++ b/src/test/bench/shootout-mandelbrot.rs @@ -83,7 +83,7 @@ fn fillbyte(x: cmplx, incr: f64) -> u8 { rv } -fn chanmb(i: uint, size: uint, ch: oldcomm::Chan) -> () +fn chanmb(i: uint, size: uint) -> Line { let mut crv = ~[]; let incr = 2f64/(size as f64); @@ -93,12 +93,12 @@ fn chanmb(i: uint, size: uint, ch: oldcomm::Chan) -> () let x = cmplx {re: xincr*(j as f64) - 1.5f64, im: y}; crv.push(fillbyte(x, incr)); }; - oldcomm::send(ch, Line {i:i, b: move crv}); + Line {i:i, b:crv} } -type devnull = {dn: int}; +struct Devnull(); -impl devnull: io::Writer { +impl Devnull: io::Writer { fn write(&self, _b: &[const u8]) {} fn seek(&self, _i: int, _s: io::SeekStyle) {} fn tell(&self) -> uint {0_u} @@ -106,14 +106,11 @@ impl devnull: io::Writer { fn get_type(&self) -> io::WriterType { io::File } } -fn writer(path: ~str, writech: oldcomm::Chan>, size: uint) +fn writer(path: ~str, pport: pipes::Port, size: uint) { - let p: oldcomm::Port = oldcomm::Port(); - let ch = oldcomm::Chan(&p); - oldcomm::send(writech, ch); let cout: io::Writer = match path { ~"" => { - {dn: 0} as io::Writer + Devnull as io::Writer } ~"-" => { io::stdout() @@ -130,7 +127,7 @@ fn writer(path: ~str, writech: oldcomm::Chan>, size: uint) let mut done = 0_u; let mut i = 0_u; while i < size { - let aline = oldcomm::recv(p); + let aline = pport.recv(); if aline.i == done { debug!("W %u", aline.i); cout.write(aline.b); @@ -171,13 +168,11 @@ fn main() { let size = if vec::len(args) < 2_u { 80_u } else { uint::from_str(args[1]).get() }; - let writep = oldcomm::Port(); - let writech = oldcomm::Chan(&writep); - do task::spawn |move path| { - writer(copy path, writech, size); - }; - let ch = oldcomm::recv(writep); + let (pport, pchan) = pipes::stream(); + let pchan = pipes::SharedChan(pchan); for uint::range(0_u, size) |j| { - do task::spawn { chanmb(j, size, ch) }; + let cchan = pchan.clone(); + do task::spawn |move cchan| { cchan.send(chanmb(j, size)) }; }; + writer(path, pport, size); } diff --git a/src/test/bench/shootout-nbody.rs b/src/test/bench/shootout-nbody.rs index a266025591031..1c0a70c32a2de 100644 --- a/src/test/bench/shootout-nbody.rs +++ b/src/test/bench/shootout-nbody.rs @@ -13,6 +13,8 @@ extern mod std; +use core::os; + // Using sqrt from the standard library is way slower than using libc // directly even though std just calls libc, I guess it must be // because the the indirection through another dynamic linker @@ -45,9 +47,9 @@ fn main() { } mod NBodySystem { - #[legacy_exports]; + use Body; - fn make() -> ~[Body::props] { + pub fn make() -> ~[Body::props] { let mut bodies: ~[Body::props] = ~[Body::sun(), Body::jupiter(), @@ -74,8 +76,7 @@ mod NBodySystem { return bodies; } - fn advance(bodies: &mut [Body::props], dt: float) { - + pub fn advance(bodies: &mut [Body::props], dt: float) { let mut i = 0; while i < 5 { let mut j = i + 1; @@ -95,16 +96,16 @@ mod NBodySystem { } } - fn advance_one(bi: &mut Body::props, - bj: &mut Body::props, - dt: float) unsafe { + pub fn advance_one(bi: &mut Body::props, + bj: &mut Body::props, + dt: float) unsafe { let dx = bi.x - bj.x; let dy = bi.y - bj.y; let dz = bi.z - bj.z; let dSquared = dx * dx + dy * dy + dz * dz; - let distance = libc::sqrt(dSquared); + let distance = ::libc::sqrt(dSquared); let mag = dt / (dSquared * distance); bi.vx -= dx * bj.mass * mag; @@ -116,13 +117,13 @@ mod NBodySystem { bj.vz += dz * bi.mass * mag; } - fn move_(b: &mut Body::props, dt: float) { + pub fn move_(b: &mut Body::props, dt: float) { b.x += dt * b.vx; b.y += dt * b.vy; b.z += dt * b.vz; } - fn energy(bodies: &[Body::props]) -> float unsafe { + pub fn energy(bodies: &[Body::props]) -> float unsafe { let mut dx; let mut dy; let mut dz; @@ -142,7 +143,7 @@ mod NBodySystem { dy = bodies[i].y - bodies[j].y; dz = bodies[i].z - bodies[j].z; - distance = libc::sqrt(dx * dx + dy * dy + dz * dz); + distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz); e -= bodies[i].mass * bodies[j].mass / distance; j += 1; @@ -156,14 +157,14 @@ mod NBodySystem { } mod Body { - #[legacy_exports]; + use Body; - const PI: float = 3.141592653589793; - const SOLAR_MASS: float = 39.478417604357432; + pub const PI: float = 3.141592653589793; + pub const SOLAR_MASS: float = 39.478417604357432; // was 4 * PI * PI originally - const DAYS_PER_YEAR: float = 365.24; + pub const DAYS_PER_YEAR: float = 365.24; - type props = + pub type props = {mut x: float, mut y: float, mut z: float, @@ -172,7 +173,7 @@ mod Body { mut vz: float, mass: float}; - fn jupiter() -> Body::props { + pub fn jupiter() -> Body::props { return {mut x: 4.84143144246472090e+00, mut y: -1.16032004402742839e+00, mut z: -1.03622044471123109e-01, @@ -182,7 +183,7 @@ mod Body { mass: 9.54791938424326609e-04 * SOLAR_MASS}; } - fn saturn() -> Body::props { + pub fn saturn() -> Body::props { return {mut x: 8.34336671824457987e+00, mut y: 4.12479856412430479e+00, mut z: -4.03523417114321381e-01, @@ -192,7 +193,7 @@ mod Body { mass: 2.85885980666130812e-04 * SOLAR_MASS}; } - fn uranus() -> Body::props { + pub fn uranus() -> Body::props { return {mut x: 1.28943695621391310e+01, mut y: -1.51111514016986312e+01, mut z: -2.23307578892655734e-01, @@ -202,7 +203,7 @@ mod Body { mass: 4.36624404335156298e-05 * SOLAR_MASS}; } - fn neptune() -> Body::props { + pub fn neptune() -> Body::props { return {mut x: 1.53796971148509165e+01, mut y: -2.59193146099879641e+01, mut z: 1.79258772950371181e-01, @@ -212,7 +213,7 @@ mod Body { mass: 5.15138902046611451e-05 * SOLAR_MASS}; } - fn sun() -> Body::props { + pub fn sun() -> Body::props { return {mut x: 0.0, mut y: 0.0, mut z: 0.0, @@ -222,7 +223,7 @@ mod Body { mass: SOLAR_MASS}; } - fn offset_momentum(props: &mut Body::props, + pub fn offset_momentum(props: &mut Body::props, px: float, py: float, pz: float) { props.vx = -px / SOLAR_MASS; props.vy = -py / SOLAR_MASS; diff --git a/src/test/bench/task-perf-word-count-generic.rs b/src/test/bench/task-perf-word-count-generic.rs index 56257aa305e47..e24979a4e060b 100644 --- a/src/test/bench/task-perf-word-count-generic.rs +++ b/src/test/bench/task-perf-word-count-generic.rs @@ -22,22 +22,20 @@ extern mod std; -use option = option; -use option::Some; -use option::None; +use core::option; use std::map; use std::map::HashMap; -use hash::Hash; -use io::{ReaderUtil, WriterUtil}; +use core::hash::Hash; +use core::io::{ReaderUtil, WriterUtil}; use std::time; -use oldcomm::Chan; -use oldcomm::Port; -use oldcomm::recv; -use oldcomm::send; -use cmp::Eq; -use to_bytes::IterBytes; +use core::oldcomm::Chan; +use core::oldcomm::Port; +use core::oldcomm::recv; +use core::oldcomm::send; +use core::cmp::Eq; +use core::to_bytes::IterBytes; macro_rules! move_out ( { $x:expr } => { unsafe { let y = move *ptr::addr_of(&($x)); move y } } @@ -117,20 +115,15 @@ fn box(+x: T) -> box { } mod map_reduce { - #[legacy_exports]; - export putter; - export getter; - export mapper; - export reducer; - export map_reduce; + use std::map; - type putter = fn(&K, V); + pub type putter = fn(&K, V); - type mapper = fn~(K1, putter); + pub type mapper = fn~(K1, putter); - type getter = fn() -> Option; + pub type getter = fn() -> Option; - type reducer = fn~(&K, getter); + pub type reducer = fn~(&K, getter); enum ctrl_proto { find_reducer(K, Chan>>), @@ -245,7 +238,7 @@ mod map_reduce { (*reduce)(&key, || get(p, &mut ref_count, &mut is_done) ); } - fn map_reduce( + pub fn map_reduce( map: mapper, reduce: reducer, inputs: ~[K1]) diff --git a/src/test/compile-fail/bad-bang-ann-3.rs b/src/test/compile-fail/bad-bang-ann-3.rs index 3f4d60a5ec97d..9e73bbe1406bd 100644 --- a/src/test/compile-fail/bad-bang-ann-3.rs +++ b/src/test/compile-fail/bad-bang-ann-3.rs @@ -13,7 +13,7 @@ fn bad_bang(i: uint) -> ! { return 7u; - //~^ ERROR expected `_|_` but found `uint` + //~^ ERROR expected `!` but found `uint` } fn main() { bad_bang(5u); } diff --git a/src/test/compile-fail/bad-bang-ann.rs b/src/test/compile-fail/bad-bang-ann.rs index da08692797f83..4dbe5876a978e 100644 --- a/src/test/compile-fail/bad-bang-ann.rs +++ b/src/test/compile-fail/bad-bang-ann.rs @@ -13,7 +13,7 @@ fn bad_bang(i: uint) -> ! { if i < 0u { } else { fail; } - //~^ ERROR expected `_|_` but found `()` + //~^ ERROR expected `!` but found `()` } fn main() { bad_bang(5u); } diff --git a/src/test/compile-fail/bang-tailexpr.rs b/src/test/compile-fail/bang-tailexpr.rs index fa33e1f832b00..af78e19e8c2e2 100644 --- a/src/test/compile-fail/bang-tailexpr.rs +++ b/src/test/compile-fail/bang-tailexpr.rs @@ -9,6 +9,6 @@ // except according to those terms. fn f() -> ! { - 3i //~ ERROR expected `_|_` but found `int` + 3i //~ ERROR expected `!` but found `int` } fn main() { } diff --git a/src/test/compile-fail/block-coerce-no-2.rs b/src/test/compile-fail/block-coerce-no-2.rs index 1e539dc4f36f6..b2265f5e959a0 100644 --- a/src/test/compile-fail/block-coerce-no-2.rs +++ b/src/test/compile-fail/block-coerce-no-2.rs @@ -19,5 +19,5 @@ fn main() { } f(g); - //~^ ERROR mismatched types: expected `fn(fn(fn()))` + //~^ ERROR mismatched types: expected `extern fn(extern fn(extern fn()))` } diff --git a/src/test/compile-fail/borrowck-autoref-3261.rs b/src/test/compile-fail/borrowck-autoref-3261.rs index 6c6f59d00ea98..457cdd2344737 100644 --- a/src/test/compile-fail/borrowck-autoref-3261.rs +++ b/src/test/compile-fail/borrowck-autoref-3261.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use either::*; -enum X = Either<(uint,uint),fn()>; +use core::either::*; +enum X = Either<(uint,uint),extern fn()>; impl &X { - fn with(blk: fn(x: &Either<(uint,uint),fn()>)) { + fn with(blk: fn(x: &Either<(uint,uint),extern fn()>)) { blk(&**self) } } @@ -26,4 +26,4 @@ fn main() { _ => fail } } -} \ No newline at end of file +} diff --git a/src/test/compile-fail/closure-that-fails.rs b/src/test/compile-fail/closure-that-fails.rs new file mode 100644 index 0000000000000..00bfa7a2233fa --- /dev/null +++ b/src/test/compile-fail/closure-that-fails.rs @@ -0,0 +1,7 @@ +fn foo(f: fn() -> !) {} + +fn main() { + // Type inference didn't use to be able to handle this: + foo(|| fail); + foo(|| 22); //~ ERROR mismatched types +} diff --git a/src/test/compile-fail/fully-qualified-type-name3.rs b/src/test/compile-fail/fully-qualified-type-name3.rs index b7d70c60c223f..464f292b75899 100644 --- a/src/test/compile-fail/fully-qualified-type-name3.rs +++ b/src/test/compile-fail/fully-qualified-type-name3.rs @@ -10,6 +10,7 @@ // Test that we use fully-qualified type names in error messages. +// xfail-test type T1 = uint; type T2 = int; diff --git a/src/test/compile-fail/issue-1697.rs b/src/test/compile-fail/issue-1697.rs index a0d2536d85f0e..2a64666d94ca6 100644 --- a/src/test/compile-fail/issue-1697.rs +++ b/src/test/compile-fail/issue-1697.rs @@ -10,8 +10,7 @@ // Testing that we don't fail abnormally after hitting the errors -use unresolved::*; //~ ERROR unresolved name -//~^ ERROR failed to resolve import +use unresolved::*; //~ ERROR unresolved import fn main() { } diff --git a/src/test/compile-fail/issue-2766-a.rs b/src/test/compile-fail/issue-2766-a.rs index c0b27789977ef..0b63ae5b1bad3 100644 --- a/src/test/compile-fail/issue-2766-a.rs +++ b/src/test/compile-fail/issue-2766-a.rs @@ -8,16 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod stream { - #[legacy_exports]; - enum Stream { send(T, server::Stream), } - mod server { - #[legacy_exports]; +pub mod stream { + pub enum Stream { send(T, ::stream::server::Stream), } + pub mod server { + use core::option; + use core::pipes; + impl Stream { - fn recv() -> extern fn(+v: Stream) -> stream::Stream { + pub 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 + pub 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 @@ -26,7 +27,8 @@ mod stream { recv } } - type Stream = pipes::RecvPacket>; + + pub type Stream = pipes::RecvPacket<::stream::Stream>; } } diff --git a/src/test/compile-fail/issue-3477.rs b/src/test/compile-fail/issue-3477.rs new file mode 100644 index 0000000000000..7e189348db354 --- /dev/null +++ b/src/test/compile-fail/issue-3477.rs @@ -0,0 +1,3 @@ +fn main() { + let _p: char = 100; //~ ERROR mismatched types: expected `char` but found +} \ No newline at end of file diff --git a/src/test/run-pass/issue-3563.rs b/src/test/compile-fail/issue-3563.rs similarity index 82% rename from src/test/run-pass/issue-3563.rs rename to src/test/compile-fail/issue-3563.rs index 2c390bf1372b7..9f7a0745c3b1b 100644 --- a/src/test/run-pass/issue-3563.rs +++ b/src/test/compile-fail/issue-3563.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test trait A { fn a(&self) { - || self.b() + || self.b() //~ ERROR type `&self/self` does not implement any method in scope named `b` } } +fn main() {} diff --git a/src/test/compile-fail/issue-3601.rs b/src/test/compile-fail/issue-3601.rs new file mode 100644 index 0000000000000..3e54aaa287ca2 --- /dev/null +++ b/src/test/compile-fail/issue-3601.rs @@ -0,0 +1,42 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +struct HTMLImageData { + mut image: Option<~str> +} + +struct ElementData { + kind: ~ElementKind +} + +enum ElementKind { + HTMLImageElement(HTMLImageData) +} + +enum NodeKind { + Element(ElementData) +} + +enum NodeData = { + kind: ~NodeKind +}; + +fn main() { + let id = HTMLImageData { image: None }; + let ed = ElementData { kind: ~HTMLImageElement(id) }; + let n = NodeData({kind : ~Element(ed)}); + match n.kind { + ~Element(ed) => match ed.kind { + ~HTMLImageElement(d) if d.image.is_some() => { true } + }, + _ => fail ~"WAT" //~ ERROR wat + }; +} diff --git a/src/test/compile-fail/issue-3707.rs b/src/test/compile-fail/issue-3707.rs new file mode 100644 index 0000000000000..c166c400b36de --- /dev/null +++ b/src/test/compile-fail/issue-3707.rs @@ -0,0 +1,29 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +struct Obj { + member: uint +} + +impl Obj { + static pure fn boom() -> bool { + return 1+1 == 2 + } + pure fn chirp() { + self.boom(); //~ ERROR wat + } +} + +fn main() { + let o = Obj { member: 0 }; + o.chirp(); + 1 + 1; +} diff --git a/src/test/compile-fail/issue-897-2.rs b/src/test/compile-fail/issue-897-2.rs index 77de0b115cbb6..61afdab405dc4 100644 --- a/src/test/compile-fail/issue-897-2.rs +++ b/src/test/compile-fail/issue-897-2.rs @@ -10,7 +10,7 @@ fn g() -> ! { fail; } fn f() -> ! { - return 42i; //~ ERROR expected `_|_` but found `int` + return 42i; //~ ERROR expected `!` but found `int` g(); //~ WARNING unreachable statement } fn main() { } diff --git a/src/test/compile-fail/issue-897.rs b/src/test/compile-fail/issue-897.rs index 3086bcc9b3f3b..1ed7034be77cd 100644 --- a/src/test/compile-fail/issue-897.rs +++ b/src/test/compile-fail/issue-897.rs @@ -9,7 +9,7 @@ // except according to those terms. fn f() -> ! { - return 42i; //~ ERROR expected `_|_` but found `int` + return 42i; //~ ERROR expected `!` but found `int` fail; //~ WARNING unreachable statement } fn main() { } diff --git a/src/test/compile-fail/loop-does-not-diverge.rs b/src/test/compile-fail/loop-does-not-diverge.rs index 77b906ca9a2cd..0265bd6d24b67 100644 --- a/src/test/compile-fail/loop-does-not-diverge.rs +++ b/src/test/compile-fail/loop-does-not-diverge.rs @@ -14,7 +14,7 @@ fn forever() -> ! { loop { break; } - return 42i; //~ ERROR expected `_|_` but found `int` + return 42i; //~ ERROR expected `!` but found `int` } fn main() { diff --git a/src/test/compile-fail/main-wrong-type-2.rs b/src/test/compile-fail/main-wrong-type-2.rs index 4e1989eb25c5e..bb6633ecdc1fd 100644 --- a/src/test/compile-fail/main-wrong-type-2.rs +++ b/src/test/compile-fail/main-wrong-type-2.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() -> char { -//~^ ERROR Wrong type in main function: found `fn() -> char` +//~^ ERROR Wrong type in main function: found `extern fn() -> char` } diff --git a/src/test/compile-fail/main-wrong-type.rs b/src/test/compile-fail/main-wrong-type.rs index 7f8a4053c43ee..33d7b913dafb5 100644 --- a/src/test/compile-fail/main-wrong-type.rs +++ b/src/test/compile-fail/main-wrong-type.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main(foo: {x: int, y: int}) { -//~^ ERROR Wrong type in main function: found `fn({x: int,y: int})` +//~^ ERROR Wrong type in main function: found `extern fn({x: int,y: int})` } diff --git a/src/test/compile-fail/missing-do.rs b/src/test/compile-fail/missing-do.rs index 3a0e8ffb9c48d..916008373c875 100644 --- a/src/test/compile-fail/missing-do.rs +++ b/src/test/compile-fail/missing-do.rs @@ -14,6 +14,6 @@ fn foo(f: fn()) { f() } fn main() { ~"" || 42; //~ ERROR binary operation || cannot be applied to type `~str` - foo || {}; //~ ERROR binary operation || cannot be applied to type `fn(&fn())` + foo || {}; //~ ERROR binary operation || cannot be applied to type `extern fn(&fn())` //~^ NOTE did you forget the 'do' keyword for the call? } diff --git a/src/test/compile-fail/name-clash-nullary.rs b/src/test/compile-fail/name-clash-nullary.rs index 9947c882a5854..e64d651dab2b4 100644 --- a/src/test/compile-fail/name-clash-nullary.rs +++ b/src/test/compile-fail/name-clash-nullary.rs @@ -9,7 +9,7 @@ // except according to those terms. // error-pattern:declaration of `None` shadows -use option::*; +use core::option::*; fn main() { let None: int = 42; diff --git a/src/test/compile-fail/no-capture-arc.rs b/src/test/compile-fail/no-capture-arc.rs index 98220195e613d..7dc3c247ea48e 100644 --- a/src/test/compile-fail/no-capture-arc.rs +++ b/src/test/compile-fail/no-capture-arc.rs @@ -12,7 +12,7 @@ extern mod std; use std::arc; -use oldcomm::*; +use core::oldcomm::*; fn main() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; diff --git a/src/test/compile-fail/no-reuse-move-arc.rs b/src/test/compile-fail/no-reuse-move-arc.rs index 8cb8f31c48976..8a7c37649d2ed 100644 --- a/src/test/compile-fail/no-reuse-move-arc.rs +++ b/src/test/compile-fail/no-reuse-move-arc.rs @@ -10,7 +10,7 @@ extern mod std; use std::arc; -use oldcomm::*; +use core::oldcomm::*; fn main() { let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; diff --git a/src/test/compile-fail/pptypedef.rs b/src/test/compile-fail/pptypedef.rs index 9ed520a6c9958..223d7effa4ce6 100644 --- a/src/test/compile-fail/pptypedef.rs +++ b/src/test/compile-fail/pptypedef.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// xfail-test type foo = Option; fn bar(_t: foo) {} diff --git a/src/test/compile-fail/unsafe-fn-autoderef.rs b/src/test/compile-fail/unsafe-fn-autoderef.rs index 4932e52657473..b602d1717be70 100644 --- a/src/test/compile-fail/unsafe-fn-autoderef.rs +++ b/src/test/compile-fail/unsafe-fn-autoderef.rs @@ -9,7 +9,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +// xfail-test type rec = {f: int}; fn f(p: *rec) -> int { diff --git a/src/test/run-pass-fulldeps/qquote.rs b/src/test/run-pass-fulldeps/qquote.rs index 3345dcaaad02a..4e4df552a2ecd 100644 --- a/src/test/run-pass-fulldeps/qquote.rs +++ b/src/test/run-pass-fulldeps/qquote.rs @@ -15,7 +15,7 @@ extern mod std; extern mod syntax; -use io::*; +use core::io::*; use syntax::diagnostic; use syntax::ast; diff --git a/src/test/run-pass/alt-pattern-drop.rs b/src/test/run-pass/alt-pattern-drop.rs index c90bec114ed26..ccc65cdab7515 100644 --- a/src/test/run-pass/alt-pattern-drop.rs +++ b/src/test/run-pass/alt-pattern-drop.rs @@ -14,7 +14,7 @@ enum t { make_t(@int), clam, } fn foo(s: @int) { - let count = core::sys::refcount(s); + let count = ::core::sys::refcount(s); let x: t = make_t(s); // ref up match x { @@ -24,20 +24,20 @@ fn foo(s: @int) { } _ => { debug!("?"); fail; } } - log(debug, core::sys::refcount(s)); - assert (core::sys::refcount(s) == count + 1u); - let _ = core::sys::refcount(s); // don't get bitten by last-use. + log(debug, ::core::sys::refcount(s)); + assert (::core::sys::refcount(s) == count + 1u); + let _ = ::core::sys::refcount(s); // don't get bitten by last-use. } fn main() { let s: @int = @0; // ref up - let count = core::sys::refcount(s); + let count = ::core::sys::refcount(s); foo(s); // ref up then down - log(debug, core::sys::refcount(s)); - let count2 = core::sys::refcount(s); - let _ = core::sys::refcount(s); // don't get bitten by last-use. + log(debug, ::core::sys::refcount(s)); + let count2 = ::core::sys::refcount(s); + let _ = ::core::sys::refcount(s); // don't get bitten by last-use. assert count == count2; } diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs index 555171f9d5f30..2bd00ddc4ef14 100644 --- a/src/test/run-pass/auto-encode.rs +++ b/src/test/run-pass/auto-encode.rs @@ -26,12 +26,12 @@ use std::serialize::{Encodable, Decodable}; use std::prettyprint; use std::time; -fn test_prettyprint>( +fn test_prettyprint>( a: &A, expected: &~str ) { let s = do io::with_str_writer |w| { - a.encode(&prettyprint::Encoder(w)) + a.encode(&prettyprint::Serializer(w)) }; debug!("s == %?", s); assert s == *expected; diff --git a/src/test/run-pass/basic-1.rs b/src/test/run-pass/basic-1.rs index 7f7da086df30c..87fd1443db9e3 100644 --- a/src/test/run-pass/basic-1.rs +++ b/src/test/run-pass/basic-1.rs @@ -10,25 +10,25 @@ // except according to those terms. -fn a(c: core::oldcomm::Chan) { core::oldcomm::send(c, 10); } +fn a(c: ::core::oldcomm::Chan) { ::core::oldcomm::send(c, 10); } fn main() { - let p = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); task::spawn(|| a(ch) ); task::spawn(|| a(ch) ); let mut n: int = 0; - n = core::oldcomm::recv(p); - n = core::oldcomm::recv(p); + n = ::core::oldcomm::recv(p); + n = ::core::oldcomm::recv(p); // debug!("Finished."); } -fn b(c: core::oldcomm::Chan) { +fn b(c: ::core::oldcomm::Chan) { // debug!("task b0"); // debug!("task b1"); // debug!("task b2"); // debug!("task b3"); // debug!("task b4"); // debug!("task b5"); - core::oldcomm::send(c, 10); + ::core::oldcomm::send(c, 10); } diff --git a/src/test/run-pass/basic-2.rs b/src/test/run-pass/basic-2.rs index 36ed4c5162b67..0e542e157cf93 100644 --- a/src/test/run-pass/basic-2.rs +++ b/src/test/run-pass/basic-2.rs @@ -10,28 +10,28 @@ // except according to those terms. -fn a(c: core::oldcomm::Chan) { +fn a(c: ::core::oldcomm::Chan) { debug!("task a0"); debug!("task a1"); - core::oldcomm::send(c, 10); + ::core::oldcomm::send(c, 10); } fn main() { - let p = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); task::spawn(|| a(ch) ); task::spawn(|| b(ch) ); let mut n: int = 0; - n = core::oldcomm::recv(p); - n = core::oldcomm::recv(p); + n = ::core::oldcomm::recv(p); + n = ::core::oldcomm::recv(p); debug!("Finished."); } -fn b(c: core::oldcomm::Chan) { +fn b(c: ::core::oldcomm::Chan) { debug!("task b0"); debug!("task b1"); debug!("task b2"); debug!("task b2"); debug!("task b3"); - core::oldcomm::send(c, 10); + ::core::oldcomm::send(c, 10); } diff --git a/src/test/run-pass/basic.rs b/src/test/run-pass/basic.rs index a84bfdcdbb7ee..ac029b63eef40 100644 --- a/src/test/run-pass/basic.rs +++ b/src/test/run-pass/basic.rs @@ -10,7 +10,7 @@ // except according to those terms. -fn a(c: core::oldcomm::Chan) { +fn a(c: ::core::oldcomm::Chan) { if true { debug!("task a"); debug!("task a"); @@ -18,7 +18,7 @@ fn a(c: core::oldcomm::Chan) { debug!("task a"); debug!("task a"); } - core::oldcomm::send(c, 10); + ::core::oldcomm::send(c, 10); } fn k(x: int) -> int { return 15; } @@ -34,18 +34,18 @@ fn main() { let mut n: int = 2 + 3 * 7; let s: ~str = ~"hello there"; let p = oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let ch = ::core::oldcomm::Chan(&p); task::spawn(|| a(ch) ); task::spawn(|| b(ch) ); let mut x: int = 10; x = g(n, s); log(debug, x); - n = core::oldcomm::recv(p); - n = core::oldcomm::recv(p); + n = ::core::oldcomm::recv(p); + n = ::core::oldcomm::recv(p); debug!("children finished, root finishing"); } -fn b(c: core::oldcomm::Chan) { +fn b(c: ::core::oldcomm::Chan) { if true { debug!("task b"); debug!("task b"); @@ -54,5 +54,5 @@ fn b(c: core::oldcomm::Chan) { debug!("task b"); debug!("task b"); } - core::oldcomm::send(c, 10); + ::core::oldcomm::send(c, 10); } diff --git a/src/test/run-pass/binops.rs b/src/test/run-pass/binops.rs index 72299e2b329c1..04cc55b22640c 100644 --- a/src/test/run-pass/binops.rs +++ b/src/test/run-pass/binops.rs @@ -63,9 +63,9 @@ fn test_box() { } fn test_ptr() unsafe { - let p1: *u8 = core::cast::reinterpret_cast(&0); - let p2: *u8 = core::cast::reinterpret_cast(&0); - let p3: *u8 = core::cast::reinterpret_cast(&1); + let p1: *u8 = ::core::cast::reinterpret_cast(&0); + let p2: *u8 = ::core::cast::reinterpret_cast(&0); + let p3: *u8 = ::core::cast::reinterpret_cast(&1); assert p1 == p2; assert p1 != p3; @@ -110,8 +110,8 @@ fn test_class() { unsafe { error!("q = %x, r = %x", - (core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&q))), - (core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&r)))); + (::core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&q))), + (::core::cast::reinterpret_cast::<*p, uint>(&ptr::addr_of(&r)))); } assert(q == r); r.y = 17; diff --git a/src/test/run-pass/capture_nil.rs b/src/test/run-pass/capture_nil.rs index 8f9049ac27b2b..893912d5c0589 100644 --- a/src/test/run-pass/capture_nil.rs +++ b/src/test/run-pass/capture_nil.rs @@ -24,9 +24,9 @@ // course preferable, as the value itself is // irrelevant). -fn foo(&&x: ()) -> core::oldcomm::Port<()> { - let p = core::oldcomm::Port(); - let c = core::oldcomm::Chan(&p); +fn foo(&&x: ()) -> ::core::oldcomm::Port<()> { + let p = ::core::oldcomm::Port(); + let c = ::core::oldcomm::Chan(&p); do task::spawn() |copy c, copy x| { c.send(x); } diff --git a/src/test/run-pass/cci_capture_clause.rs b/src/test/run-pass/cci_capture_clause.rs index be64fcd8992fa..a439d2af8fc02 100644 --- a/src/test/run-pass/cci_capture_clause.rs +++ b/src/test/run-pass/cci_capture_clause.rs @@ -18,7 +18,7 @@ extern mod cci_capture_clause; -use oldcomm::recv; +use core::oldcomm::recv; fn main() { cci_capture_clause::foo(()).recv() diff --git a/src/test/run-pass/chan-leak.rs b/src/test/run-pass/chan-leak.rs index bb429a07f39db..43825b03c296d 100644 --- a/src/test/run-pass/chan-leak.rs +++ b/src/test/run-pass/chan-leak.rs @@ -10,32 +10,32 @@ // Issue #763 -enum request { quit, close(core::oldcomm::Chan), } +enum request { quit, close(::core::oldcomm::Chan), } -type ctx = core::oldcomm::Chan; +type ctx = ::core::oldcomm::Chan; -fn request_task(c: core::oldcomm::Chan) { - let p = core::oldcomm::Port(); - core::oldcomm::send(c, core::oldcomm::Chan(&p)); +fn request_task(c: ::core::oldcomm::Chan) { + let p = ::core::oldcomm::Port(); + ::core::oldcomm::send(c, ::core::oldcomm::Chan(&p)); let mut req: request; - req = core::oldcomm::recv(p); + req = ::core::oldcomm::recv(p); // Need to drop req before receiving it again - req = core::oldcomm::recv(p); + req = ::core::oldcomm::recv(p); } fn new_cx() -> ctx { - let p = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); let t = task::spawn(|| request_task(ch) ); let mut cx: ctx; - cx = core::oldcomm::recv(p); + cx = ::core::oldcomm::recv(p); return cx; } fn main() { let cx = new_cx(); - let p = core::oldcomm::Port::(); - core::oldcomm::send(cx, close(core::oldcomm::Chan(&p))); - core::oldcomm::send(cx, quit); + let p = ::core::oldcomm::Port::(); + ::core::oldcomm::send(cx, close(::core::oldcomm::Chan(&p))); + ::core::oldcomm::send(cx, quit); } diff --git a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs index f84332a6382b5..5d53453ffc005 100644 --- a/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs +++ b/src/test/run-pass/class-cast-to-trait-cross-crate-2.rs @@ -11,7 +11,7 @@ // xfail-fast // aux-build:cci_class_cast.rs extern mod cci_class_cast; -use to_str::ToStr; +use core::to_str::ToStr; use cci_class_cast::kitty::*; fn print_out(thing: T, expected: ~str) { diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index 23c1e6792a415..eb3728f2c6fc3 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -9,8 +9,7 @@ // except according to those terms. // xfail-fast -use to_str::*; -use to_str::ToStr; +use core::to_str::*; struct cat { priv mut meows : uint, diff --git a/src/test/run-pass/coherence-impl-in-fn.rs b/src/test/run-pass/coherence-impl-in-fn.rs index 90cd3397c80e5..e014ffe4bef47 100644 --- a/src/test/run-pass/coherence-impl-in-fn.rs +++ b/src/test/run-pass/coherence-impl-in-fn.rs @@ -10,7 +10,7 @@ fn main() { enum x { foo } - impl x : core::cmp::Eq { + impl x : ::core::cmp::Eq { pure fn eq(&self, other: &x) -> bool { (*self) as int == (*other) as int } diff --git a/src/test/run-pass/comm.rs b/src/test/run-pass/comm.rs index 453ae67952319..7a79d2360684d 100644 --- a/src/test/run-pass/comm.rs +++ b/src/test/run-pass/comm.rs @@ -12,16 +12,16 @@ fn main() { let p = oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let ch = ::core::oldcomm::Chan(&p); let t = task::spawn(|| child(ch) ); - let y = core::oldcomm::recv(p); + let y = ::core::oldcomm::recv(p); error!("received"); log(error, y); assert (y == 10); } -fn child(c: core::oldcomm::Chan) { +fn child(c: ::core::oldcomm::Chan) { error!("sending"); - core::oldcomm::send(c, 10); + ::core::oldcomm::send(c, 10); error!("value sent"); } diff --git a/src/test/run-pass/const-nullary-univariant-enum.rs b/src/test/run-pass/const-nullary-univariant-enum.rs new file mode 100644 index 0000000000000..e1db50d566b43 --- /dev/null +++ b/src/test/run-pass/const-nullary-univariant-enum.rs @@ -0,0 +1,19 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + Bar = 0xDEADBEE +} + +const X: Foo = Bar; + +fn main() { + assert((X as uint) == 0xDEADBEE); +} diff --git a/src/test/run-pass/core-export-f64-sqrt.rs b/src/test/run-pass/core-export-f64-sqrt.rs index a78ca37172b28..9b080206fcdea 100644 --- a/src/test/run-pass/core-export-f64-sqrt.rs +++ b/src/test/run-pass/core-export-f64-sqrt.rs @@ -14,5 +14,5 @@ fn main() { let digits: uint = 10 as uint; - core::io::println(float::to_str(f64::sqrt(42.0f64) as float, digits)); + ::core::io::println(float::to_str(f64::sqrt(42.0f64) as float, digits)); } diff --git a/src/test/run-pass/decl-with-recv.rs b/src/test/run-pass/decl-with-recv.rs index 4b4d6a86806d1..a3679f71a6b1b 100644 --- a/src/test/run-pass/decl-with-recv.rs +++ b/src/test/run-pass/decl-with-recv.rs @@ -11,12 +11,12 @@ fn main() { - let po = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&po); - core::oldcomm::send(ch, 10); - let i = core::oldcomm::recv(po); + let po = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&po); + ::core::oldcomm::send(ch, 10); + let i = ::core::oldcomm::recv(po); assert (i == 10); - core::oldcomm::send(ch, 11); - let j = core::oldcomm::recv(po); + ::core::oldcomm::send(ch, 11); + let j = ::core::oldcomm::recv(po); assert (j == 11); } diff --git a/src/test/run-pass/deriving-via-extension-iter-bytes-enum.rs b/src/test/run-pass/deriving-via-extension-iter-bytes-enum.rs index 1f29a08a80468..849ad64270de9 100644 --- a/src/test/run-pass/deriving-via-extension-iter-bytes-enum.rs +++ b/src/test/run-pass/deriving-via-extension-iter-bytes-enum.rs @@ -1,3 +1,5 @@ +// xfail-fast + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/src/test/run-pass/deriving-via-extension-iter-bytes-struct.rs b/src/test/run-pass/deriving-via-extension-iter-bytes-struct.rs index a71d51cf21c0d..5855b1a530ba3 100644 --- a/src/test/run-pass/deriving-via-extension-iter-bytes-struct.rs +++ b/src/test/run-pass/deriving-via-extension-iter-bytes-struct.rs @@ -1,3 +1,5 @@ +// xfail-fast + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/src/test/run-pass/deriving-via-extension-type-params.rs b/src/test/run-pass/deriving-via-extension-type-params.rs index c0501a0920740..b1b196e6986a4 100644 --- a/src/test/run-pass/deriving-via-extension-type-params.rs +++ b/src/test/run-pass/deriving-via-extension-type-params.rs @@ -1,3 +1,5 @@ +// xfail-fast + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/src/test/run-pass/drop-trait-generic.rs b/src/test/run-pass/drop-trait-generic.rs index 4906f0e70b96e..238f3b8b587a3 100644 --- a/src/test/run-pass/drop-trait-generic.rs +++ b/src/test/run-pass/drop-trait-generic.rs @@ -12,7 +12,7 @@ struct S { x: T } -impl S : core::ops::Drop { +impl S : ::core::ops::Drop { fn finalize(&self) { io::println("bye"); } diff --git a/src/test/run-pass/enum-variants.rs b/src/test/run-pass/enum-variants.rs new file mode 100644 index 0000000000000..26fae68e158f7 --- /dev/null +++ b/src/test/run-pass/enum-variants.rs @@ -0,0 +1,11 @@ +enum Animal { + Dog (~str, float), + Cat { name: ~str, weight: float } +} + +fn main() { + let mut a: Animal = Dog(~"Cocoa", 37.2); + a = Cat{ name: ~"Spotty", weight: 2.7 }; + // permuting the fields should work too + let c = Cat { weight: 3.1, name: ~"Spreckles" }; +} diff --git a/src/test/run-pass/export-non-interference3.rs b/src/test/run-pass/export-non-interference3.rs index 85d1a33826c5b..5f8a74203e4e8 100644 --- a/src/test/run-pass/export-non-interference3.rs +++ b/src/test/run-pass/export-non-interference3.rs @@ -1,3 +1,5 @@ +// xfail-fast + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -8,18 +10,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -mod foo { - #[legacy_exports]; - export x; - - fn x() { bar::x(); } +pub mod foo { + pub fn x() { ::bar::x(); } } -mod bar { - #[legacy_exports]; - export x; - - fn x() { debug!("x"); } +pub mod bar { + pub fn x() { debug!("x"); } } fn main() { foo::x(); } diff --git a/src/test/run-pass/fn-coerce-field.rs b/src/test/run-pass/fn-coerce-field.rs index 47f4f122f93f6..0e7d90e2fd81f 100644 --- a/src/test/run-pass/fn-coerce-field.rs +++ b/src/test/run-pass/fn-coerce-field.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -type r = { +struct r { field: fn@() -}; +} fn main() { fn f() {} - let i: r = {field: f}; + let i: r = r {field: f}; } \ No newline at end of file diff --git a/src/test/run-pass/foreign2.rs b/src/test/run-pass/foreign2.rs index 4b7b762f4d17c..0018a1d62f686 100644 --- a/src/test/run-pass/foreign2.rs +++ b/src/test/run-pass/foreign2.rs @@ -23,7 +23,7 @@ extern mod zed { extern mod libc { #[legacy_exports]; fn write(fd: int, buf: *u8, - count: core::libc::size_t) -> core::libc::ssize_t; + count: ::core::libc::size_t) -> ::core::libc::ssize_t; } #[abi = "cdecl"] diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index c8fbb0dd7418b..577ac67dd6a69 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -28,14 +28,12 @@ use oldcomm::recv; fn map(filename: ~str, emit: map_reduce::putter) { emit(filename, ~"1"); } mod map_reduce { - #[legacy_exports]; - export putter; - export mapper; - export map_reduce; + use std::map; + use std::map::HashMap; - type putter = fn@(~str, ~str); + pub type putter = fn@(~str, ~str); - type mapper = extern fn(~str, putter); + pub type mapper = extern fn(~str, putter); enum ctrl_proto { find_reducer(~[u8], Chan), mapper_done, } @@ -70,7 +68,7 @@ mod map_reduce { send(ctrl, mapper_done); } - fn map_reduce(inputs: ~[~str]) { + pub fn map_reduce(inputs: ~[~str]) { let ctrl = Port(); // This task becomes the master control task. It spawns others diff --git a/src/test/run-pass/import-glob-crate.rs b/src/test/run-pass/import-glob-crate.rs index 0d3d08b3a39ac..eba69134c4f0a 100644 --- a/src/test/run-pass/import-glob-crate.rs +++ b/src/test/run-pass/import-glob-crate.rs @@ -12,7 +12,7 @@ extern mod std; -use vec::*; +use core::vec::*; fn main() { let mut v = from_elem(0u, 0); diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index 6239df9827845..01da68ec3426f 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -21,26 +21,24 @@ extern mod rusti { #[cfg(target_os = "macos")] #[cfg(target_os = "freebsd")] mod m { - #[legacy_exports]; #[cfg(target_arch = "x86")] - fn main() { - assert rusti::pref_align_of::() == 8u; - assert rusti::min_align_of::() == 4u; + pub fn main() { + assert ::rusti::pref_align_of::() == 8u; + assert ::rusti::min_align_of::() == 4u; } #[cfg(target_arch = "x86_64")] - fn main() { - assert rusti::pref_align_of::() == 8u; - assert rusti::min_align_of::() == 8u; + pub fn main() { + assert ::rusti::pref_align_of::() == 8u; + assert ::rusti::min_align_of::() == 8u; } } #[cfg(target_os = "win32")] mod m { - #[legacy_exports]; #[cfg(target_arch = "x86")] - fn main() { - assert rusti::pref_align_of::() == 8u; - assert rusti::min_align_of::() == 8u; + pub fn main() { + assert ::rusti::pref_align_of::() == 8u; + assert ::rusti::min_align_of::() == 8u; } } diff --git a/src/test/run-pass/intrinsic-frame-address.rs b/src/test/run-pass/intrinsic-frame-address.rs index 653e84ea347cf..4b48e9a49c2ac 100644 --- a/src/test/run-pass/intrinsic-frame-address.rs +++ b/src/test/run-pass/intrinsic-frame-address.rs @@ -13,7 +13,7 @@ #[abi = "rust-intrinsic"] extern mod rusti { #[legacy_exports]; - fn frame_address(f: fn(*u8)); + fn frame_address(f: &once fn(*u8)); } fn main() { diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 588cc496b2821..feddd0ab9cbc8 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -28,6 +28,10 @@ extern mod rusti { fn cttz16(x: i16) -> i16; fn cttz32(x: i32) -> i32; fn cttz64(x: i64) -> i64; + + fn bswap16(x: i16) -> i16; + fn bswap32(x: i32) -> i32; + fn bswap64(x: i64) -> i64; } fn main() { @@ -109,4 +113,8 @@ fn main() { assert(cttz32(-1i32) == 0i32); assert(cttz64(-1i64) == 0i64); + assert(bswap16(0x0A0Bi16) == 0x0B0Ai16); + assert(bswap32(0x0ABBCC0Di32) == 0x0DCCBB0Ai32); + assert(bswap64(0x0122334455667708i64) == 0x0877665544332201i64); + } diff --git a/src/test/run-pass/issue-1458.rs b/src/test/run-pass/issue-1458.rs index b87b3d3aa0d0f..15d809e8208b3 100644 --- a/src/test/run-pass/issue-1458.rs +++ b/src/test/run-pass/issue-1458.rs @@ -12,7 +12,7 @@ fn plus_one(f: fn() -> int) -> int { return f() + 1; } -fn ret_plus_one() -> fn(fn() -> int) -> int { +fn ret_plus_one() -> extern fn(fn() -> int) -> int { return plus_one; } diff --git a/src/test/run-pass/issue-2214.rs b/src/test/run-pass/issue-2214.rs index 05c2595931eb1..efa6d05f9da76 100644 --- a/src/test/run-pass/issue-2214.rs +++ b/src/test/run-pass/issue-2214.rs @@ -10,8 +10,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use libc::{c_double, c_int}; -use f64::*; +use core::cast; +use core::libc::{c_double, c_int}; +use core::f64::*; fn to_c_int(v: &mut int) -> &mut c_int unsafe { cast::reinterpret_cast(&v) @@ -24,13 +25,12 @@ fn lgamma(n: c_double, value: &mut int) -> c_double { #[link_name = "m"] #[abi = "cdecl"] extern mod m { - #[legacy_exports]; #[cfg(unix)] - #[link_name="lgamma_r"] fn lgamma(n: c_double, sign: &mut c_int) + #[link_name="lgamma_r"] pub fn lgamma(n: c_double, sign: &mut c_int) -> c_double; #[cfg(windows)] - #[link_name="__lgamma_r"] fn lgamma(n: c_double, - sign: &mut c_int) -> c_double; + #[link_name="__lgamma_r"] pub fn lgamma(n: c_double, + sign: &mut c_int) -> c_double; } diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index 632fe348d8d94..dc7d5b99d77d9 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -11,31 +11,30 @@ // except according to those terms. // tjc: I don't know why -mod pipes { - #[legacy_exports]; - use cast::{forget, transmute}; +pub mod pipes { + use core::cast::{forget, transmute}; - enum state { + pub enum state { empty, full, blocked, terminated } - impl state : cmp::Eq { + pub impl state : cmp::Eq { pure fn eq(&self, other: &state) -> bool { ((*self) as uint) == ((*other) as uint) } pure fn ne(&self, other: &state) -> bool { !(*self).eq(other) } } - type packet = { + pub type packet = { mut state: state, mut blocked_task: Option, mut payload: Option }; - fn packet() -> *packet unsafe { + pub fn packet() -> *packet unsafe { let p: *packet = cast::transmute(~{ mut state: empty, mut blocked_task: None::, @@ -46,31 +45,30 @@ mod pipes { #[abi = "rust-intrinsic"] mod rusti { - #[legacy_exports]; - fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail; } - fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail; } - fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail; } + pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail; } + pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail; } + pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail; } } - // We should consider moving this to core::unsafe, although I + // 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 { + pub unsafe fn uniquify(+x: *T) -> ~T { unsafe { cast::transmute(move x) } } - fn swap_state_acq(+dst: &mut state, src: state) -> state { + pub fn swap_state_acq(+dst: &mut state, src: state) -> state { unsafe { transmute(rusti::atomic_xchg_acq(transmute(move dst), src as int)) } } - fn swap_state_rel(+dst: &mut state, src: state) -> state { + pub fn swap_state_rel(+dst: &mut state, src: state) -> state { unsafe { transmute(rusti::atomic_xchg_rel(transmute(move dst), src as int)) } } - fn send(-p: send_packet, -payload: T) { + pub fn send(-p: send_packet, -payload: T) { let p = p.unwrap(); let p = unsafe { uniquify(p) }; assert (*p).payload.is_none(); @@ -96,7 +94,7 @@ mod pipes { } } - fn recv(-p: recv_packet) -> Option { + pub fn recv(-p: recv_packet) -> Option { let p = p.unwrap(); let p = unsafe { uniquify(p) }; loop { @@ -117,7 +115,7 @@ mod pipes { } } - fn sender_terminate(p: *packet) { + pub fn sender_terminate(p: *packet) { let p = unsafe { uniquify(p) }; match swap_state_rel(&mut (*p).state, terminated) { empty | blocked => { @@ -134,7 +132,7 @@ mod pipes { } } - fn receiver_terminate(p: *packet) { + pub fn receiver_terminate(p: *packet) { let p = unsafe { uniquify(p) }; match swap_state_rel(&mut (*p).state, terminated) { empty => { @@ -151,11 +149,11 @@ mod pipes { } } - struct send_packet { + pub struct send_packet { mut p: Option<*packet>, } - impl send_packet : Drop { + pub impl send_packet : Drop { fn finalize(&self) { if self.p != None { let mut p = None; @@ -165,7 +163,7 @@ mod pipes { } } - impl send_packet { + pub impl send_packet { fn unwrap() -> *packet { let mut p = None; p <-> self.p; @@ -173,17 +171,17 @@ mod pipes { } } - fn send_packet(p: *packet) -> send_packet { + pub fn send_packet(p: *packet) -> send_packet { send_packet { p: Some(p) } } - struct recv_packet { + pub struct recv_packet { mut p: Option<*packet>, } - impl recv_packet : Drop { + pub impl recv_packet : Drop { fn finalize(&self) { if self.p != None { let mut p = None; @@ -193,7 +191,7 @@ mod pipes { } } - impl recv_packet { + pub impl recv_packet { fn unwrap() -> *packet { let mut p = None; p <-> self.p; @@ -201,25 +199,27 @@ mod pipes { } } - fn recv_packet(p: *packet) -> recv_packet { + pub fn recv_packet(p: *packet) -> recv_packet { recv_packet { p: Some(p) } } - fn entangle() -> (send_packet, recv_packet) { + pub fn entangle() -> (send_packet, recv_packet) { let p = packet(); (send_packet(p), recv_packet(p)) } } -mod pingpong { - #[legacy_exports]; - enum ping = pipes::send_packet; - enum pong = pipes::send_packet; +pub mod pingpong { + use core::cast; + use core::ptr; - fn liberate_ping(-p: ping) -> pipes::send_packet unsafe { - let addr : *pipes::send_packet = match &p { + pub enum ping = ::pipes::send_packet; + pub enum pong = ::pipes::send_packet; + + pub fn liberate_ping(-p: ping) -> ::pipes::send_packet unsafe { + let addr : *::pipes::send_packet = match &p { &ping(ref x) => { cast::transmute(ptr::addr_of(x)) } }; let liberated_value = move *addr; @@ -227,8 +227,8 @@ mod pingpong { move liberated_value } - fn liberate_pong(-p: pong) -> pipes::send_packet unsafe { - let addr : *pipes::send_packet = match &p { + pub fn liberate_pong(-p: pong) -> ::pipes::send_packet unsafe { + let addr : *::pipes::send_packet = match &p { &pong(ref x) => { cast::transmute(ptr::addr_of(x)) } }; let liberated_value = move *addr; @@ -236,24 +236,26 @@ mod pingpong { move liberated_value } - fn init() -> (client::ping, server::ping) { - pipes::entangle() + pub fn init() -> (client::ping, server::ping) { + ::pipes::entangle() } - mod client { - #[legacy_exports]; - type ping = pipes::send_packet; - type pong = pipes::recv_packet; + pub mod client { + use core::option; + use pingpong; + + pub type ping = ::pipes::send_packet; + pub type pong = ::pipes::recv_packet; - fn do_ping(-c: ping) -> pong { - let (sp, rp) = pipes::entangle(); + pub fn do_ping(-c: ping) -> pong { + let (sp, rp) = ::pipes::entangle(); - pipes::send(move c, ping(move sp)); + ::pipes::send(move c, ping(move sp)); move rp } - fn do_pong(-c: pong) -> (ping, ()) { - let packet = pipes::recv(move c); + pub fn do_pong(-c: pong) -> (ping, ()) { + let packet = ::pipes::recv(move c); if packet.is_none() { fail ~"sender closed the connection" } @@ -261,22 +263,23 @@ mod pingpong { } } - mod server { - #[legacy_exports]; - type ping = pipes::recv_packet; - type pong = pipes::send_packet; + pub mod server { + use pingpong; + + pub type ping = ::pipes::recv_packet; + pub type pong = ::pipes::send_packet; - fn do_ping(-c: ping) -> (pong, ()) { - let packet = pipes::recv(move c); + pub fn do_ping(-c: ping) -> (pong, ()) { + let packet = ::pipes::recv(move c); if packet.is_none() { fail ~"sender closed the connection" } (liberate_ping(option::unwrap(move packet)), ()) } - fn do_pong(-c: pong) -> ping { - let (sp, rp) = pipes::entangle(); - pipes::send(move c, pong(move sp)); + pub fn do_pong(-c: pong) -> ping { + let (sp, rp) = ::pipes::entangle(); + ::pipes::send(move c, pong(move sp)); move rp } } diff --git a/src/test/run-pass/issue-3559 b/src/test/run-pass/issue-3559 index 406e055884a5d..505b9b65512f2 100755 Binary files a/src/test/run-pass/issue-3559 and b/src/test/run-pass/issue-3559 differ diff --git a/src/test/run-pass/issue-3559.rs b/src/test/run-pass/issue-3559.rs index ee68a546cafed..da7746681f281 100644 --- a/src/test/run-pass/issue-3559.rs +++ b/src/test/run-pass/issue-3559.rs @@ -12,7 +12,8 @@ // rustc --test map_to_str.rs && ./map_to_str extern mod std; -use io::{WriterUtil}; + +use core::io::{WriterUtil}; use std::map::*; #[cfg(test)] diff --git a/src/test/run-pass/issue-3563-2.rs b/src/test/run-pass/issue-3563-2.rs new file mode 100644 index 0000000000000..aa4598fc90b30 --- /dev/null +++ b/src/test/run-pass/issue-3563-2.rs @@ -0,0 +1,22 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[allow(default_methods)] +trait Canvas { + fn add_point(point: &int); + fn add_points(shapes: &[int]) { + for shapes.each |pt| { + self.add_point(pt) + } + } + +} + +fn main() {} diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs new file mode 100644 index 0000000000000..4517ce770ae40 --- /dev/null +++ b/src/test/run-pass/issue-3563-3.rs @@ -0,0 +1,212 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ASCII art shape renderer. +// Demonstrates traits, impls, operator overloading, non-copyable struct, unit testing. +// To run execute: rustc --test shapes.rs && ./shapes + +// Rust's core library is tightly bound to the language itself so it is automatically linked in. +// However the std library is designed to be optional (for code that must run on constrained +// environments like embedded devices or special environments like kernel code) so it must +// be explicitly linked in. +extern mod std; + +// Extern mod controls linkage. Use controls the visibility of names to modules that are +// already linked in. Using WriterUtil allows us to use the write_line method. +use io::WriterUtil; + +// Represents a position on a canvas. +struct Point +{ + x: int, + y: int, +} + +// Represents an offset on a canvas. (This has the same structure as a Point. +// but different semantics). +struct Size +{ + width: int, + height: int, +} + +struct Rect +{ + top_left: Point, + size: Size, +} + +// TODO: operators + +// Contains the information needed to do shape rendering via ASCII art. +struct AsciiArt +{ + width: uint, + height: uint, + priv fill: char, + priv lines: ~[~[mut char]], + + // This struct can be quite large so we'll disable copying: developers need + // to either pass these structs around via borrowed pointers or move them. + drop {} +} + +// It's common to define a constructor sort of function to create struct instances. +// If there is a canonical constructor it is typically named the same as the type. +// Other constructor sort of functions are typically named from_foo, from_bar, etc. +fn AsciiArt(width: uint, height: uint, fill: char) -> AsciiArt +{ + // Use an anonymous function to build a vector of vectors containing + // blank characters for each position in our canvas. + let lines = do vec::build_sized(height) + |push| + { + for height.times + { + let mut line = ~[]; + vec::grow_set(&mut line, width-1, &'.', '.'); + push(vec::to_mut(line)); + } + }; + + // Rust code often returns values by omitting the trailing semi-colon + // instead of using an explicit return statement. + AsciiArt {width: width, height: height, fill: fill, lines: lines} +} + +// Methods particular to the AsciiArt struct. +impl AsciiArt +{ + fn add_pt(x: int, y: int) + { + if x >= 0 && x < self.width as int + { + if y >= 0 && y < self.height as int + { + // Note that numeric types don't implicitly convert to each other. + let v = y as uint; + let h = x as uint; + + // Vector subscripting will normally copy the element, but &v[i] + // will return a reference which is what we need because the + // element is: + // 1) potentially large + // 2) needs to be modified + let row = &self.lines[v]; + row[h] = self.fill; + } + } + } +} + +// Allows AsciiArt to be converted to a string using the libcore ToStr trait. +// Note that the %s fmt! specifier will not call this automatically. +impl AsciiArt : ToStr +{ + pure fn to_str() -> ~str + { + // Convert each line into a string. + let lines = do self.lines.map |line| {str::from_chars(*line)}; + + // Concatenate the lines together using a new-line. + str::connect(lines, "\n") + } +} + +// This is similar to an interface in other languages: it defines a protocol which +// developers can implement for arbitrary concrete types. +#[allow(default_methods)] +trait Canvas +{ + fn add_point(shape: Point); + fn add_rect(shape: Rect); + + // Unlike interfaces traits support default implementations. + // Got an ICE as soon as I added this method. + fn add_points(shapes: &[Point]) + { + for shapes.each |pt| {self.add_point(*pt)}; + } +} + +// Here we provide an implementation of the Canvas methods for AsciiArt. +// Other implementations could also be provided (e.g. for PDF or Apple's Quartz) +// and code can use them polymorphically via the Canvas trait. +impl AsciiArt : Canvas +{ + fn add_point(shape: Point) + { + self.add_pt(shape.x, shape.y); + } + + fn add_rect(shape: Rect) + { + // Add the top and bottom lines. + for int::range(shape.top_left.x, shape.top_left.x + shape.size.width) + |x| + { + self.add_pt(x, shape.top_left.y); + self.add_pt(x, shape.top_left.y + shape.size.height - 1); + } + + // Add the left and right lines. + for int::range(shape.top_left.y, shape.top_left.y + shape.size.height) + |y| + { + self.add_pt(shape.top_left.x, y); + self.add_pt(shape.top_left.x + shape.size.width - 1, y); + } + } +} + +// Rust's unit testing framework is currently a bit under-developed so we'll use +// this little helper. +pub fn check_strs(actual: &str, expected: &str) -> bool +{ + if actual != expected + { + io::stderr().write_line(fmt!("Found:\n%s\nbut expected\n%s", actual, expected)); + return false; + } + return true; +} + + +fn test_ascii_art_ctor() +{ + let art = AsciiArt(3, 3, '*'); + assert check_strs(art.to_str(), "...\n...\n..."); +} + + +fn test_add_pt() +{ + let art = AsciiArt(3, 3, '*'); + art.add_pt(0, 0); + art.add_pt(0, -10); + art.add_pt(1, 2); + assert check_strs(art.to_str(), "*..\n...\n.*."); +} + + +fn test_shapes() +{ + let art = AsciiArt(4, 4, '*'); + art.add_rect(Rect {top_left: Point {x: 0, y: 0}, size: Size {width: 4, height: 4}}); + art.add_point(Point {x: 2, y: 2}); + assert check_strs(art.to_str(), "****\n*..*\n*.**\n****"); +} + +fn main() { + test_ascii_art_ctor(); + test_add_pt(); + test_shapes(); +} + diff --git a/src/test/run-pass/issue-3609.rs b/src/test/run-pass/issue-3609.rs new file mode 100644 index 0000000000000..9eff98ff42409 --- /dev/null +++ b/src/test/run-pass/issue-3609.rs @@ -0,0 +1,28 @@ +extern mod std; + +use pipes::Chan; + +type RingBuffer = ~[float]; +type SamplesFn = fn~ (samples: &RingBuffer); + +enum Msg +{ + GetSamples(~str, SamplesFn), // sample set name, callback which receives samples +} + +fn foo(name: ~str, samples_chan: Chan) { + do task::spawn + |copy name| + { + let callback: SamplesFn = + |buffer| + { + for uint::range(0, buffer.len()) + |i| {error!("%?: %f", i, buffer[i])} + }; + samples_chan.send(GetSamples(copy name, callback)); + }; +} + +fn main() {} + diff --git a/src/test/run-pass/issue-3656.rs b/src/test/run-pass/issue-3656.rs index bd79e287098c2..66c2a4672b4b0 100644 --- a/src/test/run-pass/issue-3656.rs +++ b/src/test/run-pass/issue-3656.rs @@ -13,7 +13,7 @@ // Incorrect struct size computation in the FFI, because of not taking // the alignment of elements into account. -use libc::*; +use core::libc::*; struct KEYGEN { hash_algorithm: [c_uint * 2], diff --git a/src/test/run-pass/issue-507.rs b/src/test/run-pass/issue-507.rs index 556e597a86da7..52f202a2deb48 100644 --- a/src/test/run-pass/issue-507.rs +++ b/src/test/run-pass/issue-507.rs @@ -15,19 +15,19 @@ https://github.com/graydon/rust/issues/507 */ -fn grandchild(c: core::oldcomm::Chan) { core::oldcomm::send(c, 42); } +fn grandchild(c: ::core::oldcomm::Chan) { ::core::oldcomm::send(c, 42); } -fn child(c: core::oldcomm::Chan) { +fn child(c: ::core::oldcomm::Chan) { task::spawn(|| grandchild(c) ) } fn main() { - let p = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); task::spawn(|| child(ch) ); - let x: int = core::oldcomm::recv(p); + let x: int = ::core::oldcomm::recv(p); log(debug, x); diff --git a/src/test/run-pass/issue-687.rs b/src/test/run-pass/issue-687.rs index 9cfec06007c95..53827bb63fa3c 100644 --- a/src/test/run-pass/issue-687.rs +++ b/src/test/run-pass/issue-687.rs @@ -10,18 +10,18 @@ enum msg { closed, received(~[u8]), } -fn producer(c: core::oldcomm::Chan<~[u8]>) { - core::oldcomm::send(c, ~[1u8, 2u8, 3u8, 4u8]); +fn producer(c: ::core::oldcomm::Chan<~[u8]>) { + ::core::oldcomm::send(c, ~[1u8, 2u8, 3u8, 4u8]); let empty: ~[u8] = ~[]; - core::oldcomm::send(c, empty); + ::core::oldcomm::send(c, empty); } -fn packager(cb: core::oldcomm::Chan>, msg: core::oldcomm::Chan) { - let p: core::oldcomm::Port<~[u8]> = core::oldcomm::Port(); - core::oldcomm::send(cb, core::oldcomm::Chan(&p)); +fn packager(cb: ::core::oldcomm::Chan<::core::oldcomm::Chan<~[u8]>>, msg: ::core::oldcomm::Chan) { + let p: ::core::oldcomm::Port<~[u8]> = ::core::oldcomm::Port(); + ::core::oldcomm::send(cb, ::core::oldcomm::Chan(&p)); loop { debug!("waiting for bytes"); - let data = core::oldcomm::recv(p); + let data = ::core::oldcomm::recv(p); debug!("got bytes"); if vec::len(data) == 0u { debug!("got empty bytes, quitting"); @@ -29,26 +29,26 @@ fn packager(cb: core::oldcomm::Chan>, msg: core::oldc } debug!("sending non-empty buffer of length"); log(debug, vec::len(data)); - core::oldcomm::send(msg, received(data)); + ::core::oldcomm::send(msg, received(data)); debug!("sent non-empty buffer"); } debug!("sending closed message"); - core::oldcomm::send(msg, closed); + ::core::oldcomm::send(msg, closed); debug!("sent closed message"); } fn main() { - let p: core::oldcomm::Port = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); - let recv_reader: core::oldcomm::Port> = core::oldcomm::Port(); - let recv_reader_chan = core::oldcomm::Chan(&recv_reader); + let p: ::core::oldcomm::Port = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); + let recv_reader: ::core::oldcomm::Port<::core::oldcomm::Chan<~[u8]>> = ::core::oldcomm::Port(); + let recv_reader_chan = ::core::oldcomm::Chan(&recv_reader); let pack = task::spawn(|| packager(recv_reader_chan, ch) ); - let source_chan: core::oldcomm::Chan<~[u8]> = core::oldcomm::recv(recv_reader); + let source_chan: ::core::oldcomm::Chan<~[u8]> = ::core::oldcomm::recv(recv_reader); let prod = task::spawn(|| producer(source_chan) ); loop { - let msg = core::oldcomm::recv(p); + let msg = ::core::oldcomm::recv(p); match msg { closed => { debug!("Got close message"); break; } received(data) => { diff --git a/src/test/run-pass/issue-783.rs b/src/test/run-pass/issue-783.rs index 3820ff770227c..75404c01fc53a 100644 --- a/src/test/run-pass/issue-783.rs +++ b/src/test/run-pass/issue-783.rs @@ -10,14 +10,14 @@ fn a() { fn doit() { - fn b(c: core::oldcomm::Chan>) { - let p = core::oldcomm::Port(); - core::oldcomm::send(c, core::oldcomm::Chan(&p)); + fn b(c: ::core::oldcomm::Chan<::core::oldcomm::Chan>) { + let p = ::core::oldcomm::Port(); + ::core::oldcomm::send(c, ::core::oldcomm::Chan(&p)); } - let p = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); task::spawn(|| b(ch) ); - core::oldcomm::recv(p); + ::core::oldcomm::recv(p); } let mut i = 0; while i < 100 { diff --git a/src/test/run-pass/ivec-tag.rs b/src/test/run-pass/ivec-tag.rs index 7066b5f63cd60..31651ab7c20a6 100644 --- a/src/test/run-pass/ivec-tag.rs +++ b/src/test/run-pass/ivec-tag.rs @@ -1,13 +1,13 @@ -fn producer(c: core::oldcomm::Chan<~[u8]>) { - core::oldcomm::send(c, +fn producer(c: ::core::oldcomm::Chan<~[u8]>) { + ::core::oldcomm::send(c, ~[1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8, 13u8]); } fn main() { - let p: core::oldcomm::Port<~[u8]> = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p: ::core::oldcomm::Port<~[u8]> = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); let prod = task::spawn(|| producer(ch) ); - let data: ~[u8] = core::oldcomm::recv(p); + let data: ~[u8] = ::core::oldcomm::recv(p); } diff --git a/src/test/run-pass/lazychan.rs b/src/test/run-pass/lazychan.rs index 34244c2ef01cb..4e5ce6cd0915f 100644 --- a/src/test/run-pass/lazychan.rs +++ b/src/test/run-pass/lazychan.rs @@ -10,21 +10,21 @@ // except according to those terms. fn main() { - let p = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&p); let mut y: int; task::spawn(|| child(ch) ); - y = core::oldcomm::recv(p); + y = ::core::oldcomm::recv(p); debug!("received 1"); log(debug, y); assert (y == 10); task::spawn(|| child(ch) ); - y = core::oldcomm::recv(p); + y = ::core::oldcomm::recv(p); debug!("received 2"); log(debug, y); assert (y == 10); } -fn child(c: core::oldcomm::Chan) { core::oldcomm::send(c, 10); } +fn child(c: ::core::oldcomm::Chan) { ::core::oldcomm::send(c, 10); } diff --git a/src/test/run-pass/pipe-pingpong-bounded.rs b/src/test/run-pass/pipe-pingpong-bounded.rs index 8589bbb8e257f..803f7f06b512c 100644 --- a/src/test/run-pass/pipe-pingpong-bounded.rs +++ b/src/test/run-pass/pipe-pingpong-bounded.rs @@ -18,17 +18,15 @@ // This was generated initially by the pipe compiler, but it's been // modified in hopefully straightforward ways. mod pingpong { - #[legacy_exports]; - use pipes::*; + use core::pipes::*; + use core::ptr; - type packets = { - // This is probably a resolve bug, I forgot to export packet, - // but since I didn't import pipes::*, it worked anyway. + pub type packets = { ping: Packet, pong: Packet, }; - fn init() -> (client::ping, server::ping) { + pub fn init() -> (client::ping, server::ping) { let buffer = ~{ header: BufferHeader(), data: { @@ -42,50 +40,51 @@ mod pingpong { ptr::addr_of(&(data.ping)) } } - enum ping = server::pong; - enum pong = client::ping; - mod client { - #[legacy_exports]; - fn ping(+pipe: ping) -> pong { + pub enum ping = server::pong; + pub enum pong = client::ping; + pub mod client { + use core::ptr; + + pub fn ping(+pipe: ping) -> pong { { 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(move s); - pipes::send(move pipe, move message); + let message = ::pingpong::ping(move s); + ::pipes::send(move pipe, move message); move c } } - type ping = pipes::SendPacketBuffered; - type pong = pipes::RecvPacketBuffered; + pub type ping = pipes::SendPacketBuffered<::pingpong::ping, + ::pingpong::packets>; + pub type pong = pipes::RecvPacketBuffered<::pingpong::pong, + ::pingpong::packets>; } - mod server { - #[legacy_exports]; - type ping = pipes::RecvPacketBuffered; - fn pong(+pipe: pong) -> ping { + pub mod server { + use core::ptr; + + pub type ping = pipes::RecvPacketBuffered<::pingpong::ping, + ::pingpong::packets>; + pub fn pong(+pipe: pong) -> ping { { let b = pipe.reuse_buffer(); let s = SendPacketBuffered(ptr::addr_of(&(b.buffer.data.ping))); let c = RecvPacketBuffered(ptr::addr_of(&(b.buffer.data.ping))); - let message = pingpong::pong(move s); - pipes::send(move pipe, move message); + let message = ::pingpong::pong(move s); + ::pipes::send(move pipe, move message); move c } } - type pong = pipes::SendPacketBuffered; + pub type pong = pipes::SendPacketBuffered<::pingpong::pong, + ::pingpong::packets>; } } mod test { - #[legacy_exports]; use pipes::recv; use pingpong::{ping, pong}; - fn client(-chan: pingpong::client::ping) { + pub fn client(-chan: ::pingpong::client::ping) { use pingpong::client; let chan = client::ping(move chan); return; @@ -94,7 +93,7 @@ mod test { log(error, "Received pong"); } - fn server(-chan: pingpong::server::ping) { + pub fn server(-chan: ::pingpong::server::ping) { use pingpong::server; let ping(chan) = recv(move chan); return; @@ -105,7 +104,7 @@ mod test { } fn main() { - let (client_, server_) = pingpong::init(); + let (client_, server_) = ::pingpong::init(); let client_ = ~mut Some(move client_); let server_ = ~mut Some(move server_); do task::spawn |move client_| { diff --git a/src/test/run-pass/pipe-pingpong-proto.rs b/src/test/run-pass/pipe-pingpong-proto.rs index 88db8953b8c33..7fb77cba3bde9 100644 --- a/src/test/run-pass/pipe-pingpong-proto.rs +++ b/src/test/run-pass/pipe-pingpong-proto.rs @@ -12,6 +12,7 @@ // An example to make sure the protocol parsing syntax extension works. +use core::option; proto! pingpong ( ping:send { @@ -24,11 +25,10 @@ proto! pingpong ( ) mod test { - #[legacy_exports]; - use pipes::recv; + use core::pipes::recv; use pingpong::{ping, pong}; - fn client(-chan: pingpong::client::ping) { + pub fn client(-chan: ::pingpong::client::ping) { use pingpong::client; let chan = client::ping(move chan); @@ -37,7 +37,7 @@ mod test { log(error, ~"Received pong"); } - fn server(-chan: pingpong::server::ping) { + pub fn server(-chan: ::pingpong::server::ping) { use pingpong::server; let ping(chan) = recv(move chan); diff --git a/src/test/run-pass/recursion.rs b/src/test/run-pass/recursion.rs new file mode 100644 index 0000000000000..8cc2c8cc80a55 --- /dev/null +++ b/src/test/run-pass/recursion.rs @@ -0,0 +1,34 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// xfail-test +enum Nil {Nil} +struct Cons {head:int, tail:T} +trait Dot {fn dot(other:self) -> int;} +impl Nil:Dot { + fn dot(_:Nil) -> int {0} +} +impl Cons:Dot { + fn dot(other:Cons) -> int { + self.head * other.head + self.tail.dot(other.tail) + } +} +fn test (n:int, i:int, first:T, second:T) ->int { + match n { + 0 => {first.dot(second)} + // Error message should be here. It should be a type error + // to instantiate `test` at a type other than T. (See #4287) + _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} + } +} +fn main() { + let n = test(1, 0, Nil, Nil); + io::println(fmt!("%d", n)); +} diff --git a/src/test/run-pass/rt-circular-buffer.rs b/src/test/run-pass/rt-circular-buffer.rs index dca62e0f9dffa..1ddeee336e3c0 100644 --- a/src/test/run-pass/rt-circular-buffer.rs +++ b/src/test/run-pass/rt-circular-buffer.rs @@ -13,7 +13,7 @@ // Regression tests for circular_buffer when using a unit // that has a size that is not a power of two -// A 12-byte unit to core::oldcomm::send over the channel +// A 12-byte unit to ::core::oldcomm::send over the channel type record = {val1: u32, val2: u32, val3: u32}; @@ -22,52 +22,52 @@ type record = {val1: u32, val2: u32, val3: u32}; // power of two so needs to be rounded up. Don't trigger any // assertions. fn test_init() { - let myport = core::oldcomm::Port(); - let mychan = core::oldcomm::Chan(&myport); + let myport = ::core::oldcomm::Port(); + let mychan = ::core::oldcomm::Chan(&myport); let val: record = {val1: 0u32, val2: 0u32, val3: 0u32}; - core::oldcomm::send(mychan, val); + ::core::oldcomm::send(mychan, val); } // Dump lots of items into the channel so it has to grow. // Don't trigger any assertions. fn test_grow() { - let myport = core::oldcomm::Port(); - let mychan = core::oldcomm::Chan(&myport); + let myport = ::core::oldcomm::Port(); + let mychan = ::core::oldcomm::Chan(&myport); for uint::range(0u, 100u) |i| { let val: record = {val1: 0u32, val2: 0u32, val3: 0u32}; - core::oldcomm::send(mychan, val); + ::core::oldcomm::send(mychan, val); } } // Don't allow the buffer to shrink below it's original size fn test_shrink1() { - let myport = core::oldcomm::Port(); - let mychan = core::oldcomm::Chan(&myport); - core::oldcomm::send(mychan, 0i8); - let x = core::oldcomm::recv(myport); + let myport = ::core::oldcomm::Port(); + let mychan = ::core::oldcomm::Chan(&myport); + ::core::oldcomm::send(mychan, 0i8); + let x = ::core::oldcomm::recv(myport); } fn test_shrink2() { - let myport = core::oldcomm::Port(); - let mychan = core::oldcomm::Chan(&myport); + let myport = ::core::oldcomm::Port(); + let mychan = ::core::oldcomm::Chan(&myport); for uint::range(0u, 100u) |_i| { let val: record = {val1: 0u32, val2: 0u32, val3: 0u32}; - core::oldcomm::send(mychan, val); + ::core::oldcomm::send(mychan, val); } - for uint::range(0u, 100u) |_i| { let x = core::oldcomm::recv(myport); } + for uint::range(0u, 100u) |_i| { let x = ::core::oldcomm::recv(myport); } } // Test rotating the buffer when the unit size is not a power of two fn test_rotate() { - let myport = core::oldcomm::Port(); - let mychan = core::oldcomm::Chan(&myport); + let myport = ::core::oldcomm::Port(); + let mychan = ::core::oldcomm::Chan(&myport); for uint::range(0u, 100u) |i| { let val = {val1: i as u32, val2: i as u32, val3: i as u32}; - core::oldcomm::send(mychan, val); - let x = core::oldcomm::recv(myport); + ::core::oldcomm::send(mychan, val); + let x = ::core::oldcomm::recv(myport); assert (x.val1 == i as u32); assert (x.val2 == i as u32); assert (x.val3 == i as u32); @@ -78,16 +78,16 @@ fn test_rotate() { // Test rotating and growing the buffer when // the unit size is not a power of two fn test_rotate_grow() { - let myport = core::oldcomm::Port::(); - let mychan = core::oldcomm::Chan(&myport); + let myport = ::core::oldcomm::Port::(); + let mychan = ::core::oldcomm::Chan(&myport); for uint::range(0u, 10u) |j| { for uint::range(0u, 10u) |i| { let val: record = {val1: i as u32, val2: i as u32, val3: i as u32}; - core::oldcomm::send(mychan, val); + ::core::oldcomm::send(mychan, val); } for uint::range(0u, 10u) |i| { - let x = core::oldcomm::recv(myport); + let x = ::core::oldcomm::recv(myport); assert (x.val1 == i as u32); assert (x.val2 == i as u32); assert (x.val3 == i as u32); diff --git a/src/test/run-pass/send-resource.rs b/src/test/run-pass/send-resource.rs index a85b01acc8edd..39ef99a72b611 100644 --- a/src/test/run-pass/send-resource.rs +++ b/src/test/run-pass/send-resource.rs @@ -23,12 +23,12 @@ fn test(f: int) -> test { } fn main() { - let p = core::oldcomm::Port(); - let c = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let c = ::core::oldcomm::Chan(&p); do task::spawn() { - let p = core::oldcomm::Port(); - c.send(core::oldcomm::Chan(&p)); + let p = ::core::oldcomm::Port(); + c.send(::core::oldcomm::Chan(&p)); let _r = p.recv(); } diff --git a/src/test/run-pass/struct-field-assignability.rs b/src/test/run-pass/struct-field-assignability.rs new file mode 100644 index 0000000000000..93c490bd5f393 --- /dev/null +++ b/src/test/run-pass/struct-field-assignability.rs @@ -0,0 +1,9 @@ +struct Foo { + x: &int +} + +fn main() { + let f = Foo { x: @3 }; + assert *f.x == 3; +} + diff --git a/src/test/run-pass/super.rs b/src/test/run-pass/super.rs new file mode 100644 index 0000000000000..0eb922643c620 --- /dev/null +++ b/src/test/run-pass/super.rs @@ -0,0 +1,12 @@ +pub mod a { + pub fn f() {} + pub mod b { + fn g() { + super::f(); + } + } +} + +fn main() { +} + diff --git a/src/test/run-pass/task-comm.rs b/src/test/run-pass/task-comm.rs index d95f4af791c65..311da9762b3c7 100644 --- a/src/test/run-pass/task-comm.rs +++ b/src/test/run-pass/task-comm.rs @@ -17,12 +17,12 @@ fn main() { test06(); } -fn test00_start(ch: core::oldcomm::Chan, message: int, count: int) { +fn test00_start(ch: ::core::oldcomm::Chan, message: int, count: int) { debug!("Starting test00_start"); let mut i: int = 0; while i < count { debug!("Sending Message"); - core::oldcomm::send(ch, message + 0); + ::core::oldcomm::send(ch, message + 0); i = i + 1; } debug!("Ending test00_start"); @@ -33,8 +33,8 @@ fn test00() { let number_of_messages: int = 4; debug!("Creating tasks"); - let po = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&po); + let po = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&po); let mut i: int = 0; @@ -50,7 +50,7 @@ fn test00() { let mut sum: int = 0; for results.each |r| { i = 0; - while i < number_of_messages { sum += core::oldcomm::recv(po); i = i + 1; } + while i < number_of_messages { sum += ::core::oldcomm::recv(po); i = i + 1; } } for results.each |r| { r.recv(); } @@ -63,19 +63,19 @@ fn test00() { } fn test01() { - let p = core::oldcomm::Port(); + let p = ::core::oldcomm::Port(); debug!("Reading from a port that is never written to."); - let value: int = core::oldcomm::recv(p); + let value: int = ::core::oldcomm::recv(p); log(debug, value); } fn test02() { - let p = core::oldcomm::Port(); - let c = core::oldcomm::Chan(&p); + let p = ::core::oldcomm::Port(); + let c = ::core::oldcomm::Chan(&p); debug!("Writing to a local task channel."); - core::oldcomm::send(c, 42); + ::core::oldcomm::send(c, 42); debug!("Reading from a local task port."); - let value: int = core::oldcomm::recv(p); + let value: int = ::core::oldcomm::recv(p); log(debug, value); } @@ -93,22 +93,22 @@ fn test04() { debug!("Finishing up."); } -fn test05_start(ch: core::oldcomm::Chan) { - core::oldcomm::send(ch, 10); - core::oldcomm::send(ch, 20); - core::oldcomm::send(ch, 30); - core::oldcomm::send(ch, 30); - core::oldcomm::send(ch, 30); +fn test05_start(ch: ::core::oldcomm::Chan) { + ::core::oldcomm::send(ch, 10); + ::core::oldcomm::send(ch, 20); + ::core::oldcomm::send(ch, 30); + ::core::oldcomm::send(ch, 30); + ::core::oldcomm::send(ch, 30); } fn test05() { - let po = core::oldcomm::Port(); - let ch = core::oldcomm::Chan(&po); + let po = ::core::oldcomm::Port(); + let ch = ::core::oldcomm::Chan(&po); task::spawn(|| test05_start(ch) ); let mut value: int; - value = core::oldcomm::recv(po); - value = core::oldcomm::recv(po); - value = core::oldcomm::recv(po); + value = ::core::oldcomm::recv(po); + value = ::core::oldcomm::recv(po); + value = ::core::oldcomm::recv(po); log(debug, value); } diff --git a/src/test/run-pass/trait-static-method-overwriting.rs b/src/test/run-pass/trait-static-method-overwriting.rs index 17309d27900f8..d8a8fc26d7fdf 100644 --- a/src/test/run-pass/trait-static-method-overwriting.rs +++ b/src/test/run-pass/trait-static-method-overwriting.rs @@ -1,3 +1,5 @@ +// xfail-fast + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -17,7 +19,7 @@ mod base { dummy: (), } - pub impl Foo : base::HasNew { + pub impl Foo : ::base::HasNew { static pure fn new() -> Foo { unsafe { io::println("Foo"); } Foo { dummy: () } @@ -28,7 +30,7 @@ mod base { dummy: (), } - pub impl Bar : base::HasNew { + pub impl Bar : ::base::HasNew { static pure fn new() -> Bar { unsafe { io::println("Bar"); } Bar { dummy: () } diff --git a/src/test/run-pass/vec-matching-autoslice.rs b/src/test/run-pass/vec-matching-autoslice.rs index badb0245b8174..298253b8825d3 100644 --- a/src/test/run-pass/vec-matching-autoslice.rs +++ b/src/test/run-pass/vec-matching-autoslice.rs @@ -1,22 +1,22 @@ fn main() { let x = @[1, 2, 3]; match x { - [2, .._] => core::util::unreachable(), + [2, .._] => ::core::util::unreachable(), [1, ..tail] => { assert tail == [2, 3]; } - [_] => core::util::unreachable(), - [] => core::util::unreachable() + [_] => ::core::util::unreachable(), + [] => ::core::util::unreachable() } let y = (~[(1, true), (2, false)], 0.5); match y { - ([_, _, _], 0.5) => core::util::unreachable(), + ([_, _, _], 0.5) => ::core::util::unreachable(), ([(1, a), (b, false), ..tail], _) => { assert a == true; assert b == 2; assert tail.is_empty(); } - ([..tail], _) => core::util::unreachable() + ([..tail], _) => ::core::util::unreachable() } } diff --git a/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs b/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs index ea21408788e88..6b005bf0e1218 100644 --- a/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs +++ b/src/test/run-pass/vec-matching-legal-tail-element-borrow.rs @@ -3,7 +3,7 @@ fn main() { if !x.is_empty() { let el = match x { [1, ..ref tail] => &tail[0], - _ => core::util::unreachable() + _ => ::core::util::unreachable() }; io::println(fmt!("%d", *el)); } diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index a3840c9f561f8..687788d8ce83d 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -14,7 +14,7 @@ fn main() { let x = [1, 2, 3, 4, 5]; match x { [a, b, c, d, e, f] => { - core::util::unreachable(); + ::core::util::unreachable(); } [a, b, c, d, e] => { assert a == 1; @@ -24,7 +24,7 @@ fn main() { assert e == 5; } _ => { - core::util::unreachable(); + ::core::util::unreachable(); } } diff --git a/src/test/run-pass/vec-tail-matching.rs b/src/test/run-pass/vec-tail-matching.rs index e2b68a11776e1..8a50d7b1643ac 100644 --- a/src/test/run-pass/vec-tail-matching.rs +++ b/src/test/run-pass/vec-tail-matching.rs @@ -17,19 +17,19 @@ fn main() { match tail { [Foo { _ }, _, Foo { _ }, ..tail] => { - core::util::unreachable(); + ::core::util::unreachable(); } [Foo { string: a }, Foo { string: b }] => { assert a == ~"bar"; assert b == ~"baz"; } _ => { - core::util::unreachable(); + ::core::util::unreachable(); } } } _ => { - core::util::unreachable(); + ::core::util::unreachable(); } } }