]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15051 : retep998/rust/master, r=alexcrichton
authorbors <bors@rust-lang.org>
Fri, 4 Jul 2014 15:31:27 +0000 (15:31 +0000)
committerbors <bors@rust-lang.org>
Fri, 4 Jul 2014 15:31:27 +0000 (15:31 +0000)
This implementation does have the minor issue of not handling things correctly when a codepoint is split across multiple writes or reads, but its better than not having unicode support at all.

Adds a Windows specific struct `WindowsTTY` in `libnative` and make `tty_open` create that struct on Windows. Adds needed functions and constants to `c_win32.rs`.

Libuv still needs to be updated before #15028 can be closed.

135 files changed:
.travis.yml
man/rustc.1
man/rustdoc.1
mk/main.mk
mk/platform.mk
src/doc/README.md
src/doc/guide.md
src/doc/rust.css
src/doc/rust.md
src/doc/rustdoc.md
src/doc/tutorial.md
src/etc/install.sh
src/etc/kate/rust.xml
src/liballoc/arc.rs
src/liballoc/lib.rs
src/libarena/lib.rs
src/libcollections/lib.rs
src/libcollections/str.rs
src/libcollections/vec.rs
src/libcore/lib.rs
src/libcore/num/mod.rs
src/libcore/tuple.rs [deleted file]
src/libcore/tuple/mod.rs [new file with mode: 0644]
src/libcore/tuple/unit.rs [new file with mode: 0644]
src/libcoretest/num/int_macros.rs
src/libcoretest/num/uint_macros.rs
src/libdebug/lib.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/libfourcc/lib.rs
src/libgetopts/lib.rs
src/libglob/lib.rs
src/libgraphviz/lib.rs
src/libgreen/lib.rs
src/libgreen/stack.rs
src/libhexfloat/lib.rs
src/liblibc/lib.rs
src/liblog/lib.rs
src/libnative/io/net.rs
src/libnative/io/pipe_win32.rs
src/libnative/io/timer_unix.rs
src/libnative/lib.rs
src/libnum/lib.rs
src/libnum/rational.rs
src/librand/lib.rs
src/libregex/lib.rs
src/libregex_macros/lib.rs
src/librlibc/lib.rs
src/librustc/back/link.rs
src/librustc/front/std_inject.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/borrowck/gather_loans/gather_moves.rs
src/librustc/middle/borrowck/gather_loans/move_error.rs
src/librustc/middle/check_match.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/kind.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/privacy.rs
src/librustc/middle/resolve.rs
src/librustc/middle/save/mod.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/_match.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/infer/unify.rs
src/librustc/middle/typeck/mod.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/librustdoc/lib.rs
src/librustrt/c_str.rs
src/librustrt/lib.rs
src/librustrt/libunwind.rs
src/librustrt/task.rs
src/librustrt/thread.rs
src/librustuv/lib.rs
src/librustuv/stream.rs
src/librustuv/timer.rs
src/libsemver/lib.rs
src/libserialize/lib.rs
src/libstd/io/net/ip.rs
src/libstd/io/net/udp.rs
src/libstd/lib.rs
src/libstd/os.rs
src/libstd/rt/backtrace.rs
src/libsync/comm/oneshot.rs
src/libsync/comm/shared.rs
src/libsync/lib.rs
src/libsync/mutex.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/ext/asm.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/cfg.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/format.rs
src/libsyntax/ext/quote.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/libtime/lib.rs
src/liburl/lib.rs
src/libuuid/lib.rs
src/test/auxiliary/issue-11908-1.rs
src/test/auxiliary/issue-11908-2.rs
src/test/compile-fail/borrowck-overloaded-call.rs [new file with mode: 0644]
src/test/compile-fail/issue-10536.rs [new file with mode: 0644]
src/test/compile-fail/kindck-impl-type-params.rs [new file with mode: 0644]
src/test/compile-fail/trait-bounds-impl-comparison-1.rs [new file with mode: 0644]
src/test/compile-fail/trait-bounds-impl-comparison-2.rs [new file with mode: 0644]
src/test/compile-fail/type-params-in-different-spaces-1.rs [new file with mode: 0644]
src/test/compile-fail/type-params-in-different-spaces-2.rs [new file with mode: 0644]
src/test/compile-fail/type-params-in-different-spaces-3.rs [new file with mode: 0644]
src/test/debuginfo/type-names.rs [new file with mode: 0644]
src/test/run-make/crate-data-smoke/Makefile
src/test/run-make/crate-data-smoke/crate.rs
src/test/run-pass/issue-12285.rs [new file with mode: 0644]
src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs [new file with mode: 0644]
src/test/run-pass/use.rs

index e3cec33ad070d340397e66e7e6a2f6295f3da90a..dd62defa02039ad5934b688d94fe07980706b4df 100644 (file)
@@ -41,7 +41,7 @@ script: |
     if [[ $LLVM_VERSION != '3.4' ]]; then exit 0; fi
   fi &&
   make tidy &&
-  travis_wait make -j4 rustc-stage1 &&
+  make -j4 rustc-stage1 RUSTFLAGS='-Z time-passes' &&
   make check-stage1-std check-stage1-rpass check-stage1-cfail check-stage1-rfail check-stage1-doc
 
 env:
index a71547893ad0b828e968814b24bc2cef28b8dadd..df65cf7bb37ffdd41d4179763c0f7557adbb12a7 100644 (file)
@@ -1,4 +1,4 @@
-.TH RUSTC "1" "March 2014" "rustc 0.11-pre" "User Commands"
+.TH RUSTC "1" "March 2014" "rustc 0.11.0" "User Commands"
 .SH NAME
 rustc \- The Rust compiler
 .SH SYNOPSIS
index d5795c328e7d52d8bf4ef7382d355fb2862f0d8a..03414ca163ec2a01e09e4d83e5942fe4ccf32b51 100644 (file)
@@ -1,4 +1,4 @@
-.TH RUSTDOC "1" "March 2014" "rustdoc 0.11-pre" "User Commands"
+.TH RUSTDOC "1" "March 2014" "rustdoc 0.11.0" "User Commands"
 .SH NAME
 rustdoc \- generate documentation from Rust source code
 .SH SYNOPSIS
index 3f6103bafa52daee662391eb5a003ee03dce6626..c4be89033a648933ab411ad7196184b582e074f5 100644 (file)
@@ -14,7 +14,7 @@
 
 # The version number
 CFG_RELEASE_NUM=0.11.0
-CFG_RELEASE_LABEL=-pre
+CFG_RELEASE_LABEL=
 
 ifndef CFG_ENABLE_NIGHTLY
 # This is the normal version string
index 3c6296d610aac8e5b85d0809730e7dc861982603..d1ec7c6500d25720ff7a875825392ff83f80a40e 100644 (file)
@@ -461,6 +461,7 @@ CFG_PATH_MUNGE_i686-pc-mingw32 :=
 CFG_LDPATH_i686-pc-mingw32 :=$(CFG_LDPATH_i686-pc-mingw32):$(PATH)
 CFG_RUN_i686-pc-mingw32=PATH="$(CFG_LDPATH_i686-pc-mingw32):$(1)" $(2)
 CFG_RUN_TARG_i686-pc-mingw32=$(call CFG_RUN_i686-pc-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
+RUSTC_FLAGS_i686-pc-mingw32=-C link-args="-Wl,--large-address-aware"
 
 # i586-mingw32msvc configuration
 CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc
index 759a21af0ce5f1d4de1a19928f0ff4e572f26c0c..f8b0f07d19afbab0badcb490bf378cf95ad733e0 100644 (file)
@@ -53,12 +53,12 @@ To generate .pot and .po files, do something like:
 ~~~~
 po4a --copyright-holder="The Rust Project Developers" \
     --package-name="Rust" \
-    --package-version="0.11.0-pre" \
+    --package-version="0.11.0" \
     -M UTF-8 -L UTF-8 \
     src/doc/po4a.conf
 ~~~~
 
-(the version number must be changed if it is not 0.11.0-pre now.)
+(the version number must be changed if it is not 0.11.0 now.)
 
 Now you can translate documents with .po files, commonly used with gettext. If
 you are not familiar with gettext-based translation, please read the online
index 0fc9671c4db292c4bcc05baa38eea38c1a52c261..dc9608563e176c08190d8ccd865c2037539837f6 100644 (file)
@@ -53,7 +53,7 @@ an uninstall option.
 
 You can re-run this script any time you want to update Rust. Which, at this
 point, is often. Rust is still pre-1.0, and so people assume that you're using
-a very recent Rust. 
+a very recent Rust.
 
 This brings me to one other point: some people, and somewhat rightfully so, get
 very upset when we tell you to `curl | sudo sh`. And they should be! Basically,
@@ -168,7 +168,7 @@ Success! Let's go over what just happened in detail.
 
 ```
 fn main() {
-   
+
 }
 ```
 
@@ -395,7 +395,7 @@ Once you have this file in place, we should be ready to build! Try this:
 ```{bash}
 $ cargo build
    Compiling hello_world v0.1.0 (file:/home/yourname/projects/hello_world)
-$ ./target/hello_world 
+$ ./target/hello_world
 Hello, world!
 ```
 
@@ -515,9 +515,45 @@ let x: int = 5;
 ```
 
 If I asked you to read this out loud to the rest of the class, you'd say "`x`
-is a binding with the type `int` and the value `five`." Rust requires you to
-initialize the binding with a value before you're allowed to use it. If
-we try...
+is a binding with the type `int` and the value `five`."
+
+By default, bindings are **immutable**. This code will not compile:
+
+```{ignore}
+let x = 5i;
+x = 10i;
+```
+
+It will give you this error:
+
+```{ignore,notrust}
+error: re-assignment of immutable variable `x`
+     x = 10i;
+     ^~~~~~~
+```
+
+If you want a binding to be mutable, you can use `mut`:
+
+```{rust}
+let mut x = 5i;
+x = 10i;
+```
+
+There is no single reason that bindings are immutable by default, but we can
+think about it through one of Rust's primary focuses: safety. If you forget to
+say `mut`, the compiler will catch it, and let you know that you have mutated
+something you may not have cared to mutate. If bindings were mutable by
+default, the compiler would not be able to tell you this. If you _did_ intend
+mutation, then the solution is quite easy: add `mut`.
+
+There are other good reasons to avoid mutable state when possible, but they're
+out of the scope of this guide. In general, you can often avoid explicit
+mutation, and so it is preferable in Rust. That said, sometimes, mutation is
+what you need, so it's not verboten.
+
+Let's get back to bindings. Rust variable bindings have one more aspect that
+differs from other languages: bindings are required to be initialized with a
+value before you're allowed to use it. If we try...
 
 ```{ignore}
 let x;
@@ -611,8 +647,301 @@ concept: `if`.
 
 ## If
 
+Rust's take on `if` is not particularly complex, but it's much more like the
+`if` you'll find in a dynamically typed language than in a more traditional
+systems language. So let's talk about it, to make sure you grasp the nuances.
+
+`if` is a specific form of a more general concept, the 'branch.' The name comes
+from a branch in a tree: a decision point, where depending on a choice,
+multiple paths can be taken.
+
+In the case of `if`, there is one choice that leads down two paths:
+
+```rust
+let x = 5i;
+
+if x == 5i {
+    println!("x is five!");
+}
+```
+
+If we changed the value of `x` to something else, this line would not print.
+More specifically, if the expression after the `if` evaluates to `true`, then
+the block is executed. If it's `false`, then it is not.
+
+If you want something to happen in the `false` case, use an `else`:
+
+```
+let x = 5i;
+
+if x == 5i {
+    println!("x is five!");
+} else {
+    println!("x is not five :(");
+}
+```
+
+This is all pretty standard. However, you can also do this:
+
+
+```
+let x = 5i;
+
+let y = if x == 5i {
+    10i
+} else {
+    15i
+};
+```
+
+Which we can (and probably should) write like this:
+
+```
+let x = 5i;
+
+let y = if x == 5i { 10i } else { 15i };
+```
+
+This reveals two interesting things about Rust: it is an expression-based
+language, and semicolons are different than in other 'curly brace and
+semicolon'-based languages. These two things are related.
+
+### Expressions vs. Statements
+
+Rust is primarily an expression based language. There are only two kinds of
+statements, and everything else is an expression.
+
+So what's the difference? Expressions return a value, and statements do not.
+In many languages, `if` is a statement, and therefore, `let x = if ...` would
+make no sense. But in Rust, `if` is an expression, which means that it returns
+a value. We can then use this value to initialize the binding.
+
+Speaking of which, bindings are a kind of the first of Rust's two statements.
+The proper name is a **declaration statement**. So far, `let` is the only kind
+of declaration statement we've seen. Let's talk about that some more.
+
+In some languages, variable bindings can be written as expressions, not just
+statements. Like Ruby:
+
+```{ruby}
+x = y = 5
+```
+
+In Rust, however, using `let` to introduce a binding is _not_ an expression. The
+following will produce a compile-time error:
+
+```{ignore}
+let x = (let y = 5i); // found `let` in ident position
+```
+
+The compiler is telling us here that it was expecting to see the beginning of
+an expression, and a `let` can only begin a statement, not an expression.
+
+However, re-assigning to a mutable binding is an expression:
+
+```{rust}
+let mut x = 0i;
+let y = x = 5i;
+```
+
+In this case, we have an assignment expression (`x = 5`) whose value is
+being used as part of a `let` declaration statement (`let y = ...`).
+
+The second kind of statement in Rust is the **expression statement**. Its
+purpose is to turn any expression into a statement. In practical terms, Rust's
+grammar expects statements to follow other statements. This means that you use
+semicolons to separate expressions from each other. This means that Rust
+looks a lot like most other languages that require you to use semicolons
+at the end of every line, and you will see semicolons at the end of almost
+every line of Rust code you see.
+
+What is this exception that makes us say 'almost?' You saw it already, in this
+code:
+
+```
+let x = 5i;
+
+let y: int = if x == 5i { 10i } else { 15i };
+```
+
+Note that I've added the type annotation to `y`, to specify explicitly that I
+want `y` to be an integer.
+
+This is not the same as this, which won't compile:
+
+```{ignore}
+let x = 5i;
+
+let y: int = if x == 5 { 10i; } else { 15i; };
+```
+
+Note the semicolons after the 10 and 15. Rust will give us the following error:
+
+```{ignore,notrust}
+error: mismatched types: expected `int` but found `()` (expected int but found ())
+```
+
+We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a
+special type in Rust's type system. `()` is different than `null` in other
+languages, because `()` is distinct from other types. For example, in C, `null`
+is a valid value for a variable of type `int`. In Rust, `()` is _not_ a valid
+value for a variable of type `int`. It's only a valid value for variables of
+the type `()`, which aren't very useful. Remember how we said statements don't
+return a value? Well, that's the purpose of unit in this case. The semicolon
+turns any expression into a statement by throwing away its value and returning
+unit instead.
+
+There's one more time in which you won't see a semicolon at the end of a line
+of Rust code. For that, we'll need our next concept: functions.
+
 ## Functions
 
+You've already seen one function so far, the `main` function:
+
+```{rust}
+fn main() {
+}
+```
+
+This is the simplest possible function declaration. As we mentioned before,
+`fn` says 'this is a function,' followed by the name, some parenthesis because
+this function takes no arguments, and then some curly braces to indicate the
+body. Here's a function named `foo`:
+
+```{rust}
+fn foo() {
+}
+```
+
+So, what about taking arguments? Here's a function that prints a number:
+
+```{rust}
+fn print_number(x: int) {
+    println!("x is: {}", x);
+}
+```
+
+Here's a complete program that uses `print_number`:
+
+```{rust}
+fn main() {
+    print_number(5);
+}
+
+fn print_number(x: int) {
+    println!("x is: {}", x);
+}
+```
+
+As you can see, function arguments work very similar to `let` declarations:
+you add a type to the argument name, after a colon.
+
+Here's a complete program that adds two numbers together and prints them:
+
+```{rust}
+fn main() {
+    print_sum(5, 6);
+}
+
+fn print_sum(x: int, y: int) {
+    println!("sum is: {}", x + y);
+}
+```
+
+You separate arguments with a comma, both when you call the function, as well
+as when you declare it.
+
+Unlike `let`, you _must_ declare the types of function arguments. This does
+not work:
+
+```{ignore}
+fn print_number(x, y) {
+    println!("x is: {}", x + y);
+}
+```
+
+You get this error:
+
+```{ignore,notrust}
+hello.rs:5:18: 5:19 error: expected `:` but found `,`
+hello.rs:5 fn print_number(x, y) {
+```
+
+This is a deliberate design decision. While full-program inference is possible,
+languages which have it, like Haskell, often suggest that documenting your
+types explicitly is a best-practice. We agree that forcing functions to declare
+types while allowing for inference inside of function bodies is a wonderful
+compromise between full inference and no inference.
+
+What about returning a value? Here's a function that adds one to an integer:
+
+```{rust}
+fn add_one(x: int) -> int {
+    x + 1
+}
+```
+
+Rust functions return exactly one value, and you declare the type after an
+'arrow', which is a dash (`-`) followed by a greater-than sign (`>`).
+
+You'll note the lack of a semicolon here. If we added it in:
+
+```{ignore}
+fn add_one(x: int) -> int {
+    x + 1;
+}
+```
+
+We would get an error:
+
+```{ignore,notrust}
+note: consider removing this semicolon:
+     x + 1;
+          ^
+error: not all control paths return a value
+fn add_one(x: int) -> int {
+     x + 1;
+}
+```
+
+Remember our earlier discussions about semicolons and `()`? Our function claims
+to return an `int`, but with a semicolon, it would return `()` instead. Rust
+realizes this probably isn't what we want, and suggests removing the semicolon.
+
+This is very much like our `if` statement before: the result of the block
+(`{}`) is the value of the expression. Other expression-oriented languages,
+such as Ruby, work like this, but it's a bit unusual in the systems programming
+world. When people first learn about this, they usually assume that it
+introduces bugs. But because Rust's type system is so strong, and because unit
+is its own unique type, we have never seen an issue where adding or removing a
+semicolon in a return position would cause a bug.
+
+But what about early returns? Rust does have a keyword for that, `return`:
+
+```{rust}
+fn foo(x: int) -> int {
+    if x < 5 { return x; }
+
+    x + 1
+}
+```
+
+Using a `return` as the last line of a function works, but is considered poor
+style:
+
+```{rust}
+fn foo(x: int) -> int {
+    if x < 5 { return x; }
+
+    return x + 1;
+}
+```
+
+There are some additional ways to define functions, but they involve features
+that we haven't learned about yet, so let's just leave it at that for now.
+
+## Comments
+
 return
 
 comments
index b9d585c953c6dfe54a0cfa407020cda50b7b9c0d..3dd770fd976b2829f312912a53cc255f5224a1bc 100644 (file)
@@ -132,6 +132,7 @@ nav {
     -moz-column-count: 2;
     -webkit-column-count: 2;
     font-size: 15px;
+    margin: 0 0 1em 0;
 }
 p {
     margin: 0 0 1em 0;
@@ -275,7 +276,7 @@ dd {
 
 nav ul {
     list-style-type: none;
-    margin: 0 0 20px 0;
+    margin: 0;
     padding-left: 0px;
 }
 
index 58819a3cf48ee2454d9958f85cc7aac28ebb7af1..e149920ab352d9fe9362f64e5208164115387fd3 100644 (file)
@@ -2155,8 +2155,6 @@ These are functions:
 
 * `str_eq`
   : Compare two strings (`&str`) for equality.
-* `uniq_str_eq`
-  : Compare two owned strings (`String`) for equality.
 * `strdup_uniq`
   : Return a new unique string
     containing a copy of the contents of a unique string.
@@ -2541,7 +2539,7 @@ A temporary's lifetime equals the largest lifetime of any reference that points
 #### Moved and copied types
 
 When a [local variable](#memory-slots) is used
-as an [rvalue](#lvalues-rvalues-and-temporaries)
+as an [rvalue](#lvalues,-rvalues-and-temporaries)
 the variable will either be moved or copied, depending on its type.
 For types that contain [owning pointers](#pointer-types)
 or values that implement the special trait `Drop`,
@@ -2564,7 +2562,7 @@ string, boolean value, or the unit value.
 ### Path expressions
 
 A [path](#paths) used as an expression context denotes either a local variable or an item.
-Path expressions are [lvalues](#lvalues-rvalues-and-temporaries).
+Path expressions are [lvalues](#lvalues,-rvalues-and-temporaries).
 
 ### Tuple expressions
 
@@ -2677,7 +2675,7 @@ foo().x;
 (Struct {a: 10, b: 20}).a;
 ~~~~
 
-A field access is an [lvalue](#lvalues-rvalues-and-temporaries) referring to the value of that field.
+A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to the value of that field.
 When the type providing the field inherits mutabilty, it can be [assigned](#assignment-expressions) to.
 
 Also, if the type of the expression to the left of the dot is a pointer,
@@ -2713,7 +2711,7 @@ idx_expr : expr '[' expr ']' ;
 
 [Vector](#vector-types)-typed expressions can be indexed by writing a
 square-bracket-enclosed expression (the index) after them. When the
-vector is mutable, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.
+vector is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can be assigned to.
 
 Indices are zero-based, and may be of any integral type. Vector access
 is bounds-checked at run-time. When the check fails, it will put the
@@ -2739,7 +2737,7 @@ before the expression they apply to.
   : Negation. May only be applied to numeric types.
 * `*`
   : Dereference. When applied to a [pointer](#pointer-types) it denotes the pointed-to location.
-    For pointers to mutable locations, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.
+    For pointers to mutable locations, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can be assigned to.
     On non-pointer types, it calls the `deref` method of the `std::ops::Deref` trait, or the
     `deref_mut` method of the `std::ops::DerefMut` trait (if implemented by the type and required
     for an outer expression that will or could mutate the dereference), and produces the
@@ -2874,8 +2872,8 @@ fn avg(v: &[f64]) -> f64 {
 
 #### Assignment expressions
 
-An _assignment expression_ consists of an [lvalue](#lvalues-rvalues-and-temporaries) expression followed by an
-equals sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression.
+An _assignment expression_ consists of an [lvalue](#lvalues,-rvalues-and-temporaries) expression followed by an
+equals sign (`=`) and an [rvalue](#lvalues,-rvalues-and-temporaries) expression.
 
 Evaluating an assignment expression [either copies or moves](#moved-and-copied-types) its right-hand operand to its left-hand operand.
 
@@ -3188,7 +3186,7 @@ fn main() {
 ~~~~
 
 A `match` behaves differently depending on whether or not the head expression
-is an [lvalue or an rvalue](#lvalues-rvalues-and-temporaries).
+is an [lvalue or an rvalue](#lvalues,-rvalues-and-temporaries).
 If the head expression is an rvalue, it is
 first evaluated into a temporary location, and the resulting value
 is sequentially compared to the patterns in the arms until a match
@@ -3552,7 +3550,7 @@ There are four varieties of pointer in Rust:
   : These point to memory _owned by some other value_.
     References arise by (automatic) conversion from owning pointers, managed pointers,
     or by applying the borrowing operator `&` to some other value,
-    including [lvalues, rvalues or temporaries](#lvalues-rvalues-and-temporaries).
+    including [lvalues, rvalues or temporaries](#lvalues,-rvalues-and-temporaries).
     References are written `&content`, or in some cases `&'f content` for some lifetime-variable `f`,
     for example `&int` means a reference to an integer.
     Copying a reference is a "shallow" operation:
@@ -3854,7 +3852,7 @@ references to any boxes; the remainder of its heap is immediately freed.
 A task's stack contains slots.
 
 A _slot_ is a component of a stack frame, either a function parameter,
-a [temporary](#lvalues-rvalues-and-temporaries), or a local variable.
+a [temporary](#lvalues,-rvalues-and-temporaries), or a local variable.
 
 A _local variable_ (or *stack-local* allocation) holds a value directly,
 allocated within the stack's memory. The value is a part of the stack frame.
index 8199eaea82c683b7cc29489b682e11fa8d9d89db..07a93e58456b94a680378e960193788db994c7b7 100644 (file)
@@ -51,7 +51,7 @@ Calculates the factorial of a number.
 
 Given the input integer `n`, this function will calculate `n!` and return it.
 "]
-pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n)} }
+pub fn factorial(n: int) -> int { if n < 2 {1} else {n * factorial(n - 1)} }
 # fn main() {}
 ~~~
 
index 5fe6a5f14c2b426d55d112a6083dbc0889ddab6e..2a788d7e7934c495d1d6ca218209faa3181c062c 100644 (file)
@@ -469,7 +469,7 @@ fn signum(x: int) -> int {
 
 Rust's `match` construct is a generalized, cleaned-up version of C's
 `switch` construct. You provide it with a value and a number of
-*arms*, each labelled with a pattern, and the code compares the value
+*arms*, each labeled with a pattern, and the code compares the value
 against each pattern in order until one matches. The matching pattern
 executes its corresponding arm.
 
@@ -2524,7 +2524,7 @@ of the components of types. By design, trait objects don't know the exact type
 of their contents and so the compiler cannot reason about those properties.
 
 You can instruct the compiler, however, that the contents of a trait object must
-acribe to a particular bound with a trailing colon (`:`). These are examples of
+ascribe to a particular bound with a trailing colon (`:`). These are examples of
 valid types:
 
 ~~~rust
@@ -2579,7 +2579,7 @@ This is a silly way to compute the radius of a circle
 
 In type-parameterized functions,
 methods of the supertrait may be called on values of subtrait-bound type parameters.
-Refering to the previous example of `trait Circle : Shape`:
+Referring to the previous example of `trait Circle : Shape`:
 
 ~~~
 # trait Shape { fn area(&self) -> f64; }
index dc09c7dfd00da7d3e787904162a7aea07f31c7a0..2ed7a9dd6c28ab246cf857376ec3d33571f6631d 100644 (file)
@@ -35,6 +35,13 @@ need_ok() {
     fi
 }
 
+need_cmd() {
+    if command -v $1 >/dev/null 2>&1
+    then msg "found $1"
+    else err "need $1"
+    fi
+}
+
 putvar() {
     local T
     eval T=\$$1
@@ -198,7 +205,16 @@ absolutify() {
     ABSOLUTIFIED="${FILE_PATH}"
 }
 
-CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
+msg "looking for install programs"
+need_cmd mkdir
+need_cmd printf
+need_cmd cut
+need_cmd grep
+need_cmd uname
+need_cmd tr
+need_cmd sed
+
+CFG_SRC_DIR="$(cd $(dirname $0) && pwd)"
 CFG_SELF="$0"
 CFG_ARGS="$@"
 
@@ -216,16 +232,65 @@ else
     step_msg "processing $CFG_SELF args"
 fi
 
+# Check for mingw or cygwin in order to special case $CFG_LIBDIR_RELATIVE.
+# This logic is duplicated from configure in order to get the correct libdir
+# for Windows installs.
+CFG_OSTYPE=$(uname -s)
+
+case $CFG_OSTYPE in
+
+    MINGW32*)
+        CFG_OSTYPE=pc-mingw32
+        ;;
+
+    MINGW64*)
+        # msys2, MSYSTEM=MINGW64
+        CFG_OSTYPE=w64-mingw32
+        ;;
+
+# Thad's Cygwin identifers below
+
+#   Vista 32 bit
+    CYGWIN_NT-6.0)
+        CFG_OSTYPE=pc-mingw32
+        ;;
+
+#   Vista 64 bit
+    CYGWIN_NT-6.0-WOW64)
+        CFG_OSTYPE=w64-mingw32
+        ;;
+
+#   Win 7 32 bit
+    CYGWIN_NT-6.1)
+        CFG_OSTYPE=pc-mingw32
+        ;;
+
+#   Win 7 64 bit
+    CYGWIN_NT-6.1-WOW64)
+        CFG_OSTYPE=w64-mingw32
+        ;;
+esac
+
 OPTIONS=""
 BOOL_OPTIONS=""
 VAL_OPTIONS=""
 
+# On windows we just store the libraries in the bin directory because
+# there's no rpath. This is where the build system itself puts libraries;
+# --libdir is used to configure the installation directory.
+# FIXME: Thise needs to parameterized over target triples. Do it in platform.mk
+CFG_LIBDIR_RELATIVE=lib
+if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
+then
+    CFG_LIBDIR_RELATIVE=bin
+fi
+
 flag uninstall "only uninstall from the installation prefix"
 opt verify 1 "verify that the installed binaries run correctly"
 valopt prefix "/usr/local" "set installation prefix"
 # NB This isn't quite the same definition as in `configure`.
 # just using 'lib' instead of CFG_LIBDIR_RELATIVE
-valopt libdir "${CFG_PREFIX}/lib" "install libraries"
+valopt libdir "${CFG_PREFIX}/${CFG_LIBDIR_RELATIVE}" "install libraries"
 valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
 
 if [ $HELP -eq 1 ]
@@ -384,7 +449,7 @@ while read p; do
     need_ok "failed to update manifest"
 
 # The manifest lists all files to install
-done < "${CFG_SRC_DIR}/lib/rustlib/manifest.in"
+done < "${CFG_SRC_DIR}/${CFG_LIBDIR_RELATIVE}/rustlib/manifest.in"
 
 # Sanity check: can we run the installed binaries?
 if [ -z "${CFG_DISABLE_VERIFY}" ]
index c0289fc6d83e188778feb0972428294f7d11b1b1..deb713ac1ae01bcc7f057d27d48c5e33a4965762 100644 (file)
@@ -7,7 +7,7 @@
        <!ENTITY rustIdent "[a-zA-Z_][a-zA-Z_0-9]*">
        <!ENTITY rustIntSuf "([iu](8|16|32|64)?)?">
 ]>
-<language name="Rust" version="0.11.0-pre" kateversion="2.4" section="Sources" extensions="*.rs" mimetype="text/x-rust" priority="15">
+<language name="Rust" version="0.11.0" kateversion="2.4" section="Sources" extensions="*.rs" mimetype="text/x-rust" priority="15">
 <highlighting>
        <list name="fn">
                <item> fn </item>
index 38ed511c4589a5004a12b6510fff04bde660d845..9b4f879e61ea4a8474cc172002d31e021b4b6bd6 100644 (file)
@@ -185,7 +185,7 @@ fn drop(&mut self) {
         // deletion of the data. Because it is marked `Release`, the
         // decreasing of the reference count synchronizes with this `Acquire`
         // fence. This means that use of the data happens before decreasing
-        // the refernce count, which happens before this fence, which
+        // the reference count, which happens before this fence, which
         // happens before the deletion of the data.
         //
         // As explained in the [Boost documentation][1],
index 77333b4dc2aee614fb6087692d14758d952358b0..26b8ccaf573718523428bd8f82c76b61be87c3e4 100644 (file)
@@ -60,7 +60,7 @@
 //! by libc malloc/free.  The `libc_heap` module is defined to be wired up to
 //! the system malloc/free.
 
-#![crate_id = "alloc#0.11.0-pre"]
+#![crate_id = "alloc#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
index 152967cb4e90841f2cd83b4e62fe4dda0a8a27f6..917de94470b35e0bf3ceb4f189e464fb747d2310 100644 (file)
 //! arena but can only hold objects of a single type, and Arena, which is a
 //! more complex, slower Arena which can hold objects of any type.
 
-#![crate_id = "arena#0.11.0-pre"]
+#![crate_id = "arena#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![feature(unsafe_destructor)]
 #![allow(missing_doc)]
index c5b8704439850e76ea3154b004a0c707cf7db5bb..c698b35c84811db2176daa87733a8394d99daafd 100644 (file)
  * Collection types.
  */
 
-#![crate_id = "collections#0.11.0-pre"]
+#![crate_id = "collections#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
index fd8ce11d0b5a4bfdfc0256a830edff57445a8229..ddba4b34e3a2a4e8a5664f54b61d95e08ffeb943 100644 (file)
@@ -160,9 +160,27 @@ pub fn from_chars(chs: &[char]) -> String {
 /// Methods for vectors of strings
 pub trait StrVector {
     /// Concatenate a vector of strings.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let first = "Restaurant at the End of the".to_string();
+    /// let second = " Universe".to_string();
+    /// let string_vec = vec![first, second];
+    /// assert_eq!(string_vec.concat(), "Restaurant at the End of the Universe".to_string());
+    /// ```
     fn concat(&self) -> String;
 
     /// Concatenate a vector of strings, placing a given separator between each.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let first = "Roast".to_string();
+    /// let second = "Sirloin Steak".to_string();
+    /// let string_vec = vec![first, second];
+    /// assert_eq!(string_vec.connect(", "), "Roast, Sirloin Steak".to_string());
+    /// ```
     fn connect(&self, sep: &str) -> String;
 }
 
@@ -172,7 +190,7 @@ fn concat(&self) -> String {
             return String::new();
         }
 
-        // `len` calculation may overflow but push_str but will check boundaries
+        // `len` calculation may overflow but push_str will check boundaries
         let len = self.iter().map(|s| s.as_slice().len()).sum();
 
         let mut result = String::with_capacity(len);
index 2ffc168f82c0eef4b4d77244a873ed3cd327d1a6..d53ecabd5a9cb147e5093e7ce172dd91acf1835a 100644 (file)
@@ -253,8 +253,7 @@ pub fn push_all(&mut self, other: &[T]) {
     /// assert_eq!(vec, vec!("hello", "world", "world"));
     /// ```
     pub fn grow(&mut self, n: uint, value: &T) {
-        let new_len = self.len() + n;
-        self.reserve(new_len);
+        self.reserve_additional(n);
         let mut i: uint = 0u;
 
         while i < n {
@@ -497,7 +496,7 @@ pub fn reserve_additional(&mut self, extra: uint) {
     /// assert!(vec.capacity() >= 10);
     /// ```
     pub fn reserve(&mut self, capacity: uint) {
-        if capacity >= self.len {
+        if capacity > self.cap {
             self.reserve_exact(num::next_power_of_two(capacity))
         }
     }
index 385a33fb92a4c67cd02d71ecd26acb5d3813fc96..5e238aeae32711004f1c5bfc6397985d06c63e1d 100644 (file)
 // Since libcore defines many fundamental lang items, all tests live in a
 // separate crate, libcoretest, to avoid bizarre issues.
 
-#![crate_id = "core#0.11.0-pre"]
+#![crate_id = "core#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![no_std]
 pub mod slice;
 pub mod str;
 pub mod tuple;
+// FIXME #15320: primitive documentation needs top-level modules, this
+// should be `core::tuple::unit`.
+#[path = "tuple/unit.rs"]
+pub mod unit;
 pub mod fmt;
 
 #[doc(hidden)]
index b32e4167da1d45e90517b74a4e36b0a55af6791b..1fae362471d9c8f168c77160af8182a871fac88b 100644 (file)
@@ -586,14 +586,14 @@ fn trailing_zeros(self) -> $T { unsafe { $cttz(self) } }
             fn rotate_left(self, n: uint) -> $T {
                 // Protect against undefined behaviour for over-long bit shifts
                 let n = n % $BITS;
-                (self << n) | (self >> ($BITS - n))
+                (self << n) | (self >> (($BITS - n) % $BITS))
             }
 
             #[inline]
             fn rotate_right(self, n: uint) -> $T {
                 // Protect against undefined behaviour for over-long bit shifts
                 let n = n % $BITS;
-                (self >> n) | (self << ($BITS - n))
+                (self >> n) | (self << (($BITS - n) % $BITS))
             }
 
             #[inline]
diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs
deleted file mode 100644 (file)
index 0e37228..0000000
+++ /dev/null
@@ -1,304 +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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Operations on tuples
-//!
-//! To access a single element of a tuple one can use the following
-//! methods:
-//!
-//! * `valN` - returns a value of _N_-th element
-//! * `refN` - returns a reference to _N_-th element
-//! * `mutN` - returns a mutable reference to _N_-th element
-//!
-//! Indexing starts from zero, so `val0` returns first value, `val1`
-//! returns second value, and so on. In general, a tuple with _S_
-//! elements provides aforementioned methods suffixed with numbers
-//! from `0` to `S-1`. Traits which contain these methods are
-//! implemented for tuples with up to 12 elements.
-//!
-//! If every type inside a tuple implements one of the following
-//! traits, then a tuple itself also implements it.
-//!
-//! * `Clone`
-//! * `PartialEq`
-//! * `Eq`
-//! * `PartialOrd`
-//! * `Ord`
-//! * `Default`
-//!
-//! # Examples
-//!
-//! Using methods:
-//!
-//! ```
-//! let pair = ("pi", 3.14f64);
-//! assert_eq!(pair.val0(), "pi");
-//! assert_eq!(pair.val1(), 3.14f64);
-//! ```
-//!
-//! Using traits implemented for tuples:
-//!
-//! ```
-//! use std::default::Default;
-//!
-//! let a = (1i, 2i);
-//! let b = (3i, 4i);
-//! assert!(a != b);
-//!
-//! let c = b.clone();
-//! assert!(b == c);
-//!
-//! let d : (u32, f32) = Default::default();
-//! assert_eq!(d, (0u32, 0.0f32));
-//! ```
-
-#![doc(primitive = "tuple")]
-
-use clone::Clone;
-use cmp::*;
-use default::Default;
-use option::{Option, Some};
-
-// macro for implementing n-ary tuple functions and operations
-macro_rules! tuple_impls {
-    ($(
-        $Tuple:ident {
-            $(($valN:ident, $refN:ident, $mutN:ident) -> $T:ident {
-                ($($x:ident),+) => $ret:expr
-            })+
-        }
-    )+) => {
-        $(
-            #[allow(missing_doc)]
-            pub trait $Tuple<$($T),+> {
-                $(fn $valN(self) -> $T;)+
-                $(fn $refN<'a>(&'a self) -> &'a $T;)+
-                $(fn $mutN<'a>(&'a mut self) -> &'a mut $T;)+
-            }
-
-            impl<$($T),+> $Tuple<$($T),+> for ($($T,)+) {
-                $(
-                    #[inline]
-                    #[allow(unused_variable)]
-                    fn $valN(self) -> $T {
-                        let ($($x,)+) = self; $ret
-                    }
-
-                    #[inline]
-                    #[allow(unused_variable)]
-                    fn $refN<'a>(&'a self) -> &'a $T {
-                        let ($(ref $x,)+) = *self; $ret
-                    }
-
-                    #[inline]
-                    #[allow(unused_variable)]
-                    fn $mutN<'a>(&'a mut self) -> &'a mut $T {
-                        let ($(ref mut $x,)+) = *self; $ret
-                    }
-                )+
-            }
-
-            #[unstable]
-            impl<$($T:Clone),+> Clone for ($($T,)+) {
-                fn clone(&self) -> ($($T,)+) {
-                    ($(self.$refN().clone(),)+)
-                }
-            }
-
-            impl<$($T:PartialEq),+> PartialEq for ($($T,)+) {
-                #[inline]
-                fn eq(&self, other: &($($T,)+)) -> bool {
-                    $(*self.$refN() == *other.$refN())&&+
-                }
-                #[inline]
-                fn ne(&self, other: &($($T,)+)) -> bool {
-                    $(*self.$refN() != *other.$refN())||+
-                }
-            }
-
-            impl<$($T:Eq),+> Eq for ($($T,)+) {}
-
-            impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
-                #[inline]
-                fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
-                    lexical_partial_cmp!($(self.$refN(), other.$refN()),+)
-                }
-                #[inline]
-                fn lt(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(lt, $(self.$refN(), other.$refN()),+)
-                }
-                #[inline]
-                fn le(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(le, $(self.$refN(), other.$refN()),+)
-                }
-                #[inline]
-                fn ge(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(ge, $(self.$refN(), other.$refN()),+)
-                }
-                #[inline]
-                fn gt(&self, other: &($($T,)+)) -> bool {
-                    lexical_ord!(gt, $(self.$refN(), other.$refN()),+)
-                }
-            }
-
-            impl<$($T:Ord),+> Ord for ($($T,)+) {
-                #[inline]
-                fn cmp(&self, other: &($($T,)+)) -> Ordering {
-                    lexical_cmp!($(self.$refN(), other.$refN()),+)
-                }
-            }
-
-            impl<$($T:Default),+> Default for ($($T,)+) {
-                #[inline]
-                fn default() -> ($($T,)+) {
-                    ($({ let x: $T = Default::default(); x},)+)
-                }
-            }
-        )+
-    }
-}
-
-// Constructs an expression that performs a lexical ordering using method $rel.
-// The values are interleaved, so the macro invocation for
-// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
-// a3, b3)` (and similarly for `lexical_cmp`)
-macro_rules! lexical_ord {
-    ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
-        if *$a != *$b { lexical_ord!($rel, $a, $b) }
-        else { lexical_ord!($rel, $($rest_a, $rest_b),+) }
-    };
-    ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) };
-}
-
-macro_rules! lexical_partial_cmp {
-    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
-        match ($a).partial_cmp($b) {
-            Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+),
-            ordering   => ordering
-        }
-    };
-    ($a:expr, $b:expr) => { ($a).partial_cmp($b) };
-}
-
-macro_rules! lexical_cmp {
-    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
-        match ($a).cmp($b) {
-            Equal => lexical_cmp!($($rest_a, $rest_b),+),
-            ordering   => ordering
-        }
-    };
-    ($a:expr, $b:expr) => { ($a).cmp($b) };
-}
-
-tuple_impls! {
-    Tuple1 {
-        (val0, ref0, mut0) -> A { (a) => a }
-    }
-    Tuple2 {
-        (val0, ref0, mut0) -> A { (a, b) => a }
-        (val1, ref1, mut1) -> B { (a, b) => b }
-    }
-    Tuple3 {
-        (val0, ref0, mut0) -> A { (a, b, c) => a }
-        (val1, ref1, mut1) -> B { (a, b, c) => b }
-        (val2, ref2, mut2) -> C { (a, b, c) => c }
-    }
-    Tuple4 {
-        (val0, ref0, mut0) -> A { (a, b, c, d) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d) => d }
-    }
-    Tuple5 {
-        (val0, ref0, mut0) -> A { (a, b, c, d, e) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d, e) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d, e) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d, e) => d }
-        (val4, ref4, mut4) -> E { (a, b, c, d, e) => e }
-    }
-    Tuple6 {
-        (val0, ref0, mut0) -> A { (a, b, c, d, e, f) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d, e, f) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d, e, f) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d, e, f) => d }
-        (val4, ref4, mut4) -> E { (a, b, c, d, e, f) => e }
-        (val5, ref5, mut5) -> F { (a, b, c, d, e, f) => f }
-    }
-    Tuple7 {
-        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g) => d }
-        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g) => e }
-        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g) => f }
-        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g) => g }
-    }
-    Tuple8 {
-        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h) => d }
-        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h) => e }
-        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h) => f }
-        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h) => g }
-        (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h) => h }
-    }
-    Tuple9 {
-        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i) => d }
-        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i) => e }
-        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i) => f }
-        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i) => g }
-        (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i) => h }
-        (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i) => i }
-    }
-    Tuple10 {
-        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j) => a }
-        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j) => b }
-        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j) => c }
-        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j) => d }
-        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j) => e }
-        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j) => f }
-        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j) => g }
-        (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j) => h }
-        (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j) => i }
-        (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j) => j }
-    }
-    Tuple11 {
-        (val0,  ref0,  mut0)  -> A { (a, b, c, d, e, f, g, h, i, j, k) => a }
-        (val1,  ref1,  mut1)  -> B { (a, b, c, d, e, f, g, h, i, j, k) => b }
-        (val2,  ref2,  mut2)  -> C { (a, b, c, d, e, f, g, h, i, j, k) => c }
-        (val3,  ref3,  mut3)  -> D { (a, b, c, d, e, f, g, h, i, j, k) => d }
-        (val4,  ref4,  mut4)  -> E { (a, b, c, d, e, f, g, h, i, j, k) => e }
-        (val5,  ref5,  mut5)  -> F { (a, b, c, d, e, f, g, h, i, j, k) => f }
-        (val6,  ref6,  mut6)  -> G { (a, b, c, d, e, f, g, h, i, j, k) => g }
-        (val7,  ref7,  mut7)  -> H { (a, b, c, d, e, f, g, h, i, j, k) => h }
-        (val8,  ref8,  mut8)  -> I { (a, b, c, d, e, f, g, h, i, j, k) => i }
-        (val9,  ref9,  mut9)  -> J { (a, b, c, d, e, f, g, h, i, j, k) => j }
-        (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k) => k }
-    }
-    Tuple12 {
-        (val0,  ref0,  mut0)  -> A { (a, b, c, d, e, f, g, h, i, j, k, l) => a }
-        (val1,  ref1,  mut1)  -> B { (a, b, c, d, e, f, g, h, i, j, k, l) => b }
-        (val2,  ref2,  mut2)  -> C { (a, b, c, d, e, f, g, h, i, j, k, l) => c }
-        (val3,  ref3,  mut3)  -> D { (a, b, c, d, e, f, g, h, i, j, k, l) => d }
-        (val4,  ref4,  mut4)  -> E { (a, b, c, d, e, f, g, h, i, j, k, l) => e }
-        (val5,  ref5,  mut5)  -> F { (a, b, c, d, e, f, g, h, i, j, k, l) => f }
-        (val6,  ref6,  mut6)  -> G { (a, b, c, d, e, f, g, h, i, j, k, l) => g }
-        (val7,  ref7,  mut7)  -> H { (a, b, c, d, e, f, g, h, i, j, k, l) => h }
-        (val8,  ref8,  mut8)  -> I { (a, b, c, d, e, f, g, h, i, j, k, l) => i }
-        (val9,  ref9,  mut9)  -> J { (a, b, c, d, e, f, g, h, i, j, k, l) => j }
-        (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k, l) => k }
-        (val11, ref11, mut11) -> L { (a, b, c, d, e, f, g, h, i, j, k, l) => l }
-    }
-}
-
diff --git a/src/libcore/tuple/mod.rs b/src/libcore/tuple/mod.rs
new file mode 100644 (file)
index 0000000..4f34c64
--- /dev/null
@@ -0,0 +1,306 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations on tuples
+//!
+//! To access a single element of a tuple one can use the following
+//! methods:
+//!
+//! * `valN` - returns a value of _N_-th element
+//! * `refN` - returns a reference to _N_-th element
+//! * `mutN` - returns a mutable reference to _N_-th element
+//!
+//! Indexing starts from zero, so `val0` returns first value, `val1`
+//! returns second value, and so on. In general, a tuple with _S_
+//! elements provides aforementioned methods suffixed with numbers
+//! from `0` to `S-1`. Traits which contain these methods are
+//! implemented for tuples with up to 12 elements.
+//!
+//! If every type inside a tuple implements one of the following
+//! traits, then a tuple itself also implements it.
+//!
+//! * `Clone`
+//! * `PartialEq`
+//! * `Eq`
+//! * `PartialOrd`
+//! * `Ord`
+//! * `Default`
+//!
+//! # Examples
+//!
+//! Using methods:
+//!
+//! ```
+//! let pair = ("pi", 3.14f64);
+//! assert_eq!(pair.val0(), "pi");
+//! assert_eq!(pair.val1(), 3.14f64);
+//! ```
+//!
+//! Using traits implemented for tuples:
+//!
+//! ```
+//! use std::default::Default;
+//!
+//! let a = (1i, 2i);
+//! let b = (3i, 4i);
+//! assert!(a != b);
+//!
+//! let c = b.clone();
+//! assert!(b == c);
+//!
+//! let d : (u32, f32) = Default::default();
+//! assert_eq!(d, (0u32, 0.0f32));
+//! ```
+
+#![doc(primitive = "tuple")]
+
+pub use unit;
+
+use clone::Clone;
+use cmp::*;
+use default::Default;
+use option::{Option, Some};
+
+// macro for implementing n-ary tuple functions and operations
+macro_rules! tuple_impls {
+    ($(
+        $Tuple:ident {
+            $(($valN:ident, $refN:ident, $mutN:ident) -> $T:ident {
+                ($($x:ident),+) => $ret:expr
+            })+
+        }
+    )+) => {
+        $(
+            #[allow(missing_doc)]
+            pub trait $Tuple<$($T),+> {
+                $(fn $valN(self) -> $T;)+
+                $(fn $refN<'a>(&'a self) -> &'a $T;)+
+                $(fn $mutN<'a>(&'a mut self) -> &'a mut $T;)+
+            }
+
+            impl<$($T),+> $Tuple<$($T),+> for ($($T,)+) {
+                $(
+                    #[inline]
+                    #[allow(unused_variable)]
+                    fn $valN(self) -> $T {
+                        let ($($x,)+) = self; $ret
+                    }
+
+                    #[inline]
+                    #[allow(unused_variable)]
+                    fn $refN<'a>(&'a self) -> &'a $T {
+                        let ($(ref $x,)+) = *self; $ret
+                    }
+
+                    #[inline]
+                    #[allow(unused_variable)]
+                    fn $mutN<'a>(&'a mut self) -> &'a mut $T {
+                        let ($(ref mut $x,)+) = *self; $ret
+                    }
+                )+
+            }
+
+            #[unstable]
+            impl<$($T:Clone),+> Clone for ($($T,)+) {
+                fn clone(&self) -> ($($T,)+) {
+                    ($(self.$refN().clone(),)+)
+                }
+            }
+
+            impl<$($T:PartialEq),+> PartialEq for ($($T,)+) {
+                #[inline]
+                fn eq(&self, other: &($($T,)+)) -> bool {
+                    $(*self.$refN() == *other.$refN())&&+
+                }
+                #[inline]
+                fn ne(&self, other: &($($T,)+)) -> bool {
+                    $(*self.$refN() != *other.$refN())||+
+                }
+            }
+
+            impl<$($T:Eq),+> Eq for ($($T,)+) {}
+
+            impl<$($T:PartialOrd + PartialEq),+> PartialOrd for ($($T,)+) {
+                #[inline]
+                fn partial_cmp(&self, other: &($($T,)+)) -> Option<Ordering> {
+                    lexical_partial_cmp!($(self.$refN(), other.$refN()),+)
+                }
+                #[inline]
+                fn lt(&self, other: &($($T,)+)) -> bool {
+                    lexical_ord!(lt, $(self.$refN(), other.$refN()),+)
+                }
+                #[inline]
+                fn le(&self, other: &($($T,)+)) -> bool {
+                    lexical_ord!(le, $(self.$refN(), other.$refN()),+)
+                }
+                #[inline]
+                fn ge(&self, other: &($($T,)+)) -> bool {
+                    lexical_ord!(ge, $(self.$refN(), other.$refN()),+)
+                }
+                #[inline]
+                fn gt(&self, other: &($($T,)+)) -> bool {
+                    lexical_ord!(gt, $(self.$refN(), other.$refN()),+)
+                }
+            }
+
+            impl<$($T:Ord),+> Ord for ($($T,)+) {
+                #[inline]
+                fn cmp(&self, other: &($($T,)+)) -> Ordering {
+                    lexical_cmp!($(self.$refN(), other.$refN()),+)
+                }
+            }
+
+            impl<$($T:Default),+> Default for ($($T,)+) {
+                #[inline]
+                fn default() -> ($($T,)+) {
+                    ($({ let x: $T = Default::default(); x},)+)
+                }
+            }
+        )+
+    }
+}
+
+// Constructs an expression that performs a lexical ordering using method $rel.
+// The values are interleaved, so the macro invocation for
+// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_ord!(lt, a1, b1, a2, b2,
+// a3, b3)` (and similarly for `lexical_cmp`)
+macro_rules! lexical_ord {
+    ($rel: ident, $a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
+        if *$a != *$b { lexical_ord!($rel, $a, $b) }
+        else { lexical_ord!($rel, $($rest_a, $rest_b),+) }
+    };
+    ($rel: ident, $a:expr, $b:expr) => { (*$a) . $rel ($b) };
+}
+
+macro_rules! lexical_partial_cmp {
+    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
+        match ($a).partial_cmp($b) {
+            Some(Equal) => lexical_partial_cmp!($($rest_a, $rest_b),+),
+            ordering   => ordering
+        }
+    };
+    ($a:expr, $b:expr) => { ($a).partial_cmp($b) };
+}
+
+macro_rules! lexical_cmp {
+    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
+        match ($a).cmp($b) {
+            Equal => lexical_cmp!($($rest_a, $rest_b),+),
+            ordering   => ordering
+        }
+    };
+    ($a:expr, $b:expr) => { ($a).cmp($b) };
+}
+
+tuple_impls! {
+    Tuple1 {
+        (val0, ref0, mut0) -> A { (a) => a }
+    }
+    Tuple2 {
+        (val0, ref0, mut0) -> A { (a, b) => a }
+        (val1, ref1, mut1) -> B { (a, b) => b }
+    }
+    Tuple3 {
+        (val0, ref0, mut0) -> A { (a, b, c) => a }
+        (val1, ref1, mut1) -> B { (a, b, c) => b }
+        (val2, ref2, mut2) -> C { (a, b, c) => c }
+    }
+    Tuple4 {
+        (val0, ref0, mut0) -> A { (a, b, c, d) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d) => d }
+    }
+    Tuple5 {
+        (val0, ref0, mut0) -> A { (a, b, c, d, e) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d, e) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d, e) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d, e) => d }
+        (val4, ref4, mut4) -> E { (a, b, c, d, e) => e }
+    }
+    Tuple6 {
+        (val0, ref0, mut0) -> A { (a, b, c, d, e, f) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d, e, f) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d, e, f) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d, e, f) => d }
+        (val4, ref4, mut4) -> E { (a, b, c, d, e, f) => e }
+        (val5, ref5, mut5) -> F { (a, b, c, d, e, f) => f }
+    }
+    Tuple7 {
+        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g) => d }
+        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g) => e }
+        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g) => f }
+        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g) => g }
+    }
+    Tuple8 {
+        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h) => d }
+        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h) => e }
+        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h) => f }
+        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h) => g }
+        (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h) => h }
+    }
+    Tuple9 {
+        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i) => d }
+        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i) => e }
+        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i) => f }
+        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i) => g }
+        (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i) => h }
+        (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i) => i }
+    }
+    Tuple10 {
+        (val0, ref0, mut0) -> A { (a, b, c, d, e, f, g, h, i, j) => a }
+        (val1, ref1, mut1) -> B { (a, b, c, d, e, f, g, h, i, j) => b }
+        (val2, ref2, mut2) -> C { (a, b, c, d, e, f, g, h, i, j) => c }
+        (val3, ref3, mut3) -> D { (a, b, c, d, e, f, g, h, i, j) => d }
+        (val4, ref4, mut4) -> E { (a, b, c, d, e, f, g, h, i, j) => e }
+        (val5, ref5, mut5) -> F { (a, b, c, d, e, f, g, h, i, j) => f }
+        (val6, ref6, mut6) -> G { (a, b, c, d, e, f, g, h, i, j) => g }
+        (val7, ref7, mut7) -> H { (a, b, c, d, e, f, g, h, i, j) => h }
+        (val8, ref8, mut8) -> I { (a, b, c, d, e, f, g, h, i, j) => i }
+        (val9, ref9, mut9) -> J { (a, b, c, d, e, f, g, h, i, j) => j }
+    }
+    Tuple11 {
+        (val0,  ref0,  mut0)  -> A { (a, b, c, d, e, f, g, h, i, j, k) => a }
+        (val1,  ref1,  mut1)  -> B { (a, b, c, d, e, f, g, h, i, j, k) => b }
+        (val2,  ref2,  mut2)  -> C { (a, b, c, d, e, f, g, h, i, j, k) => c }
+        (val3,  ref3,  mut3)  -> D { (a, b, c, d, e, f, g, h, i, j, k) => d }
+        (val4,  ref4,  mut4)  -> E { (a, b, c, d, e, f, g, h, i, j, k) => e }
+        (val5,  ref5,  mut5)  -> F { (a, b, c, d, e, f, g, h, i, j, k) => f }
+        (val6,  ref6,  mut6)  -> G { (a, b, c, d, e, f, g, h, i, j, k) => g }
+        (val7,  ref7,  mut7)  -> H { (a, b, c, d, e, f, g, h, i, j, k) => h }
+        (val8,  ref8,  mut8)  -> I { (a, b, c, d, e, f, g, h, i, j, k) => i }
+        (val9,  ref9,  mut9)  -> J { (a, b, c, d, e, f, g, h, i, j, k) => j }
+        (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k) => k }
+    }
+    Tuple12 {
+        (val0,  ref0,  mut0)  -> A { (a, b, c, d, e, f, g, h, i, j, k, l) => a }
+        (val1,  ref1,  mut1)  -> B { (a, b, c, d, e, f, g, h, i, j, k, l) => b }
+        (val2,  ref2,  mut2)  -> C { (a, b, c, d, e, f, g, h, i, j, k, l) => c }
+        (val3,  ref3,  mut3)  -> D { (a, b, c, d, e, f, g, h, i, j, k, l) => d }
+        (val4,  ref4,  mut4)  -> E { (a, b, c, d, e, f, g, h, i, j, k, l) => e }
+        (val5,  ref5,  mut5)  -> F { (a, b, c, d, e, f, g, h, i, j, k, l) => f }
+        (val6,  ref6,  mut6)  -> G { (a, b, c, d, e, f, g, h, i, j, k, l) => g }
+        (val7,  ref7,  mut7)  -> H { (a, b, c, d, e, f, g, h, i, j, k, l) => h }
+        (val8,  ref8,  mut8)  -> I { (a, b, c, d, e, f, g, h, i, j, k, l) => i }
+        (val9,  ref9,  mut9)  -> J { (a, b, c, d, e, f, g, h, i, j, k, l) => j }
+        (val10, ref10, mut10) -> K { (a, b, c, d, e, f, g, h, i, j, k, l) => k }
+        (val11, ref11, mut11) -> L { (a, b, c, d, e, f, g, h, i, j, k, l) => l }
+    }
+}
+
diff --git a/src/libcore/tuple/unit.rs b/src/libcore/tuple/unit.rs
new file mode 100644 (file)
index 0000000..a60b3d0
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![doc(primitive = "unit")]
+
+//! The `()` type, sometimes called "unit" or "nil".
+//!
+//! The `()` type has exactly one value `()`, and is used when there
+//! is no other meaningful value that could be returned. `()` is most
+//! commonly seen implicitly: functions without a `-> ...` implicitly
+//! have return type `()`, that is, these are equivalent:
+//!
+//! ```rust
+//! fn long() -> () {}
+//!
+//! fn short() {}
+//! ```
+//!
+//! The semicolon `;` can be used to discard the result of an
+//! expression at the end of a block, making the expression (and thus
+//! the block) evaluate to `()`. For example,
+//!
+//! ```rust
+//! fn returns_i64() -> i64 {
+//!     1i64
+//! }
+//! fn returns_unit() {
+//!     1i64;
+//! }
+//!
+//! let is_i64 = {
+//!     returns_i64()
+//! };
+//! let is_unit = {
+//!     returns_i64();
+//! };
+//! ```
index 940b036ca907be036b4a7003ba70186d79c66738..d078b51408512fa5e0d13b572a4da0bee79b4c00 100644 (file)
@@ -114,6 +114,15 @@ fn test_rotate() {
         assert_eq!(_1.rotate_left(124), _1);
         assert_eq!(_0.rotate_right(124), _0);
         assert_eq!(_1.rotate_right(124), _1);
+
+        // Rotating by 0 should have no effect
+        assert_eq!(A.rotate_left(0), A);
+        assert_eq!(B.rotate_left(0), B);
+        assert_eq!(C.rotate_left(0), C);
+        // Rotating by a multiple of word size should also have no effect
+        assert_eq!(A.rotate_left(64), A);
+        assert_eq!(B.rotate_left(64), B);
+        assert_eq!(C.rotate_left(64), C);
     }
 
     #[test]
index 2272af67daf8580b7303aeb1f84d4a341ba70a5a..aefaa90520e798a339d35ef7d15adfad12c0f8ff 100644 (file)
@@ -74,6 +74,15 @@ fn test_rotate() {
         assert_eq!(_1.rotate_left(124), _1);
         assert_eq!(_0.rotate_right(124), _0);
         assert_eq!(_1.rotate_right(124), _1);
+
+        // Rotating by 0 should have no effect
+        assert_eq!(A.rotate_left(0), A);
+        assert_eq!(B.rotate_left(0), B);
+        assert_eq!(C.rotate_left(0), C);
+        // Rotating by a multiple of word size should also have no effect
+        assert_eq!(A.rotate_left(64), A);
+        assert_eq!(B.rotate_left(64), B);
+        assert_eq!(C.rotate_left(64), C);
     }
 
     #[test]
index b5afb3381ada92c3219c55c704c2f828ea4e9776..850002b595e91a0031981e494e4be42cc9cef124 100644 (file)
 //! Additionally, it is not guaranteed that functionality such as reflection
 //! will persist into the future.
 
-#![crate_id = "debug#0.11.0-pre"]
+#![crate_id = "debug#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 #![experimental]
 #![feature(managed_boxes, macro_rules)]
 #![allow(experimental)]
index 06f574f4c88a3a4b275620847e6f4e58e691ae3b..d944818abc56ad3a4054aa87590448e4d4c1a9b5 100644 (file)
 
 */
 
-#![crate_id = "flate#0.11.0-pre"]
+#![crate_id = "flate#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 #![feature(phase)]
 
 #[cfg(test)] #[phase(plugin, link)] extern crate log;
index 90023ab0fc5051014e0fbe6c3b30dcce97ed8b03..b9c0fcce52da7c3e162412c0292392d358c59a24 100644 (file)
@@ -14,7 +14,7 @@
 //! Parsing does not happen at runtime: structures of `std::fmt::rt` are
 //! generated instead.
 
-#![crate_id = "fmt_macros#0.11.0-pre"]
+#![crate_id = "fmt_macros#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
index a5880f3247242eb0c5ffefe54a5dfdcd4e8a2aad..e854cd3069c8a78d0ff031cfe203a4bd9977eae5 100644 (file)
@@ -39,14 +39,14 @@ fn main() {
 
 */
 
-#![crate_id = "fourcc#0.11.0-pre"]
+#![crate_id = "fourcc#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![feature(plugin_registrar, managed_boxes)]
 
@@ -59,7 +59,6 @@ fn main() {
 use syntax::ext::base;
 use syntax::ext::base::{ExtCtxt, MacExpr};
 use syntax::ext::build::AstBuilder;
-use syntax::parse;
 use syntax::parse::token;
 use syntax::parse::token::InternedString;
 use rustc::plugin::Registry;
@@ -135,11 +134,7 @@ struct Ident {
 
 fn parse_tts(cx: &ExtCtxt,
              tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
-    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
-                                            cx.cfg(),
-                                            tts.iter()
-                                               .map(|x| (*x).clone())
-                                               .collect());
+    let p = &mut cx.new_parser_from_tts(tts);
     let ex = p.parse_expr();
     let id = if p.token == token::EOF {
         None
index 0e525bc46e7c8b124226b32c65210d6ed3f4afca..00e6df9ffbbb2eab49343ac77ca144970fe07e07 100644 (file)
 //! }
 //! ~~~
 
-#![crate_id = "getopts#0.11.0-pre"]
+#![crate_id = "getopts#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(globs, phase)]
 #![deny(missing_doc)]
index f80208c4743f7c74003029796dd12f8c10e81d7e..3cb21601e331d8f2f9d73022ecd076c4fde92bae 100644 (file)
  * `glob`/`fnmatch` functions.
  */
 
-#![crate_id = "glob#0.11.0-pre"]
+#![crate_id = "glob#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 use std::cell::Cell;
index 13342633f4c232b082b67705c18e1229eee0bcfc..16298f51ea96b283a562537069a5ae98476f483b 100644 (file)
@@ -266,14 +266,14 @@ pub fn main() {
 
 */
 
-#![crate_id = "graphviz#0.11.0-pre"]
+#![crate_id = "graphviz#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![experimental]
 
index e803c75ca5a725b03a2524fd8d1b91734c8f7e4f..1b34679b0a18a67a0857d39ee3ce5aaf68c23f0c 100644 (file)
 //! pool.shutdown();
 //! ```
 
-#![crate_id = "green#0.11.0-pre"]
+#![crate_id = "green#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 // NB this does *not* include globs, please keep it that way.
index c4885edb7d3a776f63cb3df282c6c65f6ed36a13..5faa9cfe6f6a2bd0cbbb0c7d80cf95754de2331f 100644 (file)
@@ -124,7 +124,7 @@ fn drop(&mut self) {
 }
 
 pub struct StackPool {
-    // Ideally this would be some datastructure that preserved ordering on
+    // Ideally this would be some data structure that preserved ordering on
     // Stack.min_size.
     stacks: Vec<Stack>,
 }
index 1b43f236e69b554b9ba877f98c393d1b617415f0..64538bd2212a47e8d7562c7faa619036927172de 100644 (file)
@@ -36,14 +36,14 @@ fn main() {
 
 */
 
-#![crate_id = "hexfloat#0.11.0-pre"]
+#![crate_id = "hexfloat#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 #![feature(plugin_registrar, managed_boxes)]
 
 extern crate syntax;
@@ -54,7 +54,6 @@ fn main() {
 use syntax::ext::base;
 use syntax::ext::base::{ExtCtxt, MacExpr};
 use syntax::ext::build::AstBuilder;
-use syntax::parse;
 use syntax::parse::token;
 use rustc::plugin::Registry;
 
@@ -167,11 +166,7 @@ struct Ident {
 
 fn parse_tts(cx: &ExtCtxt,
              tts: &[ast::TokenTree]) -> (Gc<ast::Expr>, Option<Ident>) {
-    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
-                                            cx.cfg(),
-                                            tts.iter()
-                                               .map(|x| (*x).clone())
-                                               .collect());
+    let p = &mut cx.new_parser_from_tts(tts);
     let ex = p.parse_expr();
     let id = if p.token == token::EOF {
         None
index 3f7f0437baee4378592fa5b3edc1c0b806adab22..81e50889952ec2671e931604c50654d03e2dd996 100644 (file)
@@ -9,11 +9,15 @@
 // except according to those terms.
 
 #![feature(globs)]
-#![crate_id = "libc#0.11.0-pre"]
+#![crate_id = "libc#0.11.0"]
 #![experimental]
 #![no_std] // we don't need std, and we can't have std, since it doesn't exist
            // yet. std depends on us.
 #![crate_type = "rlib"]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
+       html_playground_url = "http://play.rust-lang.org/")]
 
 /*!
 * Bindings for the C standard library and other platform libraries
index ba102a85c1bcb16b6cd3d533274372ba01201302..6216e79fe841878f0ae73347f98c29609dcb8e1e 100644 (file)
@@ -105,14 +105,14 @@ fn main() {
 
 */
 
-#![crate_id = "log#0.11.0-pre"]
+#![crate_id = "log#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules)]
@@ -288,7 +288,7 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
     unsafe { INIT.doit(init); }
 
     // It's possible for many threads are in this function, only one of them
-    // will peform the global initialization, but all of them will need to check
+    // will perform the global initialization, but all of them will need to check
     // again to whether they should really be here or not. Hence, despite this
     // check being expanded manually in the logging macro, this function checks
     // the log level again.
index dfc2c55cde7cb511bb79303ed6942d7b69f1572f..f052826d303861f8b24b60d3f83380ef839c91d6 100644 (file)
@@ -877,7 +877,7 @@ pub fn write<T>(fd: sock_t,
             }
 
             // Also as with read(), we use MSG_DONTWAIT to guard ourselves
-            // against unforseen circumstances.
+            // against unforeseen circumstances.
             let _guard = lock();
             let ptr = buf.slice_from(written).as_ptr();
             let len = buf.len() - written;
index da713e3f2a931e9394a02f90b5bd3061175d2601..e5e8cdeffd7e4c2249b44d5a7f1db0fa2fee47f7 100644 (file)
@@ -376,7 +376,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         if ret != 0 { return Ok(bytes_read as uint) }
 
         // If our errno doesn't say that the I/O is pending, then we hit some
-        // legitimate error and reeturn immediately.
+        // legitimate error and return immediately.
         if os::errno() != libc::ERROR_IO_PENDING as uint {
             return Err(super::last_error())
         }
index 8d6563bafad6365c3ed287bda8a31b81731a3918..87c320e0457cbfe2f3e270e57592ed8306eb0bd9 100644 (file)
@@ -93,20 +93,7 @@ pub fn now() -> u64 {
     }
 }
 
-
-// Note: although the last parameter isn't used there is no way now to
-// convert it to unit type, because LLVM dies in SjLj preparation
-// step (unfortunately iOS uses SjLJ exceptions)
-//
-// It's definitely a temporary workaround just to get it working.
-// So far it looks like an LLVM issue and it was reported:
-// http://llvm.org/bugs/show_bug.cgi?id=19855
-// Actually this issue is pretty common while compiling for armv7 iOS
-// and in most cases it is simply solved by using --opt-level=2 (or -O)
-//
-// For this specific case unfortunately turning optimizations wasn't
-// enough.
-fn helper(input: libc::c_int, messages: Receiver<Req>, _: int) {
+fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
     let mut set: c::fd_set = unsafe { mem::zeroed() };
 
     let mut fd = FileDesc::new(input, true);
@@ -218,7 +205,7 @@ impl Timer {
     pub fn new() -> IoResult<Timer> {
         // See notes above regarding using int return value
         // instead of ()
-        unsafe { HELPER.boot(|| {0}, helper); }
+        unsafe { HELPER.boot(|| {}, helper); }
 
         static mut ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
         let id = unsafe { ID.fetch_add(1, atomics::Relaxed) };
index b6a4b08c60cafdfc7abba70ca2cf9f970cf53bef..2e43ddba6449ce08bb956b2c14711911472775b5 100644 (file)
 //! }
 //! ```
 
-#![crate_id = "native#0.11.0-pre"]
+#![crate_id = "native#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![deny(unused_result, unused_must_use)]
 #![allow(non_camel_case_types, deprecated)]
index 1e82da5ef8de47c2902ec11d83a04ae4ef943162..db0cd7f2567243b006d36a0508bdd8cb55b601e0 100644 (file)
 
 #![feature(macro_rules)]
 
-#![crate_id = "num#0.11.0-pre"]
+#![crate_id = "num#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![allow(deprecated)] // from_str_radix
index 9a455edf2c086e8d034b5c178847fda15b556ae5..c35b2976b407f19aef7f9614c48d2f3fc19e4bd7 100644 (file)
@@ -274,12 +274,17 @@ impl<T: Clone + Integer + PartialOrd>
     Num for Ratio<T> {}
 
 /* String conversions */
-impl<T: fmt::Show> fmt::Show for Ratio<T> {
-    /// Renders as `numer/denom`.
+impl<T: fmt::Show + Eq + One> fmt::Show for Ratio<T> {
+    /// Renders as `numer/denom`. If denom=1, renders as numer.
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}/{}", self.numer, self.denom)
+        if self.denom == One::one() {
+            write!(f, "{}", self.numer)
+        } else {
+            write!(f, "{}/{}", self.numer, self.denom)
+        }
     }
 }
+
 impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
     /// Renders as `numer/denom` where the numbers are in base `radix`.
     fn to_str_radix(&self, radix: uint) -> String {
@@ -291,21 +296,20 @@ fn to_str_radix(&self, radix: uint) -> String {
 
 impl<T: FromStr + Clone + Integer + PartialOrd>
     FromStr for Ratio<T> {
-    /// Parses `numer/denom`.
+    /// Parses `numer/denom` or just `numer`
     fn from_str(s: &str) -> Option<Ratio<T>> {
-        let split: Vec<&str> = s.splitn('/', 1).collect();
-        if split.len() < 2 {
-            return None
+        let mut split = s.splitn('/', 1);
+
+        let num = split.next().and_then(|n| FromStr::from_str(n));
+        let den = split.next().or(Some("1")).and_then(|d| FromStr::from_str(d));
+
+        match (num, den) {
+            (Some(n), Some(d)) => Some(Ratio::new(n, d)),
+            _ => None
         }
-        let a_option: Option<T> = FromStr::from_str(*split.get(0));
-        a_option.and_then(|a| {
-            let b_option: Option<T> = FromStr::from_str(*split.get(1));
-            b_option.and_then(|b| {
-                Some(Ratio::new(a.clone(), b.clone()))
-            })
-        })
     }
 }
+
 impl<T: FromStrRadix + Clone + Integer + PartialOrd>
     FromStrRadix for Ratio<T> {
     /// Parses `numer/denom` where the numbers are in base `radix`.
@@ -429,6 +433,13 @@ fn test_is_integer() {
         assert!(!_neg1_2.is_integer());
     }
 
+    #[test]
+    fn test_show() {
+        assert_eq!(format!("{}", _2), "2".to_string());
+        assert_eq!(format!("{}", _1_2), "1/2".to_string());
+        assert_eq!(format!("{}", _0), "0".to_string());
+        assert_eq!(format!("{}", Ratio::from_integer(-2i)), "-2".to_string());
+    }
 
     mod arith {
         use super::{_0, _1, _2, _1_2, _3_2, _neg1_2, to_big};
@@ -562,11 +573,11 @@ fn test(r: Rational, s: String) {
             assert_eq!(FromStr::from_str(s.as_slice()), Some(r));
             assert_eq!(r.to_str(), s);
         }
-        test(_1, "1/1".to_string());
-        test(_0, "0/1".to_string());
+        test(_1, "1".to_string());
+        test(_0, "0".to_string());
         test(_1_2, "1/2".to_string());
         test(_3_2, "3/2".to_string());
-        test(_2, "2/1".to_string());
+        test(_2, "2".to_string());
         test(_neg1_2, "-1/2".to_string());
     }
     #[test]
index ae1a10f620663c3edcc6d9187bf17bf338cdd127..593b9785d475abb3f65ae9d3b49982ea7e8c5299 100644 (file)
 //! is not recommended to use this library directly, but rather the official
 //! interface through `std::rand`.
 
-#![crate_id = "rand#0.11.0-pre"]
+#![crate_id = "rand#0.11.0"]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, phase, globs)]
index 61b133c4e68abef23ecb275231bb1d1f1cc0863d..b69c4471267bb6cefdf80f1d940966eb32b941b9 100644 (file)
 //! characters in the search text and `m` is the number of instructions in a
 //! compiled expression.
 
-#![crate_id = "regex#0.11.0-pre"]
+#![crate_id = "regex#0.11.0"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, phase)]
index ff5cada05ea2e18adbc63282cbbdf86d075d5567..b21b51bf4eb5e7e1a3bb915d194e4a668b18b704 100644 (file)
 //! This crate provides the `regex!` macro. Its use is documented in the
 //! `regex` crate.
 
-#![crate_id = "regex_macros#0.11.0-pre"]
+#![crate_id = "regex_macros#0.11.0"]
 #![crate_type = "dylib"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![feature(plugin_registrar, managed_boxes, quote)]
 
@@ -32,7 +32,6 @@
 use syntax::codemap;
 use syntax::ext::build::AstBuilder;
 use syntax::ext::base::{ExtCtxt, MacResult, MacExpr, DummyResult};
-use syntax::parse;
 use syntax::parse::token;
 use syntax::print::pprust;
 
@@ -615,8 +614,7 @@ fn vec_expr<T, It: Iterator<T>>(&self, xs: It,
 /// Looks for a single string literal and returns it.
 /// Otherwise, logs an error with cx.span_err and returns None.
 fn parse(cx: &mut ExtCtxt, tts: &[ast::TokenTree]) -> Option<String> {
-    let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(),
-                                                Vec::from_slice(tts));
+    let mut parser = cx.new_parser_from_tts(tts);
     let entry = cx.expand_expr(parser.parse_expr());
     let regex = match entry.node {
         ast::ExprLit(lit) => {
index c85e0099ab832f9012f59c4ece785ac7298e43e4..c653e1ca07787afc4b141a772ac9588d26a847c9 100644 (file)
 //! necessary. It is an error to include this library when also linking with
 //! the system libc library.
 
-#![crate_id = "rlibc#0.11.0-pre"]
+#![crate_id = "rlibc#0.11.0"]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 #![feature(intrinsics)]
 
 #![no_std]
 #![experimental]
 
-// This library is definining the builtin functions, so it would be a shame for
+// This library defines the builtin functions, so it would be a shame for
 // LLVM to optimize these function calls to themselves!
 #![no_builtins]
 
index 17f29639601dd72455e0e7e38202970df8f3a298..a190d9309cc8df8612f6fbe85f5a8b76173be14f 100644 (file)
@@ -119,7 +119,7 @@ pub mod write {
     // get all hardware potential via VFP3 (hardware floating point)
     // and NEON (SIMD) instructions supported by LLVM.
     // Note that without those flags various linking errors might
-    // arise as some of intrinsicts are converted into function calls
+    // arise as some of intrinsics are converted into function calls
     // and nobody provides implementations those functions
     fn target_feature<'a>(sess: &'a Session) -> &'a str {
         match sess.targ_cfg.os {
index 401d3fd9b244fa4f141d679a1108281ffd24623a..54ba9db570e6366af279777b1d4cdee4b96e4a11 100644 (file)
@@ -25,7 +25,7 @@
 use std::mem;
 use std::gc::{Gc, GC};
 
-pub static VERSION: &'static str = "0.11.0-pre";
+pub static VERSION: &'static str = "0.11.0";
 
 pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
                                -> ast::Crate {
index 2cd41cf14ab2128e380e5b794bfc54dd1c6f91ae..729eb908e3943be911df2c82cf1a159e4fb02494 100644 (file)
@@ -18,7 +18,7 @@
 
 */
 
-#![crate_id = "rustc#0.11.0-pre"]
+#![crate_id = "rustc#0.11.0"]
 #![experimental]
 #![comment = "The Rust compiler"]
 #![license = "MIT/ASL2"]
@@ -26,7 +26,7 @@
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-      html_root_url = "http://doc.rust-lang.org/")]
+      html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![allow(deprecated)]
 #![feature(macro_rules, globs, struct_variant, managed_boxes, quote)]
index 30296cb318617af1fdc0a544374596a44e5a37c8..a8f778934ae47e21c28b9b3c016d5326598bd1ea 100644 (file)
@@ -902,12 +902,10 @@ fn get_lints(&self) -> LintArray {
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         match (&p.node, cx.tcx.def_map.borrow().find(&p.id)) {
-            (&ast::PatIdent(_, ref path, _), Some(&def::DefStatic(_, false))) => {
-                // last identifier alone is right choice for this lint.
-                let ident = path.segments.last().unwrap().identifier;
-                let s = token::get_ident(ident);
+            (&ast::PatIdent(_, ref path1, _), Some(&def::DefStatic(_, false))) => {
+                let s = token::get_ident(path1.node);
                 if s.get().chars().any(|c| c.is_lowercase()) {
-                    cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path.span,
+                    cx.span_lint(NON_UPPERCASE_PATTERN_STATICS, path1.span,
                         format!("static constant in pattern `{}` should have an uppercase \
                                  name such as `{}`",
                                 s.get(), s.get().chars().map(|c| c.to_uppercase())
@@ -931,15 +929,13 @@ fn get_lints(&self) -> LintArray {
 
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         match &p.node {
-            &ast::PatIdent(_, ref path, _) => {
+            &ast::PatIdent(_, ref path1, _) => {
                 match cx.tcx.def_map.borrow().find(&p.id) {
                     Some(&def::DefLocal(_, _)) | Some(&def::DefBinding(_, _)) |
                             Some(&def::DefArg(_, _)) => {
-                        // last identifier alone is right choice for this lint.
-                        let ident = path.segments.last().unwrap().identifier;
-                        let s = token::get_ident(ident);
+                        let s = token::get_ident(path1.node);
                         if s.get().len() > 0 && s.get().char_at(0).is_uppercase() {
-                            cx.span_lint(UPPERCASE_VARIABLES, path.span,
+                            cx.span_lint(UPPERCASE_VARIABLES, path1.span,
                                          "variable names should start with \
                                           a lowercase character");
                         }
@@ -989,7 +985,7 @@ fn check_unnecessary_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &s
             _ => {}
         }
 
-        /// Expressions that syntatically contain an "exterior" struct
+        /// Expressions that syntactically contain an "exterior" struct
         /// literal i.e. not surrounded by any parens or other
         /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
         /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
@@ -1113,15 +1109,10 @@ fn check_unused_mut_pat(&self, cx: &Context, pats: &[Gc<ast::Pat>]) {
         // avoid false warnings in match arms with multiple patterns
         let mut mutables = HashMap::new();
         for &p in pats.iter() {
-            pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path| {
+            pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path1| {
+                let ident = path1.node;
                 match mode {
                     ast::BindByValue(ast::MutMutable) => {
-                        if path.segments.len() != 1 {
-                            cx.sess().span_bug(p.span,
-                                               "mutable binding that doesn't consist \
-                                                of exactly one segment");
-                        }
-                        let ident = path.segments.get(0).identifier;
                         if !token::get_ident(ident).get().starts_with("_") {
                             mutables.insert_or_update_with(ident.name as uint,
                                 vec!(id), |_, old| { old.push(id); });
index 96284f8de261a78254f0faa3ff837c660049cf2b..6eb7c5a4310e6f9cb61abc55001000ae275839cc 100644 (file)
@@ -809,9 +809,8 @@ fn encode_method_argument_names(ebml_w: &mut Encoder,
     for arg in decl.inputs.iter() {
         ebml_w.start_tag(tag_method_argument_name);
         match arg.pat.node {
-            ast::PatIdent(_, ref name, _) => {
-                let name = name.segments.last().unwrap().identifier;
-                let name = token::get_ident(name);
+            ast::PatIdent(_, ref path1, _) => {
+                let name = token::get_ident(path1.node);
                 ebml_w.writer.write(name.get().as_bytes());
             }
             _ => {}
@@ -1106,8 +1105,9 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
         match ty.node {
             ast::TyPath(ref path, ref bounds, _) if path.segments
                                                         .len() == 1 => {
+                let ident = path.segments.last().unwrap().identifier;
                 assert!(bounds.is_none());
-                encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
+                encode_impl_type_basename(ebml_w, ident);
             }
             _ => {}
         }
index 6df474809779ac37cd62eebe2b80a6c86f002b7b..de77fa602c9b406a0bf85a4e8c58b04bb72b7975 100644 (file)
@@ -66,9 +66,9 @@ pub fn gather_move_from_pat(bccx: &BorrowckCtxt,
                             move_pat: &ast::Pat,
                             cmt: mc::cmt) {
     let pat_span_path_opt = match move_pat.node {
-        ast::PatIdent(_, ref path, _) => {
-            Some(MoveSpanAndPath::with_span_and_path(move_pat.span,
-                                                     (*path).clone()))
+        ast::PatIdent(_, ref path1, _) => {
+            Some(MoveSpanAndPath{span: move_pat.span,
+                                 ident: path1.node})
         },
         _ => None,
     };
index 925244849bc8ab408f340242155d4c9f3812a742..f5c91f7b1b3bf4441e664ff0fd479486864b6d22 100644 (file)
@@ -56,19 +56,8 @@ pub fn with_move_info(move_from: mc::cmt,
 
 #[deriving(Clone)]
 pub struct MoveSpanAndPath {
-    span: codemap::Span,
-    path: ast::Path
-}
-
-impl MoveSpanAndPath {
-    pub fn with_span_and_path(span: codemap::Span,
-                              path: ast::Path)
-                              -> MoveSpanAndPath {
-        MoveSpanAndPath {
-            span: span,
-            path: path,
-        }
-    }
+    pub span: codemap::Span,
+    pub ident: ast::Ident
 }
 
 pub struct GroupedMoveErrors {
@@ -83,7 +72,7 @@ fn report_move_errors(bccx: &BorrowckCtxt, errors: &Vec<MoveError>) {
         let mut is_first_note = true;
         for move_to in error.move_to_places.iter() {
             note_move_destination(bccx, move_to.span,
-                                  &move_to.path, is_first_note);
+                                  &move_to.ident, is_first_note);
             is_first_note = false;
         }
     }
@@ -154,9 +143,9 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
 
 fn note_move_destination(bccx: &BorrowckCtxt,
                          move_to_span: codemap::Span,
-                         pat_ident_path: &ast::Path,
+                         pat_ident: &ast::Ident,
                          is_first_note: bool) {
-    let pat_name = pprust::path_to_str(pat_ident_path);
+    let pat_name = pprust::ident_to_str(pat_ident);
     if is_first_note {
         bccx.span_note(
             move_to_span,
index 1400e207ab1a8615f73416d3fd7a7227bea279a1..8b5c7061a149faf4587ff9eecfd6a742ec6e5140 100644 (file)
@@ -74,12 +74,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-struct MatchCheckCtxt<'a> {
-    tcx: &'a ty::ctxt
+pub struct MatchCheckCtxt<'a> {
+    pub tcx: &'a ty::ctxt
 }
 
 #[deriving(Clone, PartialEq)]
-enum Constructor {
+pub enum Constructor {
     /// The constructor of all patterns that don't vary by constructor,
     /// e.g. struct patterns and fixed-length arrays.
     Single,
@@ -93,9 +93,10 @@ enum Constructor {
     Slice(uint)
 }
 
-#[deriving(Clone)]
+#[deriving(Clone, PartialEq)]
 enum Usefulness {
-    Useful(Vec<Gc<Pat>>),
+    Useful,
+    UsefulWithWitness(Vec<Gc<Pat>>),
     NotUseful
 }
 
@@ -104,15 +105,6 @@ enum WitnessPreference {
     LeaveOutWitness
 }
 
-impl Usefulness {
-    fn useful(self) -> Option<Vec<Gc<Pat>>> {
-        match self {
-            Useful(pats) => Some(pats),
-            _ => None
-        }
-    }
-}
-
 impl<'a> Visitor<()> for MatchCheckCtxt<'a> {
     fn visit_expr(&mut self, ex: &Expr, _: ()) {
         check_expr(self, ex);
@@ -203,7 +195,8 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
             let v = vec!(*pat);
             match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
                 NotUseful => cx.tcx.sess.span_err(pat.span, "unreachable pattern"),
-                _ => ()
+                Useful => (),
+                UsefulWithWitness(_) => unreachable!()
             }
             if arm.guard.is_none() {
                 let Matrix(mut rows) = seen;
@@ -223,7 +216,7 @@ fn raw_pat(p: Gc<Pat>) -> Gc<Pat> {
 
 fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
     match is_useful(cx, m, [wild()], ConstructWitness) {
-        Useful(pats) => {
+        UsefulWithWitness(pats) => {
             let witness = match pats.as_slice() {
                 [witness] => witness,
                 [] => wild(),
@@ -234,7 +227,8 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
         }
         NotUseful => {
             // This is good, wildcard pattern isn't reachable
-        }
+        },
+        _ => unreachable!()
     }
 }
 
@@ -404,11 +398,14 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: ty::t,
 
 // 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: &MatchCheckCtxt, m @ &Matrix(ref rows): &Matrix,
+fn is_useful(cx: &MatchCheckCtxt, matrix @ &Matrix(ref rows): &Matrix,
              v: &[Gc<Pat>], witness: WitnessPreference) -> Usefulness {
-    debug!("{:}", m);
+    debug!("{:}", matrix);
     if rows.len() == 0u {
-        return Useful(vec!());
+        return match witness {
+            ConstructWitness => UsefulWithWitness(vec!()),
+            LeaveOutWitness => Useful
+        };
     }
     if rows.get(0).len() == 0u {
         return NotUseful;
@@ -438,53 +435,46 @@ fn is_useful(cx: &MatchCheckCtxt, m @ &Matrix(ref rows): &Matrix,
 
     let constructors = pat_constructors(cx, v[0], left_ty, max_slice_length);
     if constructors.is_empty() {
-        match missing_constructor(cx, m, left_ty, max_slice_length) {
+        match missing_constructor(cx, matrix, left_ty, max_slice_length) {
             None => {
-                all_constructors(cx, left_ty, max_slice_length).move_iter().filter_map(|c| {
-                    is_useful_specialized(cx, m, v, c.clone(),
-                                          left_ty, witness).useful().map(|pats| {
-                        Useful(match witness {
-                            ConstructWitness => {
-                                let arity = constructor_arity(cx, &c, left_ty);
-                                let subpats = {
-                                    let pat_slice = pats.as_slice();
-                                    Vec::from_fn(arity, |i| {
-                                        pat_slice.get(i).map(|p| p.clone())
-                                            .unwrap_or_else(|| wild())
-                                    })
-                                };
-                                let mut result = vec!(construct_witness(cx, &c, subpats, left_ty));
-                                result.extend(pats.move_iter().skip(arity));
-                                result
-                            }
-                            LeaveOutWitness => vec!()
-                        })
-                    })
-                }).nth(0).unwrap_or(NotUseful)
+                all_constructors(cx, left_ty, max_slice_length).move_iter().map(|c| {
+                    match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
+                        UsefulWithWitness(pats) => UsefulWithWitness({
+                            let arity = constructor_arity(cx, &c, left_ty);
+                            let subpats = {
+                                let pat_slice = pats.as_slice();
+                                Vec::from_fn(arity, |i| {
+                                    pat_slice.get(i).map(|p| p.clone())
+                                        .unwrap_or_else(|| wild())
+                                })
+                            };
+                            let mut result = vec!(construct_witness(cx, &c, subpats, left_ty));
+                            result.extend(pats.move_iter().skip(arity));
+                            result
+                        }),
+                        result => result
+                    }
+                }).find(|result| result != &NotUseful).unwrap_or(NotUseful)
             },
 
             Some(constructor) => {
                 let matrix = Matrix(rows.iter().filter_map(|r|
                     default(cx, r.as_slice())).collect());
                 match is_useful(cx, &matrix, v.tail(), witness) {
-                    Useful(pats) => Useful(match witness {
-                        ConstructWitness => {
-                            let arity = constructor_arity(cx, &constructor, left_ty);
-                            let wild_pats = Vec::from_elem(arity, wild());
-                            let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
-                            (vec!(enum_pat)).append(pats.as_slice())
-                        }
-                        LeaveOutWitness => vec!()
-                    }),
+                    UsefulWithWitness(pats) => {
+                        let arity = constructor_arity(cx, &constructor, left_ty);
+                        let wild_pats = Vec::from_elem(arity, wild());
+                        let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
+                        UsefulWithWitness(vec!(enum_pat).append(pats.as_slice()))
+                    },
                     result => result
                 }
             }
         }
     } else {
-        constructors.move_iter().filter_map(|c| {
-            is_useful_specialized(cx, m, v, c.clone(), left_ty, witness)
-                .useful().map(|pats| Useful(pats))
-        }).nth(0).unwrap_or(NotUseful)
+        constructors.move_iter().map(|c|
+            is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness)
+        ).find(|result| result != &NotUseful).unwrap_or(NotUseful)
     }
 }
 
@@ -492,9 +482,9 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, v: &[Gc<P
                          ctor: Constructor, lty: ty::t, witness: WitnessPreference) -> Usefulness {
     let arity = constructor_arity(cx, &ctor, lty);
     let matrix = Matrix(m.iter().filter_map(|r| {
-        specialize(cx, r.as_slice(), &ctor, arity)
+        specialize(cx, r.as_slice(), &ctor, 0u, arity)
     }).collect());
-    match specialize(cx, v, &ctor, arity) {
+    match specialize(cx, v, &ctor, 0u, arity) {
         Some(v) => is_useful(cx, &matrix, v.as_slice(), witness),
         None => NotUseful
     }
@@ -519,6 +509,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
                     let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
                     vec!(ConstantValue(eval_const_expr(cx.tcx, &*const_expr)))
                 },
+                Some(&DefStruct(_)) => vec!(Single),
                 Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!()
             },
@@ -560,27 +551,12 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
     }
 }
 
-fn is_wild(cx: &MatchCheckCtxt, p: Gc<Pat>) -> bool {
-    let pat = raw_pat(p);
-    match pat.node {
-        PatWild | PatWildMulti => true,
-        PatIdent(_, _, _) =>
-            match cx.tcx.def_map.borrow().find(&pat.id) {
-                Some(&DefVariant(_, _, _)) | Some(&DefStatic(..)) => false,
-                _ => true
-            },
-        PatVec(ref before, Some(_), ref after) =>
-            before.is_empty() && after.is_empty(),
-        _ => false
-    }
-}
-
 /// This computes the arity of a constructor. The arity of a constructor
 /// is how many subpattern patterns of that constructor should be expanded to.
 ///
 /// For instance, a tuple pattern (_, 42u, Some([])) has the arity of 3.
 /// A struct pattern's arity is the number of fields it contains, etc.
-fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: ty::t) -> uint {
+pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: ty::t) -> uint {
     match ty::get(ty).sty {
         ty::ty_tup(ref fs) => fs.len(),
         ty::ty_box(_) | ty::ty_uniq(_) => 1u,
@@ -628,11 +604,11 @@ fn range_covered_by_constructor(ctor: &Constructor,
 /// different patterns.
 /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
 /// fields filled with wild patterns.
-fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
-              constructor: &Constructor, arity: uint) -> Option<Vec<Gc<Pat>>> {
+pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
+                  constructor: &Constructor, col: uint, arity: uint) -> Option<Vec<Gc<Pat>>> {
     let &Pat {
         id: pat_id, node: ref node, span: pat_span
-    } = &(*raw_pat(r[0]));
+    } = &(*raw_pat(r[col]));
     let head: Option<Vec<Gc<Pat>>> = match node {
         &PatWild =>
             Some(Vec::from_elem(arity, wild())),
@@ -776,11 +752,11 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
             None
         }
     };
-    head.map(|head| head.append(r.tail()))
+    head.map(|head| head.append(r.slice_to(col)).append(r.slice_from(col + 1)))
 }
 
 fn default(cx: &MatchCheckCtxt, r: &[Gc<Pat>]) -> Option<Vec<Gc<Pat>>> {
-    if is_wild(cx, r[0]) {
+    if pat_is_binding_or_wild(&cx.tcx.def_map, &*raw_pat(r[0])) {
         Some(Vec::from_slice(r.tail()))
     } else {
         None
@@ -833,12 +809,14 @@ fn check_fn(cx: &mut MatchCheckCtxt,
 
 fn is_refutable(cx: &MatchCheckCtxt, pat: Gc<Pat>) -> Option<Gc<Pat>> {
     let pats = Matrix(vec!(vec!(pat)));
-    is_useful(cx, &pats, [wild()], ConstructWitness)
-        .useful()
-        .map(|pats| {
+    match is_useful(cx, &pats, [wild()], ConstructWitness) {
+        UsefulWithWitness(pats) => {
             assert_eq!(pats.len(), 1);
-            pats.get(0).clone()
-        })
+            Some(pats.get(0).clone())
+        },
+        NotUseful => None,
+        Useful => unreachable!()
+    }
 }
 
 // Legality of move bindings checking
index e7457f370d9adea16253276cb4fa5bc0b9224758..70db3e964abb3273cc2f4d078a3c809b1c7fdad0 100644 (file)
@@ -247,6 +247,10 @@ fn visit_pat(&mut self, pat: &ast::Pat, ctxt: MarkSymbolVisitorContext) {
             ast::PatStruct(_, ref fields, _) => {
                 self.handle_field_pattern_match(pat, fields.as_slice());
             }
+            ast::PatIdent(_, _, _) => {
+                // it might be the only use of a static:
+                self.lookup_and_handle_definition(&pat.id)
+            }
             _ => ()
         }
 
index 3e72341ebb02fa37db26279e186f9eff122d6400..1e06b3b1fd46393a0434ddd09230667307c76c01 100644 (file)
 use middle::freevars;
 use middle::pat_util;
 use middle::ty;
-use middle::typeck::MethodCall;
+use middle::typeck::{MethodCall, MethodObject, MethodOrigin, MethodParam};
+use middle::typeck::{MethodStatic};
 use middle::typeck;
-use syntax::ast;
-use syntax::codemap::{Span};
 use util::ppaux::Repr;
 
 use std::gc::Gc;
+use syntax::ast;
+use syntax::codemap::Span;
 
 ///////////////////////////////////////////////////////////////////////////
 // The Delegate trait
@@ -101,6 +102,74 @@ pub enum MutateMode {
     WriteAndRead, // x += y
 }
 
+enum OverloadedCallType {
+    FnOverloadedCall,
+    FnMutOverloadedCall,
+    FnOnceOverloadedCall,
+}
+
+impl OverloadedCallType {
+    fn from_trait_id(tcx: &ty::ctxt, trait_id: ast::DefId)
+                     -> OverloadedCallType {
+        for &(maybe_function_trait, overloaded_call_type) in [
+            (tcx.lang_items.fn_once_trait(), FnOnceOverloadedCall),
+            (tcx.lang_items.fn_mut_trait(), FnMutOverloadedCall),
+            (tcx.lang_items.fn_trait(), FnOverloadedCall)
+        ].iter() {
+            match maybe_function_trait {
+                Some(function_trait) if function_trait == trait_id => {
+                    return overloaded_call_type
+                }
+                _ => continue,
+            }
+        }
+
+        tcx.sess.bug("overloaded call didn't map to known function trait")
+    }
+
+    fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
+                      -> OverloadedCallType {
+        let method_descriptor =
+            match tcx.methods.borrow_mut().find(&method_id) {
+                None => {
+                    tcx.sess.bug("overloaded call method wasn't in method \
+                                  map")
+                }
+                Some(ref method_descriptor) => (*method_descriptor).clone(),
+            };
+        let impl_id = match method_descriptor.container {
+            ty::TraitContainer(_) => {
+                tcx.sess.bug("statically resolved overloaded call method \
+                              belonged to a trait?!")
+            }
+            ty::ImplContainer(impl_id) => impl_id,
+        };
+        let trait_ref = match ty::impl_trait_ref(tcx, impl_id) {
+            None => {
+                tcx.sess.bug("statically resolved overloaded call impl \
+                              didn't implement a trait?!")
+            }
+            Some(ref trait_ref) => (*trait_ref).clone(),
+        };
+        OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
+    }
+
+    fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
+                          -> OverloadedCallType {
+        match *origin {
+            MethodStatic(def_id) => {
+                OverloadedCallType::from_method_id(tcx, def_id)
+            }
+            MethodParam(ref method_param) => {
+                OverloadedCallType::from_trait_id(tcx, method_param.trait_id)
+            }
+            MethodObject(ref method_object) => {
+                OverloadedCallType::from_trait_id(tcx, method_object.trait_id)
+            }
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // The ExprUseVisitor type
 //
@@ -413,19 +482,37 @@ fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
                 }
             }
             _ => {
-                match self.tcx()
-                          .method_map
-                          .borrow()
-                          .find(&MethodCall::expr(call.id)) {
-                    Some(_) => {
-                        // FIXME(#14774, pcwalton): Implement this.
+                let overloaded_call_type =
+                    match self.tcx()
+                              .method_map
+                              .borrow()
+                              .find(&MethodCall::expr(call.id)) {
+                    Some(ref method_callee) => {
+                        OverloadedCallType::from_method_origin(
+                            self.tcx(),
+                            &method_callee.origin)
                     }
                     None => {
                         self.tcx().sess.span_bug(
                             callee.span,
                             format!("unexpected callee type {}",
-                                    callee_ty.repr(self.tcx())).as_slice());
+                                    callee_ty.repr(self.tcx())).as_slice())
+                    }
+                };
+                match overloaded_call_type {
+                    FnMutOverloadedCall => {
+                        self.borrow_expr(callee,
+                                         ty::ReScope(call.id),
+                                         ty::MutBorrow,
+                                         ClosureInvocation);
+                    }
+                    FnOverloadedCall => {
+                        self.borrow_expr(callee,
+                                         ty::ReScope(call.id),
+                                         ty::ImmBorrow,
+                                         ClosureInvocation);
                     }
+                    FnOnceOverloadedCall => self.consume_expr(callee),
                 }
             }
         }
index 34754f045ffce8b00ecc1d677d3c2df6b6d536b5..a7154e78bc58612d7243430bd2aa3a106be75ac1 100644 (file)
@@ -13,6 +13,7 @@
 use middle::freevars;
 use middle::subst;
 use middle::ty;
+use middle::typeck::{MethodCall, NoAdjustment};
 use middle::typeck;
 use util::ppaux::{Repr, ty_to_str};
 use util::ppaux::UserString;
@@ -20,7 +21,7 @@
 use syntax::ast::*;
 use syntax::attr;
 use syntax::codemap::Span;
-use syntax::print::pprust::{expr_to_str,path_to_str};
+use syntax::print::pprust::{expr_to_str, ident_to_str};
 use syntax::{visit};
 use syntax::visit::Visitor;
 
@@ -261,7 +262,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
         ExprCast(ref source, _) => {
             let source_ty = ty::expr_ty(cx.tcx, &**source);
             let target_ty = ty::expr_ty(cx.tcx, e);
-            check_trait_cast(cx, source_ty, target_ty, source.span);
+            let method_call = MethodCall {
+                expr_id: e.id,
+                adjustment: NoAdjustment,
+            };
+            check_trait_cast(cx,
+                             source_ty,
+                             target_ty,
+                             source.span,
+                             method_call);
         }
         ExprRepeat(ref element, ref count_expr) => {
             let count = ty::eval_repeat_count(cx.tcx, &**count_expr);
@@ -281,7 +290,15 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
                 ty::AutoObject(..) => {
                     let source_ty = ty::expr_ty(cx.tcx, e);
                     let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
-                    check_trait_cast(cx, source_ty, target_ty, e.span);
+                    let method_call = MethodCall {
+                        expr_id: e.id,
+                        adjustment: typeck::AutoObject,
+                    };
+                    check_trait_cast(cx,
+                                     source_ty,
+                                     target_ty,
+                                     e.span,
+                                     method_call);
                 }
                 ty::AutoAddEnv(..) |
                 ty::AutoDerefRef(..) => {}
@@ -364,15 +381,62 @@ fn check_bounds_on_type_parameters(cx: &mut Context, e: &Expr) {
     }
 }
 
-fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
+fn check_type_parameter_bounds_in_vtable_result(
+        cx: &mut Context,
+        span: Span,
+        vtable_res: &typeck::vtable_res) {
+    for origins in vtable_res.iter() {
+        for origin in origins.iter() {
+            let (type_param_defs, substs) = match *origin {
+                typeck::vtable_static(def_id, ref tys, _) => {
+                    let type_param_defs =
+                        ty::lookup_item_type(cx.tcx, def_id).generics
+                                                            .types
+                                                            .clone();
+                    (type_param_defs, (*tys).clone())
+                }
+                _ => {
+                    // Nothing to do here.
+                    continue
+                }
+            };
+            for type_param_def in type_param_defs.iter() {
+                let typ = substs.types.get(type_param_def.space,
+                                           type_param_def.index);
+                check_typaram_bounds(cx, span, *typ, type_param_def)
+            }
+        }
+    }
+}
+
+fn check_trait_cast(cx: &mut Context,
+                    source_ty: ty::t,
+                    target_ty: ty::t,
+                    span: Span,
+                    method_call: MethodCall) {
     check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
     match ty::get(target_ty).sty {
-        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ ty, .. }) => match ty::get(ty).sty {
-            ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
-                check_trait_cast_bounds(cx, span, source_ty, bounds);
+        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ ty, .. }) => {
+            match ty::get(ty).sty {
+                ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
+                     match cx.tcx.vtable_map.borrow().find(&method_call) {
+                        None => {
+                            cx.tcx.sess.span_bug(span,
+                                                 "trait cast not in vtable \
+                                                  map?!")
+                        }
+                        Some(vtable_res) => {
+                            check_type_parameter_bounds_in_vtable_result(
+                                cx,
+                                span,
+                                vtable_res)
+                        }
+                    };
+                    check_trait_cast_bounds(cx, span, source_ty, bounds);
+                }
+                _ => {}
             }
-            _ => {}
-        },
+        }
         _ => {}
     }
 }
@@ -627,7 +691,7 @@ fn check_sized(tcx: &ty::ctxt, ty: ty::t, name: String, sp: Span) {
 fn check_pat(cx: &mut Context, pat: &Pat) {
     let var_name = match pat.node {
         PatWild => Some("_".to_string()),
-        PatIdent(_, ref path, _) => Some(path_to_str(path).to_string()),
+        PatIdent(_, ref path1, _) => Some(ident_to_str(&path1.node).to_string()),
         _ => None
     };
 
index 20e4188a8f6c5cf01386610e71d9b435b0b4a968..186a737a56ba34f6cd0833d10d5894a050797f0a 100644 (file)
@@ -248,7 +248,6 @@ pub fn collect_language_items(krate: &ast::Crate,
     OrdTraitLangItem,                "ord",                     ord_trait;
 
     StrEqFnLangItem,                 "str_eq",                  str_eq_fn;
-    UniqStrEqFnLangItem,             "uniq_str_eq",             uniq_str_eq_fn;
 
     // A number of failure-related lang items. The `fail_` item corresponds to
     // divide-by-zero and various failure cases with `match`. The
index 5c09466cd96820bdfb686760caf70ba973302ba7..d48f7f541f0da016d1c85cfe980a529656c89031 100644 (file)
@@ -367,9 +367,9 @@ fn visit_fn(ir: &mut IrMaps,
     for arg in decl.inputs.iter() {
         pat_util::pat_bindings(&ir.tcx.def_map,
                                &*arg.pat,
-                               |_bm, arg_id, _x, path| {
+                               |_bm, arg_id, _x, path1| {
             debug!("adding argument {}", arg_id);
-            let ident = ast_util::path_to_ident(path);
+            let ident = path1.node;
             fn_maps.add_variable(Arg(arg_id, ident));
         })
     };
@@ -399,9 +399,9 @@ fn visit_fn(ir: &mut IrMaps,
 }
 
 fn visit_local(ir: &mut IrMaps, local: &Local) {
-    pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path| {
+    pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
         debug!("adding local variable {}", p_id);
-        let name = ast_util::path_to_ident(path);
+        let name = path1.node;
         ir.add_live_node_for_node(p_id, VarDefNode(sp));
         ir.add_variable(Local(LocalInfo {
           id: p_id,
@@ -413,10 +413,10 @@ fn visit_local(ir: &mut IrMaps, local: &Local) {
 
 fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
     for pat in arm.pats.iter() {
-        pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path| {
+        pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
             debug!("adding local variable {} from match with bm {:?}",
                    p_id, bm);
-            let name = ast_util::path_to_ident(path);
+            let name = path1.node;
             ir.add_live_node_for_node(p_id, VarDefNode(sp));
             ir.add_variable(Local(LocalInfo {
                 id: p_id,
@@ -1522,10 +1522,10 @@ fn warn_about_unused_args(&self, decl: &FnDecl, entry_ln: LiveNode) {
         for arg in decl.inputs.iter() {
             pat_util::pat_bindings(&self.ir.tcx.def_map,
                                    &*arg.pat,
-                                   |_bm, p_id, sp, path| {
+                                   |_bm, p_id, sp, path1| {
                 let var = self.variable(p_id, sp);
                 // Ignore unused self.
-                let ident = ast_util::path_to_ident(path);
+                let ident = path1.node;
                 if ident.name != special_idents::self_.name {
                     self.warn_about_unused(sp, p_id, entry_ln, var);
                 }
index e1a2a5741fbe1b0d0e03ba62c41dd7666e647f6e..54cca082e0de86950a10f7c26aeb8672369b6ae4 100644 (file)
@@ -383,7 +383,7 @@ pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt> {
             Some(adjustment) => {
                 match *adjustment {
                     ty::AutoObject(..) => {
-                        // Implicity cast a concrete object to trait object.
+                        // Implicitly cast a concrete object to trait object.
                         // Result is an rvalue.
                         let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
                         Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
index 24d97f5aac354212171f61b1110cae7506c0fb96..2d53d742ee44b15800ed580c6f375f65b1e87a24 100644 (file)
@@ -14,7 +14,7 @@
 use std::collections::HashMap;
 use std::gc::{Gc, GC};
 use syntax::ast::*;
-use syntax::ast_util::{path_to_ident, walk_pat};
+use syntax::ast_util::{walk_pat};
 use syntax::codemap::{Span, DUMMY_SP};
 
 pub type PatIdMap = HashMap<Ident, NodeId>;
@@ -23,8 +23,8 @@
 // use the NodeId of their namesake in the first pattern.
 pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
     let mut map = HashMap::new();
-    pat_bindings(dm, pat, |_bm, p_id, _s, n| {
-      map.insert(path_to_ident(n), p_id);
+    pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
+      map.insert(path1.node, p_id);
     });
     map
 }
@@ -75,7 +75,7 @@ pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
 /// `match foo() { Some(a) => (), None => () }`
 pub fn pat_bindings(dm: &resolve::DefMap,
                     pat: &Pat,
-                    it: |BindingMode, NodeId, Span, &Path|) {
+                    it: |BindingMode, NodeId, Span, &SpannedIdent|) {
     walk_pat(pat, |p| {
         match p.node {
           PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
@@ -102,10 +102,10 @@ pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool {
     contains_bindings
 }
 
-pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
+pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Ident> {
     match pat.node {
-        PatIdent(BindByValue(_), ref path, None) => {
-            Some(path)
+        PatIdent(BindByValue(_), ref path1, None) => {
+            Some(&path1.node)
         }
         _ => {
             None
index 414aac47cdcc0882719525d04160e9e6bf1fabc3..76e962a3bc4da6a1894def5f64c29b5c0b374072 100644 (file)
@@ -1267,7 +1267,7 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
             // error messages without (too many) false positives
             // (i.e. we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
-            // publically visible.
+            // publicly visible.
             ast::ItemImpl(ref g, ref trait_ref, self_, ref methods) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
index d42befc65421b36bb184bb7f1a3053b1f986eb86..b7b4618a7904619a97f34eacd6d26a0efe1a2b0f 100644 (file)
 use syntax::ast::*;
 use syntax::ast;
 use syntax::ast_util::{local_def};
-use syntax::ast_util::{path_to_ident, walk_pat, trait_method_to_ty_method};
+use syntax::ast_util::{walk_pat, trait_method_to_ty_method};
 use syntax::ext::mtwt;
 use syntax::parse::token::special_idents;
 use syntax::parse::token;
-use syntax::print::pprust::path_to_str;
 use syntax::codemap::{Span, DUMMY_SP, Pos};
 use syntax::owned_slice::OwnedSlice;
 use syntax::visit;
@@ -1247,7 +1246,7 @@ fn build_reduced_graph_for_item(&mut self,
                 // Create the module and add all methods.
                 match ty.node {
                     TyPath(ref path, _, _) if path.segments.len() == 1 => {
-                        let name = path_to_ident(path);
+                        let name = path.segments.last().unwrap().identifier;
 
                         let parent_opt = parent.module().children.borrow()
                                                .find_copy(&name.name);
@@ -4104,8 +4103,8 @@ fn resolve_local(&mut self, local: &Local) {
     // user and one 'x' came from the macro.
     fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
         let mut result = HashMap::new();
-        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| {
-            let name = mtwt::resolve(path_to_ident(path));
+        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
+            let name = mtwt::resolve(path1.node);
             result.insert(name,
                           binding_info {span: sp,
                                         binding_mode: binding_mode});
@@ -4314,8 +4313,7 @@ fn resolve_pattern(&mut self,
         let pat_id = pattern.id;
         walk_pat(pattern, |pattern| {
             match pattern.node {
-                PatIdent(binding_mode, ref path, _)
-                        if !path.global && path.segments.len() == 1 => {
+                PatIdent(binding_mode, ref path1, _) => {
 
                     // The meaning of pat_ident with no type parameters
                     // depends on whether an enum variant or unit-like struct
@@ -4326,7 +4324,7 @@ fn resolve_pattern(&mut self,
                     // such a value is simply disallowed (since it's rarely
                     // what you want).
 
-                    let ident = path.segments.get(0).identifier;
+                    let ident = path1.node;
                     let renamed = mtwt::resolve(ident);
 
                     match self.resolve_bare_identifier_pattern(ident) {
@@ -4416,57 +4414,12 @@ struct or enum variant",
                                     format!("identifier `{}` is bound \
                                              more than once in the same \
                                              pattern",
-                                            path_to_str(path)).as_slice());
+                                            token::get_ident(ident)).as_slice());
                             }
                             // Else, not bound in the same pattern: do
                             // nothing.
                         }
                     }
-
-                    // Check the types in the path pattern.
-                    for ty in path.segments
-                                  .iter()
-                                  .flat_map(|seg| seg.types.iter()) {
-                        self.resolve_type(&**ty);
-                    }
-                }
-
-                PatIdent(binding_mode, ref path, _) => {
-                    // This must be an enum variant, struct, or constant.
-                    match self.resolve_path(pat_id, path, ValueNS, false) {
-                        Some(def @ (DefVariant(..), _)) |
-                        Some(def @ (DefStruct(..), _)) => {
-                            self.record_def(pattern.id, def);
-                        }
-                        Some(def @ (DefStatic(..), _)) => {
-                            self.enforce_default_binding_mode(
-                                pattern,
-                                binding_mode,
-                                "a constant");
-                            self.record_def(pattern.id, def);
-                        }
-                        Some(_) => {
-                            self.resolve_error(
-                                path.span,
-                                format!("`{}` is not an enum variant or constant",
-                                        token::get_ident(
-                                            path.segments
-                                                .last()
-                                                .unwrap()
-                                                .identifier)).as_slice())
-                        }
-                        None => {
-                            self.resolve_error(path.span,
-                                                  "unresolved enum variant");
-                        }
-                    }
-
-                    // Check the types in the path pattern.
-                    for ty in path.segments
-                                  .iter()
-                                  .flat_map(|s| s.types.iter()) {
-                        self.resolve_type(&**ty);
-                    }
                 }
 
                 PatEnum(ref path, _) => {
@@ -5202,8 +5155,8 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                              in a static method. Maybe a \
                                              `self` argument is missing?");
                                 } else {
-                                    let name = path_to_ident(path).name;
-                                    let mut msg = match self.find_fallback_in_self_type(name) {
+                                    let last_name = path.segments.last().unwrap().identifier.name;
+                                    let mut msg = match self.find_fallback_in_self_type(last_name) {
                                         NoSuggestion => {
                                             // limit search to 5 to reduce the number
                                             // of stupid suggestions
index 2b2f3b8fb0b5fd085ba00cdc24736f1bde36644d..bdb7d30339d66f010f0ba8e170dffe17dcaafe4b 100644 (file)
@@ -484,7 +484,7 @@ fn process_static(&mut self,
     {
         let qualname = self.analysis.ty_cx.map.path_to_str(item.id);
 
-        // If the variable is immutable, save the initialising expresion.
+        // If the variable is immutable, save the initialising expression.
         let value = match mt {
             ast::MutMutable => String::from_str("<mutable>"),
             ast::MutImmutable => self.span.snippet(expr.span),
@@ -845,7 +845,7 @@ fn process_method_call(&mut self,
                 let decl_id = ty::trait_method_of_method(&self.analysis.ty_cx, def_id);
 
                 // This incantation is required if the method referenced is a trait's
-                // defailt implementation.
+                // default implementation.
                 let def_id = ty::method(&self.analysis.ty_cx, def_id).provided_source
                                     .unwrap_or(def_id);
                 (Some(def_id), decl_id)
@@ -926,7 +926,7 @@ fn process_pat(&mut self, p:&ast::Pat, e: DxrVisitorEnv) {
                 self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef));
                 visit::walk_pat(self, p, e);
             }
-            ast::PatIdent(bm, ref path, ref optional_subpattern) => {
+            ast::PatIdent(bm, ref path1, ref optional_subpattern) => {
                 let immut = match bm {
                     // Even if the ref is mut, you can't change the ref, only
                     // the data pointed at, so showing the initialising expression
@@ -940,7 +940,8 @@ fn process_pat(&mut self, p:&ast::Pat, e: DxrVisitorEnv) {
                     }
                 };
                 // collect path for either visit_local or visit_arm
-                self.collected_paths.push((p.id, path.clone(), immut, recorder::VarRef));
+                let path = ast_util::ident_to_path(path1.span,path1.node);
+                self.collected_paths.push((p.id, path, immut, recorder::VarRef));
                 match *optional_subpattern {
                     None => {}
                     Some(subpattern) => self.visit_pat(&*subpattern, e),
@@ -1402,7 +1403,7 @@ pub fn process_crate(sess: &Session,
         info!("Writing output to {}", disp);
     }
 
-    // Create ouput file.
+    // Create output file.
     let mut out_name = cratename.clone();
     out_name.push_str(".csv");
     root_path.push(out_name);
index 5fae1635bee8e491dc458670c6856a41a0aa6213..2f8918acb30bc30d8700ed3b954338b3ad36b037 100644 (file)
  * We store information about the bound variables for each arm as part of the
  * per-arm `ArmData` struct.  There is a mapping from identifiers to
  * `BindingInfo` structs.  These structs contain the mode/id/type of the
- * binding, but they also contain up to two LLVM values, called `llmatch` and
- * `llbinding` respectively (the `llbinding`, as will be described shortly, is
- * optional and only present for by-value bindings---therefore it is bundled
- * up as part of the `TransBindingMode` type).  Both point at allocas.
+ * binding, but they also contain an LLVM value which points at an alloca
+ * called `llmatch`. For by value bindings that are Copy, we also create
+ * an extra alloca that we copy the matched value to so that any changes
+ * we do to our copy is not reflected in the original and vice-versa.
+ * We don't do this if it's a move since the original value can't be used
+ * and thus allowing us to cheat in not creating an extra alloca.
  *
  * The `llmatch` binding always stores a pointer into the value being matched
  * which points at the data for the binding.  If the value being matched has
  * up against an identifier, we store the current pointer into the
  * corresponding alloca.
  *
- * In addition, for each by-value binding (copy or move), we will create a
- * second alloca (`llbinding`) that will hold the final value.  In this
- * example, that means that `d` would have this second alloca of type `D` (and
- * hence `llbinding` has type `D*`).
- *
  * Once a pattern is completely matched, and assuming that there is no guard
  * pattern, we will branch to a block that leads to the body itself.  For any
  * by-value bindings, this block will first load the ptr from `llmatch` (the
- * one of type `D*`) and copy/move the value into `llbinding` (the one of type
- * `D`).  The second alloca then becomes the value of the local variable.  For
- * by ref bindings, the value of the local variable is simply the first
- * alloca.
+ * one of type `D*`) and then load a second time to get the actual value (the
+ * one of type `D`). For by ref bindings, the value of the local variable is
+ * simply the first alloca.
  *
  * So, for the example above, we would generate a setup kind of like this:
  *
  *        | Entry |
  *        +-------+
  *            |
- *        +-------------------------------------------+
- *        | llmatch_c = (addr of first half of tuple) |
- *        | llmatch_d = (addr of first half of tuple) |
- *        +-------------------------------------------+
+ *        +--------------------------------------------+
+ *        | llmatch_c = (addr of first half of tuple)  |
+ *        | llmatch_d = (addr of second half of tuple) |
+ *        +--------------------------------------------+
  *            |
  *        +--------------------------------------+
- *        | *llbinding_d = **llmatch_dlbinding_d |
+ *        | *llbinding_d = **llmatch_d           |
  *        +--------------------------------------+
  *
  * If there is a guard, the situation is slightly different, because we must
  *        +-------------------------------------------+
  *            |
  *        +-------------------------------------------------+
- *        | *llbinding_d = **llmatch_dlbinding_d            |
+ *        | *llbinding_d = **llmatch_d                      |
  *        | check condition                                 |
- *        | if false { free *llbinding_d, goto next case }  |
+ *        | if false { goto next case }                     |
  *        | if true { goto body }                           |
  *        +-------------------------------------------------+
  *
  * The handling for the cleanups is a bit... sensitive.  Basically, the body
  * is the one that invokes `add_clean()` for each binding.  During the guard
  * evaluation, we add temporary cleanups and revoke them after the guard is
- * evaluated (it could fail, after all).  Presuming the guard fails, we drop
- * the various values we copied explicitly.  Note that guards and moves are
+ * evaluated (it could fail, after all). Note that guards and moves are
  * just plain incompatible.
  *
  * Some relevant helper functions that manage bindings:
  * - `create_bindings_map()`
- * - `store_non_ref_bindings()`
  * - `insert_lllocals()`
  *
  *
 use lib::llvm::{llvm, ValueRef, BasicBlockRef};
 use middle::const_eval;
 use middle::def;
-use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
+use middle::check_match;
+use middle::lang_items::StrEqFnLangItem;
 use middle::pat_util::*;
 use middle::resolve::DefMap;
 use middle::trans::adt;
 use middle::trans::common::*;
 use middle::trans::consts;
 use middle::trans::controlflow;
-use middle::trans::datum;
 use middle::trans::datum::*;
 use middle::trans::expr::Dest;
 use middle::trans::expr;
-use middle::trans::glue;
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::trans::debuginfo;
 use util::common::indenter;
 use util::ppaux::{Repr, vec_map_to_str};
 
+use std;
 use std::collections::HashMap;
 use std::cell::Cell;
 use std::rc::Rc;
-use std::gc::{Gc, GC};
+use std::gc::{Gc};
 use syntax::ast;
 use syntax::ast::Ident;
-use syntax::ast_util::path_to_ident;
-use syntax::ast_util;
-use syntax::codemap::{Span, DUMMY_SP};
+use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
 
-// An option identifying a literal: either a unit-like struct or an
-// expression.
+// An option identifying a literal: either an expression or a DefId of a static expression.
 enum Lit {
-    UnitLikeStructLit(ast::NodeId),    // the node ID of the pattern
     ExprLit(Gc<ast::Expr>),
     ConstLit(ast::DefId),              // the def ID of the constant
 }
@@ -252,7 +242,7 @@ pub enum VecLenOpt {
 // range)
 enum Opt {
     lit(Lit),
-    var(ty::Disr, Rc<adt::Repr>),
+    var(ty::Disr, Rc<adt::Repr>, ast::DefId),
     range(Gc<ast::Expr>, Gc<ast::Expr>),
     vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
@@ -260,14 +250,12 @@ enum Opt {
 fn lit_to_expr(tcx: &ty::ctxt, a: &Lit) -> Gc<ast::Expr> {
     match *a {
         ExprLit(existing_a_expr) => existing_a_expr,
-        ConstLit(a_const) => const_eval::lookup_const_by_id(tcx, a_const).unwrap(),
-        UnitLikeStructLit(_) => fail!("lit_to_expr: unexpected struct lit"),
+        ConstLit(a_const) => const_eval::lookup_const_by_id(tcx, a_const).unwrap()
     }
 }
 
 fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
     match (a, b) {
-        (&lit(UnitLikeStructLit(a)), &lit(UnitLikeStructLit(b))) => a == b,
         (&lit(a), &lit(b)) => {
             let a_expr = lit_to_expr(tcx, &a);
             let b_expr = lit_to_expr(tcx, &b);
@@ -284,7 +272,7 @@ fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
                 _ => fail!("compare_list_exprs: type mismatch"),
             }
         }
-        (&var(a, _), &var(b, _)) => a == b,
+        (&var(a, _, _), &var(b, _, _)) => a == b,
         (&vec_len(a1, a2, _), &vec_len(b1, b2, _)) =>
             a1 == b1 && a2 == b2,
         _ => false
@@ -308,11 +296,6 @@ fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
             let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
             return single_result(Result::new(bcx, lit_datum.val));
         }
-        lit(UnitLikeStructLit(pat_id)) => {
-            let struct_ty = ty::node_id_to_type(bcx.tcx(), pat_id);
-            let datum = datum::rvalue_scratch_datum(bcx, struct_ty, "");
-            return single_result(Result::new(bcx, datum.val));
-        }
         lit(l @ ConstLit(ref def_id)) => {
             let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_to_expr(bcx.tcx(), &l).id);
             let (llval, _) = consts::get_const_val(bcx.ccx(), *def_id);
@@ -320,7 +303,7 @@ fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
             let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
             return single_result(Result::new(bcx, lit_datum.val));
         }
-        var(disr_val, ref repr) => {
+        var(disr_val, ref repr, _) => {
             return adt::trans_case(bcx, &**repr, disr_val);
         }
         range(ref l1, ref l2) => {
@@ -342,18 +325,8 @@ fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
     let def = ccx.tcx.def_map.borrow().get_copy(&pat_id);
     match def {
         def::DefVariant(enum_id, var_id, _) => {
-            let variants = ty::enum_variants(ccx.tcx(), enum_id);
-            for v in (*variants).iter() {
-                if var_id == v.id {
-                    return var(v.disr_val,
-                               adt::represent_node(bcx, pat_id))
-                }
-            }
-            unreachable!();
-        }
-        def::DefFn(..) |
-        def::DefStruct(_) => {
-            return lit(UnitLikeStructLit(pat_id));
+            let variant = ty::enum_variant_with_id(ccx.tcx(), enum_id, var_id);
+            var(variant.disr_val, adt::represent_node(bcx, pat_id), var_id)
         }
         _ => {
             ccx.sess().bug("non-variant or struct in variant_opt()");
@@ -362,8 +335,9 @@ fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
 }
 
 #[deriving(Clone)]
-enum TransBindingMode {
-    TrByValue(/*llbinding:*/ ValueRef),
+pub enum TransBindingMode {
+    TrByCopy(/* llbinding */ ValueRef),
+    TrByMove,
     TrByRef,
 }
 
@@ -376,12 +350,12 @@ enum TransBindingMode {
  * - `id` is the node id of the binding
  * - `ty` is the Rust type of the binding */
  #[deriving(Clone)]
-struct BindingInfo {
-    llmatch: ValueRef,
-    trmode: TransBindingMode,
-    id: ast::NodeId,
-    span: Span,
-    ty: ty::t,
+pub struct BindingInfo {
+    pub llmatch: ValueRef,
+    pub trmode: TransBindingMode,
+    pub id: ast::NodeId,
+    pub span: Span,
+    pub ty: ty::t,
 }
 
 type BindingsMap = HashMap<Ident, BindingInfo>;
@@ -440,13 +414,13 @@ fn expand_nested_bindings<'a, 'b>(
 
     m.iter().map(|br| {
         match br.pats.get(col).node {
-            ast::PatIdent(_, ref path, Some(inner)) => {
+            ast::PatIdent(_, ref path1, Some(inner)) => {
                 let pats = Vec::from_slice(br.pats.slice(0u, col))
                            .append((vec!(inner))
                                    .append(br.pats.slice(col + 1u, br.pats.len())).as_slice());
 
                 let mut bound_ptrs = br.bound_ptrs.clone();
-                bound_ptrs.push((path_to_ident(path), val));
+                bound_ptrs.push((path1.node, val));
                 Match {
                     pats: pats,
                     data: &*br.data,
@@ -462,16 +436,7 @@ fn expand_nested_bindings<'a, 'b>(
     }).collect()
 }
 
-fn assert_is_binding_or_wild(bcx: &Block, p: Gc<ast::Pat>) {
-    if !pat_is_binding_or_wild(&bcx.tcx().def_map, &*p) {
-        bcx.sess().span_bug(
-            p.span,
-            format!("expected an identifier pattern but found p: {}",
-                    p.repr(bcx.tcx())).as_slice());
-    }
-}
-
-type enter_pat<'a> = |Gc<ast::Pat>|: 'a -> Option<Vec<Gc<ast::Pat>>>;
+type enter_pats<'a> = |&[Gc<ast::Pat>]|: 'a -> Option<Vec<Gc<ast::Pat>>>;
 
 fn enter_match<'a, 'b>(
                bcx: &'b Block<'b>,
@@ -479,7 +444,7 @@ fn enter_match<'a, 'b>(
                m: &'a [Match<'a, 'b>],
                col: uint,
                val: ValueRef,
-               e: enter_pat)
+               e: enter_pats)
                -> Vec<Match<'a, 'b>> {
     debug!("enter_match(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
@@ -489,16 +454,13 @@ fn enter_match<'a, 'b>(
     let _indenter = indenter();
 
     m.iter().filter_map(|br| {
-        e(*br.pats.get(col)).map(|sub| {
-            let pats = sub.append(br.pats.slice(0u, col))
-                            .append(br.pats.slice(col + 1u, br.pats.len()));
-
+        e(br.pats.as_slice()).map(|pats| {
             let this = *br.pats.get(col);
             let mut bound_ptrs = br.bound_ptrs.clone();
             match this.node {
-                ast::PatIdent(_, ref path, None) => {
+                ast::PatIdent(_, ref path1, None) => {
                     if pat_is_binding(dm, &*this) {
-                        bound_ptrs.push((path_to_ident(path), val));
+                        bound_ptrs.push((path1.node, val));
                     }
                 }
                 _ => {}
@@ -528,11 +490,11 @@ fn enter_default<'a, 'b>(
     let _indenter = indenter();
 
     // Collect all of the matches that can match against anything.
-    enter_match(bcx, dm, m, col, val, |p| {
-        match p.node {
-          ast::PatWild | ast::PatWildMulti => Some(Vec::new()),
-          ast::PatIdent(_, _, None) if pat_is_binding(dm, &*p) => Some(Vec::new()),
-          _ => None
+    enter_match(bcx, dm, m, col, val, |pats| {
+        if pat_is_binding_or_wild(dm, pats[col]) {
+            Some(Vec::from_slice(pats.slice_to(col)).append(pats.slice_from(col + 1)))
+        } else {
+            None
         }
     })
 }
@@ -561,8 +523,14 @@ fn enter_default<'a, 'b>(
 // <nmatsakis> so all patterns must either be records (resp. tuples) or
 //             wildcards
 
+/// The above is now outdated in that enter_match() now takes a function that
+/// takes the complete row of patterns rather than just the first one.
+/// Also, most of the enter_() family functions have been unified with
+/// the check_match specialization step.
 fn enter_opt<'a, 'b>(
              bcx: &'b Block<'b>,
+             _: ast::NodeId,
+             dm: &DefMap,
              m: &'a [Match<'a, 'b>],
              opt: &Opt,
              col: uint,
@@ -577,88 +545,31 @@ fn enter_opt<'a, 'b>(
            bcx.val_to_str(val));
     let _indenter = indenter();
 
-    let tcx = bcx.tcx();
-    let dummy = box(GC) ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
-    let mut i = 0;
-    enter_match(bcx, &tcx.def_map, m, col, val, |p| {
-        let answer = match p.node {
-            ast::PatEnum(..) |
-            ast::PatIdent(_, _, None) if pat_is_const(&tcx.def_map, &*p) => {
-                let const_def = tcx.def_map.borrow().get_copy(&p.id);
-                let const_def_id = const_def.def_id();
-                if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
-                    Some(Vec::new())
-                } else {
-                    None
-                }
-            }
-            ast::PatEnum(_, ref subpats) => {
-                if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
-                    // FIXME: Must we clone?
-                    match *subpats {
-                        None => Some(Vec::from_elem(variant_size, dummy)),
-                        Some(ref subpats) => {
-                            Some((*subpats).iter().map(|x| *x).collect())
-                        }
-                    }
-                } else {
-                    None
-                }
-            }
-            ast::PatIdent(_, _, None)
-                    if pat_is_variant_or_struct(&tcx.def_map, &*p) => {
-                if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
-                    Some(Vec::new())
-                } else {
-                    None
-                }
-            }
-            ast::PatLit(l) => {
-                if opt_eq(tcx, &lit(ExprLit(l)), opt) { Some(Vec::new()) }
-                else { None }
-            }
-            ast::PatRange(l1, l2) => {
-                if opt_eq(tcx, &range(l1, l2), opt) { Some(Vec::new()) }
-                else { None }
-            }
-            ast::PatStruct(_, ref field_pats, _) => {
-                if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
-                    // Look up the struct variant ID.
-                    let struct_id;
-                    match tcx.def_map.borrow().get_copy(&p.id) {
-                        def::DefVariant(_, found_struct_id, _) => {
-                            struct_id = found_struct_id;
-                        }
-                        _ => {
-                            tcx.sess.span_bug(p.span, "expected enum variant def");
-                        }
-                    }
+    let ctor = match opt {
+        &lit(x) => check_match::ConstantValue(const_eval::eval_const_expr(
+            bcx.tcx(), lit_to_expr(bcx.tcx(), &x))),
+        &range(ref lo, ref hi) => check_match::ConstantRange(
+            const_eval::eval_const_expr(bcx.tcx(), &**lo),
+            const_eval::eval_const_expr(bcx.tcx(), &**hi)
+        ),
+        &vec_len(len, _, _) => check_match::Slice(len),
+        &var(_, _, def_id) => check_match::Variant(def_id)
+    };
 
-                    // Reorder the patterns into the same order they were
-                    // specified in the struct definition. Also fill in
-                    // unspecified fields with dummy.
-                    let mut reordered_patterns = Vec::new();
-                    let r = ty::lookup_struct_fields(tcx, struct_id);
-                    for field in r.iter() {
-                            match field_pats.iter().find(|p| p.ident.name
-                                                         == field.name) {
-                                None => reordered_patterns.push(dummy),
-                                Some(fp) => reordered_patterns.push(fp.pat)
-                            }
-                    }
-                    Some(reordered_patterns)
-                } else {
-                    None
-                }
-            }
+    let mut i = 0;
+    let tcx = bcx.tcx();
+    let mcx = check_match::MatchCheckCtxt { tcx: bcx.tcx() };
+    enter_match(bcx, dm, m, col, val, |pats| {
+        let span = pats[col].span;
+        let specialized = match pats[col].node {
             ast::PatVec(ref before, slice, ref after) => {
                 let (lo, hi) = match *opt {
                     vec_len(_, _, (lo, hi)) => (lo, hi),
-                    _ => tcx.sess.span_bug(p.span,
+                    _ => tcx.sess.span_bug(span,
                                            "vec pattern but not vec opt")
                 };
 
-                match slice {
+                let elems = match slice {
                     Some(slice) if i >= lo && i <= hi => {
                         let n = before.len() + after.len();
                         let this_opt = vec_len(n, vec_len_ge(before.len()),
@@ -690,172 +601,15 @@ fn enter_opt<'a, 'b>(
                         }
                     }
                     _ => None
-                }
+                };
+                elems.map(|head| head.append(pats.slice_to(col)).append(pats.slice_from(col + 1)))
             }
             _ => {
-                assert_is_binding_or_wild(bcx, p);
-                Some(Vec::from_elem(variant_size, dummy))
+                check_match::specialize(&mcx, pats.as_slice(), &ctor, col, variant_size)
             }
         };
         i += 1;
-        answer
-    })
-}
-
-fn enter_rec_or_struct<'a, 'b>(
-                       bcx: &'b Block<'b>,
-                       dm: &DefMap,
-                       m: &'a [Match<'a, 'b>],
-                       col: uint,
-                       fields: &[ast::Ident],
-                       val: ValueRef)
-                       -> Vec<Match<'a, 'b>> {
-    debug!("enter_rec_or_struct(bcx={}, m={}, col={}, val={})",
-           bcx.to_str(),
-           m.repr(bcx.tcx()),
-           col,
-           bcx.val_to_str(val));
-    let _indenter = indenter();
-
-    let dummy = box(GC) ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
-    enter_match(bcx, dm, m, col, val, |p| {
-        match p.node {
-            ast::PatStruct(_, ref fpats, _) => {
-                let mut pats = Vec::new();
-                for fname in fields.iter() {
-                    match fpats.iter().find(|p| p.ident.name == fname.name) {
-                        None => pats.push(dummy),
-                        Some(pat) => pats.push(pat.pat)
-                    }
-                }
-                Some(pats)
-            }
-            _ => {
-                assert_is_binding_or_wild(bcx, p);
-                Some(Vec::from_elem(fields.len(), dummy))
-            }
-        }
-    })
-}
-
-fn enter_tup<'a, 'b>(
-             bcx: &'b Block<'b>,
-             dm: &DefMap,
-             m: &'a [Match<'a, 'b>],
-             col: uint,
-             val: ValueRef,
-             n_elts: uint)
-             -> Vec<Match<'a, 'b>> {
-    debug!("enter_tup(bcx={}, m={}, col={}, val={})",
-           bcx.to_str(),
-           m.repr(bcx.tcx()),
-           col,
-           bcx.val_to_str(val));
-    let _indenter = indenter();
-
-    let dummy = box(GC) ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
-    enter_match(bcx, dm, m, col, val, |p| {
-        match p.node {
-            ast::PatTup(ref elts) => {
-                let mut new_elts = Vec::new();
-                for elt in elts.iter() {
-                    new_elts.push((*elt).clone())
-                }
-                Some(new_elts)
-            }
-            _ => {
-                assert_is_binding_or_wild(bcx, p);
-                Some(Vec::from_elem(n_elts, dummy))
-            }
-        }
-    })
-}
-
-fn enter_tuple_struct<'a, 'b>(
-                      bcx: &'b Block<'b>,
-                      dm: &DefMap,
-                      m: &'a [Match<'a, 'b>],
-                      col: uint,
-                      val: ValueRef,
-                      n_elts: uint)
-                      -> Vec<Match<'a, 'b>> {
-    debug!("enter_tuple_struct(bcx={}, m={}, col={}, val={})",
-           bcx.to_str(),
-           m.repr(bcx.tcx()),
-           col,
-           bcx.val_to_str(val));
-    let _indenter = indenter();
-
-    let dummy = box(GC) ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
-    enter_match(bcx, dm, m, col, val, |p| {
-        match p.node {
-            ast::PatEnum(_, Some(ref elts)) => {
-                Some(elts.iter().map(|x| (*x)).collect())
-            }
-            ast::PatEnum(_, None) => {
-                Some(Vec::from_elem(n_elts, dummy))
-            }
-            _ => {
-                assert_is_binding_or_wild(bcx, p);
-                Some(Vec::from_elem(n_elts, dummy))
-            }
-        }
-    })
-}
-
-fn enter_uniq<'a, 'b>(
-              bcx: &'b Block<'b>,
-              dm: &DefMap,
-              m: &'a [Match<'a, 'b>],
-              col: uint,
-              val: ValueRef)
-              -> Vec<Match<'a, 'b>> {
-    debug!("enter_uniq(bcx={}, m={}, col={}, val={})",
-           bcx.to_str(),
-           m.repr(bcx.tcx()),
-           col,
-           bcx.val_to_str(val));
-    let _indenter = indenter();
-
-    let dummy = box(GC) ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
-    enter_match(bcx, dm, m, col, val, |p| {
-        match p.node {
-            ast::PatBox(sub) => {
-                Some(vec!(sub))
-            }
-            _ => {
-                assert_is_binding_or_wild(bcx, p);
-                Some(vec!(dummy))
-            }
-        }
-    })
-}
-
-fn enter_region<'a, 'b>(
-                bcx: &'b Block<'b>,
-                dm: &DefMap,
-                m: &'a [Match<'a, 'b>],
-                col: uint,
-                val: ValueRef)
-                -> Vec<Match<'a, 'b>> {
-    debug!("enter_region(bcx={}, m={}, col={}, val={})",
-           bcx.to_str(),
-           m.repr(bcx.tcx()),
-           col,
-           bcx.val_to_str(val));
-    let _indenter = indenter();
-
-    let dummy = box(GC) ast::Pat { id: 0, node: ast::PatWild, span: DUMMY_SP };
-    enter_match(bcx, dm, m, col, val, |p| {
-        match p.node {
-            ast::PatRegion(sub) => {
-                Some(vec!(sub))
-            }
-            _ => {
-                assert_is_binding_or_wild(bcx, p);
-                Some(vec!(dummy))
-            }
-        }
+        specialized
     })
 }
 
@@ -896,18 +650,13 @@ fn add_veclen_to_set(set: &mut Vec<Opt> , i: uint,
                 add_to_set(ccx.tcx(), &mut found, lit(ExprLit(l)));
             }
             ast::PatIdent(..) => {
-                // This is one of: an enum variant, a unit-like struct, or a
-                // variable binding.
+                // This is either an enum variant or a variable binding.
                 let opt_def = ccx.tcx.def_map.borrow().find_copy(&cur.id);
                 match opt_def {
                     Some(def::DefVariant(..)) => {
                         add_to_set(ccx.tcx(), &mut found,
                                    variant_opt(bcx, cur.id));
                     }
-                    Some(def::DefStruct(..)) => {
-                        add_to_set(ccx.tcx(), &mut found,
-                                   lit(UnitLikeStructLit(cur.id)));
-                    }
                     Some(def::DefStatic(const_did, false)) => {
                         add_to_set(ccx.tcx(), &mut found,
                                    lit(ConstLit(const_did)));
@@ -1027,49 +776,6 @@ fn extract_vec_elems<'a>(
     ExtractedBlock { vals: elems, bcx: bcx }
 }
 
-/// Checks every pattern in `m` at `col` column.
-/// If there are a struct pattern among them function
-/// returns list of all fields that are matched in these patterns.
-/// Function returns None if there is no struct pattern.
-/// Function doesn't collect fields from struct-like enum variants.
-/// Function can return empty list if there is only wildcard struct pattern.
-fn collect_record_or_struct_fields<'a>(
-                                   bcx: &'a Block<'a>,
-                                   m: &[Match],
-                                   col: uint)
-                                   -> Option<Vec<ast::Ident> > {
-    let mut fields: Vec<ast::Ident> = Vec::new();
-    let mut found = false;
-    for br in m.iter() {
-        match br.pats.get(col).node {
-          ast::PatStruct(_, ref fs, _) => {
-            match ty::get(node_id_type(bcx, br.pats.get(col).id)).sty {
-              ty::ty_struct(..) => {
-                   extend(&mut fields, fs.as_slice());
-                   found = true;
-              }
-              _ => ()
-            }
-          }
-          _ => ()
-        }
-    }
-    if found {
-        return Some(fields);
-    } else {
-        return None;
-    }
-
-    fn extend(idents: &mut Vec<ast::Ident> , field_pats: &[ast::FieldPat]) {
-        for field_pat in field_pats.iter() {
-            let field_ident = field_pat.ident;
-            if !idents.iter().any(|x| x.name == field_ident.name) {
-                idents.push(field_ident);
-            }
-        }
-    }
-}
-
 // Macro for deciding whether any of the remaining matches fit a given kind of
 // pattern.  Note that, because the macro is well-typed, either ALL of the
 // matches should fit that sort of pattern or NONE (however, some of the
@@ -1093,21 +799,17 @@ fn any_region_pat(m: &[Match], col: uint) -> bool {
     any_pat!(m, ast::PatRegion(_))
 }
 
-fn any_tup_pat(m: &[Match], col: uint) -> bool {
-    any_pat!(m, ast::PatTup(_))
-}
-
-fn any_tuple_struct_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
+fn any_irrefutable_adt_pat(bcx: &Block, m: &[Match], col: uint) -> bool {
     m.iter().any(|br| {
         let pat = *br.pats.get(col);
         match pat.node {
-            ast::PatEnum(_, _) => {
+            ast::PatTup(_) => true,
+            ast::PatEnum(..) | ast::PatIdent(_, _, None) | ast::PatStruct(..) =>
                 match bcx.tcx().def_map.borrow().find(&pat.id) {
                     Some(&def::DefFn(..)) |
                     Some(&def::DefStruct(..)) => true,
                     _ => false
-                }
-            }
+                },
             _ => false
         }
     })
@@ -1197,7 +899,7 @@ fn score(p: &ast::Pat) -> uint {
 }
 
 #[deriving(PartialEq)]
-pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len, }
+pub enum branch_kind { no_branch, single, switch, compare, compare_vec_len }
 
 // Compiles a comparison between two things.
 fn compare_values<'a>(
@@ -1226,21 +928,6 @@ fn compare_str<'a>(cx: &'a Block<'a>,
     }
 
     match ty::get(rhs_t).sty {
-        ty::ty_uniq(t) => match ty::get(t).sty {
-            ty::ty_str => {
-                let scratch_lhs = alloca(cx, val_ty(lhs), "__lhs");
-                Store(cx, lhs, scratch_lhs);
-                let scratch_rhs = alloca(cx, val_ty(rhs), "__rhs");
-                Store(cx, rhs, scratch_rhs);
-                let did = langcall(cx,
-                                   None,
-                                   format!("comparison of `{}`",
-                                           cx.ty_to_str(rhs_t)).as_slice(),
-                                   UniqStrEqFnLangItem);
-                callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None)
-            }
-            _ => cx.sess().bug("only strings supported in compare_values"),
-        },
         ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
             ty::ty_str => compare_str(cx, lhs, rhs, rhs_t),
             ty::ty_vec(mt, _) => match ty::get(mt.ty).sty {
@@ -1254,70 +941,40 @@ fn compare_str<'a>(cx: &'a Block<'a>,
                 },
                 _ => cx.sess().bug("only byte strings supported in compare_values"),
             },
-            _ => cx.sess().bug("on string and byte strings supported in compare_values"),
+            _ => cx.sess().bug("only string and byte strings supported in compare_values"),
         },
         _ => cx.sess().bug("only scalars, byte strings, and strings supported in compare_values"),
     }
 }
 
-fn store_non_ref_bindings<'a>(
-                          bcx: &'a Block<'a>,
-                          bindings_map: &BindingsMap,
-                          opt_cleanup_scope: Option<cleanup::ScopeId>)
-                          -> &'a Block<'a>
-{
-    /*!
-     * For each copy/move binding, copy the value from the value being
-     * matched into its final home.  This code executes once one of
-     * the patterns for a given arm has completely matched.  It adds
-     * cleanups to the `opt_cleanup_scope`, if one is provided.
-     */
-
-    let fcx = bcx.fcx;
-    let mut bcx = bcx;
-    for (_, &binding_info) in bindings_map.iter() {
-        match binding_info.trmode {
-            TrByValue(lldest) => {
-                let llval = Load(bcx, binding_info.llmatch); // get a T*
-                let datum = Datum::new(llval, binding_info.ty, Lvalue);
-                bcx = datum.store_to(bcx, lldest);
-
-                match opt_cleanup_scope {
-                    None => {}
-                    Some(s) => {
-                        fcx.schedule_drop_mem(s, lldest, binding_info.ty);
-                    }
-                }
-            }
-            TrByRef => {}
-        }
-    }
-    return bcx;
-}
-
-fn insert_lllocals<'a>(bcx: &'a Block<'a>,
-                       bindings_map: &BindingsMap,
-                       cleanup_scope: cleanup::ScopeId)
+fn insert_lllocals<'a>(mut bcx: &'a Block<'a>,
+                       bindings_map: &BindingsMap)
                        -> &'a Block<'a> {
     /*!
      * For each binding in `data.bindings_map`, adds an appropriate entry into
-     * the `fcx.lllocals` map, scheduling cleanup in `cleanup_scope`.
+     * the `fcx.lllocals` map
      */
 
-    let fcx = bcx.fcx;
-
     for (&ident, &binding_info) in bindings_map.iter() {
         let llval = match binding_info.trmode {
-            // By value bindings: use the stack slot that we
-            // copied/moved the value into
-            TrByValue(lldest) => lldest,
+            // By value mut binding for a copy type: load from the ptr
+            // into the matched value and copy to our alloca
+            TrByCopy(llbinding) => {
+                let llval = Load(bcx, binding_info.llmatch);
+                let datum = Datum::new(llval, binding_info.ty, Lvalue);
+                bcx = datum.store_to(bcx, llbinding);
+
+                llbinding
+            },
+
+            // By value move bindings: load from the ptr into the matched value
+            TrByMove => Load(bcx, binding_info.llmatch),
 
             // By ref binding: use the ptr into the matched value
             TrByRef => binding_info.llmatch
         };
 
         let datum = Datum::new(llval, binding_info.ty, Lvalue);
-        fcx.schedule_drop_mem(cleanup_scope, llval, binding_info.ty);
 
         debug!("binding {:?} to {}",
                binding_info.id,
@@ -1327,9 +984,7 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
         if bcx.sess().opts.debuginfo == FullDebugInfo {
             debuginfo::create_match_binding_metadata(bcx,
                                                      ident,
-                                                     binding_info.id,
-                                                     binding_info.span,
-                                                     datum);
+                                                     binding_info);
         }
     }
     bcx
@@ -1351,28 +1006,16 @@ fn compile_guard<'a, 'b>(
            vec_map_to_str(vals, |v| bcx.val_to_str(*v)));
     let _indenter = indenter();
 
-    // Lest the guard itself should fail, introduce a temporary cleanup
-    // scope for any non-ref bindings we create.
-    let temp_scope = bcx.fcx.push_custom_cleanup_scope();
-
-    let mut bcx = bcx;
-    bcx = store_non_ref_bindings(bcx, &data.bindings_map,
-                                 Some(cleanup::CustomScope(temp_scope)));
-    bcx = insert_lllocals(bcx, &data.bindings_map,
-                          cleanup::CustomScope(temp_scope));
+    let mut bcx = insert_lllocals(bcx, &data.bindings_map);
 
     let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
     let val = val.to_llbool(bcx);
 
-    // Cancel cleanups now that the guard successfully executed.  If
-    // the guard was false, we will drop the values explicitly
-    // below. Otherwise, we'll add lvalue cleanups at the end.
-    bcx.fcx.pop_custom_cleanup_scope(temp_scope);
-
     return with_cond(bcx, Not(bcx, val), |bcx| {
-        // Guard does not match: free the values we copied,
-        // and remove all bindings from the lllocals table
-        let bcx = drop_bindings(bcx, data);
+        // Guard does not match: remove all bindings from the lllocals table
+        for (_, &binding_info) in data.bindings_map.iter() {
+            bcx.fcx.lllocals.borrow_mut().remove(&binding_info.id);
+        }
         match chk {
             // If the default arm is the only one left, move on to the next
             // condition explicitly rather than (possibly) falling back to
@@ -1386,21 +1029,6 @@ fn compile_guard<'a, 'b>(
         };
         bcx
     });
-
-    fn drop_bindings<'a>(bcx: &'a Block<'a>, data: &ArmData)
-                     -> &'a Block<'a> {
-        let mut bcx = bcx;
-        for (_, &binding_info) in data.bindings_map.iter() {
-            match binding_info.trmode {
-                TrByValue(llval) => {
-                    bcx = glue::drop_ty(bcx, llval, binding_info.ty);
-                }
-                TrByRef => {}
-            }
-            bcx.fcx.lllocals.borrow_mut().remove(&binding_info.id);
-        }
-        return bcx;
-    }
 }
 
 fn compile_submatch<'a, 'b>(
@@ -1475,103 +1103,41 @@ fn compile_submatch_continue<'a, 'b>(
 
     let vals_left = Vec::from_slice(vals.slice(0u, col)).append(vals.slice(col + 1u, vals.len()));
     let ccx = bcx.fcx.ccx;
-    let mut pat_id = 0;
-    for br in m.iter() {
-        // Find a real id (we're adding placeholder wildcard patterns, but
-        // each column is guaranteed to have at least one real pattern)
-        if pat_id == 0 {
-            pat_id = br.pats.get(col).id;
-        }
-    }
 
-    match collect_record_or_struct_fields(bcx, m, col) {
-        Some(ref rec_fields) => {
-            let pat_ty = node_id_type(bcx, pat_id);
-            let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
-            expr::with_field_tys(tcx, pat_ty, Some(pat_id), |discr, field_tys| {
-                let rec_vals = rec_fields.iter().map(|field_name| {
-                        let ix = ty::field_idx_strict(tcx, field_name.name, field_tys);
-                        adt::trans_field_ptr(bcx, &*pat_repr, val, discr, ix)
-                        }).collect::<Vec<_>>();
-                compile_submatch(
-                        bcx,
-                        enter_rec_or_struct(bcx,
-                                            dm,
-                                            m,
-                                            col,
-                                            rec_fields.as_slice(),
-                                            val).as_slice(),
-                        rec_vals.append(vals_left.as_slice()).as_slice(),
-                        chk, has_genuine_default);
-            });
-            return;
-        }
-        None => {}
-    }
+    // Find a real id (we're adding placeholder wildcard patterns, but
+    // each column is guaranteed to have at least one real pattern)
+    let pat_id = m.iter().map(|br| br.pats.get(col).id).find(|&id| id != 0).unwrap_or(0);
 
-    if any_tup_pat(m, col) {
-        let tup_ty = node_id_type(bcx, pat_id);
-        let tup_repr = adt::represent_type(bcx.ccx(), tup_ty);
-        let n_tup_elts = match ty::get(tup_ty).sty {
-          ty::ty_tup(ref elts) => elts.len(),
-          _ => ccx.sess().bug("non-tuple type in tuple pattern")
-        };
-        let tup_vals = Vec::from_fn(n_tup_elts, |i| {
-            adt::trans_field_ptr(bcx, &*tup_repr, val, 0, i)
-        });
-        compile_submatch(bcx,
-                         enter_tup(bcx,
-                                   dm,
-                                   m,
-                                   col,
-                                   val,
-                                   n_tup_elts).as_slice(),
-                         tup_vals.append(vals_left.as_slice()).as_slice(),
-                         chk, has_genuine_default);
-        return;
-    }
-
-    if any_tuple_struct_pat(bcx, m, col) {
-        let struct_ty = node_id_type(bcx, pat_id);
-        let struct_element_count;
-        match ty::get(struct_ty).sty {
-            ty::ty_struct(struct_id, _) => {
-                struct_element_count =
-                    ty::lookup_struct_fields(tcx, struct_id).len();
-            }
-            _ => {
-                ccx.sess().bug("non-struct type in tuple struct pattern");
-            }
-        }
-
-        let struct_repr = adt::represent_type(bcx.ccx(), struct_ty);
-        let llstructvals = Vec::from_fn(struct_element_count, |i| {
-            adt::trans_field_ptr(bcx, &*struct_repr, val, 0, i)
-        });
-        compile_submatch(bcx,
-                         enter_tuple_struct(bcx, dm, m, col, val,
-                                            struct_element_count).as_slice(),
-                         llstructvals.append(vals_left.as_slice()).as_slice(),
-                         chk, has_genuine_default);
-        return;
-    }
+    let left_ty = if pat_id == 0 {
+        ty::mk_nil()
+    } else {
+        node_id_type(bcx, pat_id)
+    };
 
-    if any_uniq_pat(m, col) {
-        let llbox = Load(bcx, val);
-        compile_submatch(bcx,
-                         enter_uniq(bcx, dm, m, col, val).as_slice(),
-                         (vec!(llbox)).append(vals_left.as_slice()).as_slice(),
-                         chk, has_genuine_default);
-        return;
-    }
+    let mcx = check_match::MatchCheckCtxt { tcx: bcx.tcx() };
+    let adt_vals = if any_irrefutable_adt_pat(bcx, m, col) {
+        let repr = adt::represent_type(bcx.ccx(), left_ty);
+        let arg_count = adt::num_args(&*repr, 0);
+        let field_vals: Vec<ValueRef> = std::iter::range(0, arg_count).map(|ix|
+            adt::trans_field_ptr(bcx, &*repr, val, 0, ix)
+        ).collect();
+        Some(field_vals)
+    } else if any_uniq_pat(m, col) || any_region_pat(m, col) {
+        Some(vec!(Load(bcx, val)))
+    } else {
+        None
+    };
 
-    if any_region_pat(m, col) {
-        let loaded_val = Load(bcx, val);
-        compile_submatch(bcx,
-                         enter_region(bcx, dm, m, col, val).as_slice(),
-                         (vec!(loaded_val)).append(vals_left.as_slice()).as_slice(),
-                         chk, has_genuine_default);
-        return;
+    match adt_vals {
+        Some(field_vals) => {
+            let pats = enter_match(bcx, dm, m, col, val, |pats|
+                check_match::specialize(&mcx, pats, &check_match::Single, col, field_vals.len())
+            );
+            let vals = field_vals.append(vals_left.as_slice());
+            compile_submatch(bcx, pats.as_slice(), vals.as_slice(), chk, has_genuine_default);
+            return;
+        }
+        _ => ()
     }
 
     // Decide what kind of branch we need
@@ -1582,15 +1148,14 @@ fn compile_submatch_continue<'a, 'b>(
     debug!("test_val={}", bcx.val_to_str(test_val));
     if opts.len() > 0u {
         match *opts.get(0) {
-            var(_, ref repr) => {
+            var(_, ref repr, _) => {
                 let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val);
                 kind = the_kind;
                 for &tval in val_opt.iter() { test_val = tval; }
             }
             lit(_) => {
-                let pty = node_id_type(bcx, pat_id);
-                test_val = load_if_immediate(bcx, val, pty);
-                kind = if ty::type_is_integral(pty) { switch }
+                test_val = load_if_immediate(bcx, val, left_ty);
+                kind = if ty::type_is_integral(left_ty) { switch }
                 else { compare };
             }
             range(_, _) => {
@@ -1598,8 +1163,7 @@ fn compile_submatch_continue<'a, 'b>(
                 kind = compare;
             },
             vec_len(..) => {
-                let vec_ty = node_id_type(bcx, pat_id);
-                let (_, len) = tvec::get_base_and_len(bcx, val, vec_ty);
+                let (_, len) = tvec::get_base_and_len(bcx, val, left_ty);
                 test_val = len;
                 kind = compare_vec_len;
             }
@@ -1652,17 +1216,19 @@ fn compile_submatch_continue<'a, 'b>(
                       }
                   }
               }
-              compare => {
-                  let t = node_id_type(bcx, pat_id);
+              compare | compare_vec_len => {
+                  let t = if kind == compare {
+                      left_ty
+                  } else {
+                      ty::mk_uint() // vector length
+                  };
                   let Result {bcx: after_cx, val: matches} = {
                       match trans_opt(bcx, opt) {
                           single_result(Result {bcx, val}) => {
                               compare_values(bcx, test_val, val, t)
                           }
                           lower_bound(Result {bcx, val}) => {
-                              compare_scalar_types(
-                                  bcx, test_val, val,
-                                  t, ast::BiGe)
+                              compare_scalar_types(bcx, test_val, val, t, ast::BiGe)
                           }
                           range_result(Result {val: vbegin, ..},
                                        Result {bcx, val: vend}) => {
@@ -1686,48 +1252,7 @@ fn compile_submatch_continue<'a, 'b>(
                   // the default.
                   let guarded = m[i].data.arm.guard.is_some();
                   let multi_pats = m[i].pats.len() > 1;
-                  if i+1 < len && (guarded || multi_pats) {
-                      branch_chk = Some(JumpToBasicBlock(bcx.llbb));
-                  }
-                  CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
-              }
-              compare_vec_len => {
-                  let Result {bcx: after_cx, val: matches} = {
-                      match trans_opt(bcx, opt) {
-                          single_result(
-                              Result {bcx, val}) => {
-                              let value = compare_scalar_values(
-                                  bcx, test_val, val,
-                                  signed_int, ast::BiEq);
-                              Result::new(bcx, value)
-                          }
-                          lower_bound(
-                              Result {bcx, val: val}) => {
-                              let value = compare_scalar_values(
-                                  bcx, test_val, val,
-                                  signed_int, ast::BiGe);
-                              Result::new(bcx, value)
-                          }
-                          range_result(
-                              Result {val: vbegin, ..},
-                              Result {bcx, val: vend}) => {
-                              let llge =
-                                  compare_scalar_values(
-                                  bcx, test_val,
-                                  vbegin, signed_int, ast::BiGe);
-                              let llle =
-                                  compare_scalar_values(
-                                  bcx, test_val, vend,
-                                  signed_int, ast::BiLe);
-                              Result::new(bcx, And(bcx, llge, llle))
-                          }
-                      }
-                  };
-                  bcx = fcx.new_temp_block("compare_vec_len_next");
-
-                  // If none of these subcases match, move on to the
-                  // next condition if there is any.
-                  if i+1 < len {
+                  if i + 1 < len && (guarded || multi_pats || kind == compare_vec_len) {
                       branch_chk = Some(JumpToBasicBlock(bcx.llbb));
                   }
                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
@@ -1741,7 +1266,7 @@ fn compile_submatch_continue<'a, 'b>(
         let mut size = 0u;
         let mut unpacked = Vec::new();
         match *opt {
-            var(disr_val, ref repr) => {
+            var(disr_val, ref repr, _) => {
                 let ExtractedBlock {vals: argvals, bcx: new_bcx} =
                     extract_variant_args(opt_cx, &**repr, disr_val, val);
                 size = argvals.len();
@@ -1761,7 +1286,7 @@ fn compile_submatch_continue<'a, 'b>(
             }
             lit(_) | range(_, _) => ()
         }
-        let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
+        let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val);
         let opt_vals = unpacked.append(vals_left.as_slice());
 
         match branch_chk {
@@ -1824,22 +1349,32 @@ fn create_bindings_map(bcx: &Block, pat: Gc<ast::Pat>) -> BindingsMap {
     let ccx = bcx.ccx();
     let tcx = bcx.tcx();
     let mut bindings_map = HashMap::new();
-    pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path| {
-        let ident = path_to_ident(path);
+    pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
+        let ident = path1.node;
         let variable_ty = node_id_type(bcx, p_id);
         let llvariable_ty = type_of::type_of(ccx, variable_ty);
+        let tcx = bcx.tcx();
 
         let llmatch;
         let trmode;
         match bm {
+            ast::BindByValue(_)
+                if !ty::type_moves_by_default(tcx, variable_ty) => {
+                llmatch = alloca(bcx,
+                                 llvariable_ty.ptr_to(),
+                                 "__llmatch");
+                trmode = TrByCopy(alloca(bcx,
+                                         llvariable_ty,
+                                         bcx.ident(ident).as_slice()));
+            }
             ast::BindByValue(_) => {
                 // in this case, the final type of the variable will be T,
                 // but during matching we need to store a *T as explained
                 // above
-                llmatch = alloca(bcx, llvariable_ty.ptr_to(), "__llmatch");
-                trmode = TrByValue(alloca(bcx,
-                                          llvariable_ty,
-                                          bcx.ident(ident).as_slice()));
+                llmatch = alloca(bcx,
+                                 llvariable_ty.ptr_to(),
+                                 bcx.ident(ident).as_slice());
+                trmode = TrByMove;
             }
             ast::BindByRef(_) => {
                 llmatch = alloca(bcx,
@@ -1925,20 +1460,9 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
     for arm_data in arm_datas.iter() {
         let mut bcx = arm_data.bodycx;
 
-        // If this arm has a guard, then the various by-value bindings have
-        // already been copied into their homes.  If not, we do it here.  This
-        // is just to reduce code space.  See extensive comment at the start
-        // of the file for more details.
-        if arm_data.arm.guard.is_none() {
-            bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None);
-        }
-
-        // insert bindings into the lllocals map and add cleanups
-        let cleanup_scope = fcx.push_custom_cleanup_scope();
-        bcx = insert_lllocals(bcx, &arm_data.bindings_map,
-                              cleanup::CustomScope(cleanup_scope));
+        // insert bindings into the lllocals map
+        bcx = insert_lllocals(bcx, &arm_data.bindings_map);
         bcx = expr::trans_into(bcx, &*arm_data.arm.body, dest);
-        bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
         arm_cxs.push(bcx);
     }
 
@@ -1979,10 +1503,10 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
             // In such cases, the more general path is unsafe, because
             // it assumes it is matching against a valid value.
             match simple_identifier(&*pat) {
-                Some(path) => {
+                Some(ident) => {
                     let var_scope = cleanup::var_scope(tcx, local.id);
                     return mk_binding_alloca(
-                        bcx, pat.id, path, BindLocal, var_scope, (),
+                        bcx, pat.id, ident, BindLocal, var_scope, (),
                         |(), bcx, v, _| expr::trans_into(bcx, &*init_expr,
                                                          expr::SaveIn(v)));
                 }
@@ -2014,10 +1538,10 @@ fn create_dummy_locals<'a>(mut bcx: &'a Block<'a>,
         // create dummy memory for the variables if we have no
         // value to store into them immediately
         let tcx = bcx.tcx();
-        pat_bindings(&tcx.def_map, &*pat, |_, p_id, _, path| {
+        pat_bindings(&tcx.def_map, &*pat, |_, p_id, _, path1| {
                 let scope = cleanup::var_scope(tcx, p_id);
                 bcx = mk_binding_alloca(
-                    bcx, p_id, path, BindLocal, scope, (),
+                    bcx, p_id, &path1.node, BindLocal, scope, (),
                     |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
             });
         bcx
@@ -2045,7 +1569,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
     let _icx = push_ctxt("match::store_arg");
 
     match simple_identifier(&*pat) {
-        Some(path) => {
+        Some(ident) => {
             // Generate nicer LLVM for the common case of fn a pattern
             // like `x: T`
             let arg_ty = node_id_type(bcx, pat.id);
@@ -2060,7 +1584,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
                 bcx
             } else {
                 mk_binding_alloca(
-                    bcx, pat.id, path, BindArgument, arg_scope, arg,
+                    bcx, pat.id, ident, BindArgument, arg_scope, arg,
                     |arg, bcx, llval, _| arg.store_to(bcx, llval))
             }
         }
@@ -2078,17 +1602,16 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
 
 fn mk_binding_alloca<'a,A>(bcx: &'a Block<'a>,
                            p_id: ast::NodeId,
-                           path: &ast::Path,
+                           ident: &ast::Ident,
                            binding_mode: IrrefutablePatternBindingMode,
                            cleanup_scope: cleanup::ScopeId,
                            arg: A,
                            populate: |A, &'a Block<'a>, ValueRef, ty::t| -> &'a Block<'a>)
                          -> &'a Block<'a> {
     let var_ty = node_id_type(bcx, p_id);
-    let ident = ast_util::path_to_ident(path);
 
     // Allocate memory on stack for the binding.
-    let llval = alloc_ty(bcx, var_ty, bcx.ident(ident).as_slice());
+    let llval = alloc_ty(bcx, var_ty, bcx.ident(*ident).as_slice());
 
     // Subtle: be sure that we *populate* the memory *before*
     // we schedule the cleanup.
@@ -2146,13 +1669,13 @@ fn bind_irrefutable_pat<'a>(
     let tcx = bcx.tcx();
     let ccx = bcx.ccx();
     match pat.node {
-        ast::PatIdent(pat_binding_mode, ref path, inner) => {
+        ast::PatIdent(pat_binding_mode, ref path1, inner) => {
             if pat_is_binding(&tcx.def_map, &*pat) {
                 // Allocate the stack slot where the value of this
                 // binding will live and place it into the appropriate
                 // map.
                 bcx = mk_binding_alloca(
-                    bcx, pat.id, path, binding_mode, cleanup_scope, (),
+                    bcx, pat.id, &path1.node, binding_mode, cleanup_scope, (),
                     |(), bcx, llval, ty| {
                         match pat_binding_mode {
                             ast::BindByValue(_) => {
index 116b2e6b421b81e41e1c5a94064853528c57897a..0cc4a9223d49963bd0909253711d2f3c3d8fb806 100644 (file)
@@ -261,7 +261,7 @@ pub fn trans_unboxing_shim(bcx: &Block,
     let function_type =
         ty::mk_bare_fn(tcx, method.fty.clone()).subst(tcx, &substs);
 
-    let function_name = tcx.map.with_path(method_id.node, |path| {
+    let function_name = ty::with_path(tcx, method_id, |path| {
         link::mangle_internal_name_by_path_and_seq(path, "unboxing_shim")
     });
     let llfn = decl_internal_rust_fn(ccx,
index 400babb39f82cc12b8dee9be88cee6794947de08..b3c7c0d0fac46e19c278ed001880bf935842e695 100644 (file)
@@ -187,8 +187,8 @@ struct List {
 use middle::subst;
 use middle::trans::adt;
 use middle::trans::common::*;
-use middle::trans::datum::{Datum, Lvalue};
 use middle::trans::machine;
+use middle::trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
 use middle::trans::type_of;
 use middle::trans::type_::Type;
 use middle::trans;
@@ -222,6 +222,13 @@ struct List {
 static DW_ATE_unsigned: c_uint = 0x07;
 static DW_ATE_unsigned_char: c_uint = 0x08;
 
+static UNKNOWN_LINE_NUMBER: c_uint = 0;
+static UNKNOWN_COLUMN_NUMBER: c_uint = 0;
+
+// ptr::null() doesn't work :(
+static UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
+static UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
+
 //=-----------------------------------------------------------------------------
 //  Public Interface of debuginfo module
 //=-----------------------------------------------------------------------------
@@ -330,15 +337,15 @@ fn get_unique_type_id_of_type(&mut self, cx: &CrateContext, type_: ty::t) -> Uni
         unique_type_id.push_char('{');
 
         match ty::get(type_).sty {
-            ty::ty_nil                |
-            ty::ty_bot                |
-            ty::ty_bool               |
-            ty::ty_char               |
-            ty::ty_str                |
-            ty::ty_int(_)             |
-            ty::ty_uint(_)            |
+            ty::ty_nil      |
+            ty::ty_bot      |
+            ty::ty_bool     |
+            ty::ty_char     |
+            ty::ty_str      |
+            ty::ty_int(_)   |
+            ty::ty_uint(_)  |
             ty::ty_float(_) => {
-                unique_type_id.push_str(ppaux::ty_to_str(cx.tcx(), type_).as_slice());
+                push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
             },
             ty::ty_enum(def_id, ref substs) => {
                 unique_type_id.push_str("enum ");
@@ -587,7 +594,7 @@ fn get_unique_type_id_of_heap_vec_box(&mut self,
                                           element_type: ty::t)
                                        -> UniqueTypeId {
         let element_type_id = self.get_unique_type_id_of_type(cx, element_type);
-        let heap_vec_box_type_id = format!("$$HEAP_VEC_BOX<{}>$$",
+        let heap_vec_box_type_id = format!("{{HEAP_VEC_BOX<{}>}}",
                                            self.get_unique_type_id_as_string(element_type_id)
                                                .as_slice());
         let interner_key = self.unique_id_interner.intern(Rc::new(heap_vec_box_type_id));
@@ -599,7 +606,7 @@ fn get_unique_type_id_of_gc_box(&mut self,
                                     element_type: ty::t)
                                  -> UniqueTypeId {
         let element_type_id = self.get_unique_type_id_of_type(cx, element_type);
-        let gc_box_type_id = format!("$$GC_BOX<{}>$$",
+        let gc_box_type_id = format!("{{GC_BOX<{}>}}",
                                      self.get_unique_type_id_as_string(element_type_id)
                                          .as_slice());
         let interner_key = self.unique_id_interner.intern(Rc::new(gc_box_type_id));
@@ -607,6 +614,19 @@ fn get_unique_type_id_of_gc_box(&mut self,
     }
 }
 
+// Returns from the enclosing function if the type metadata with the given
+// unique id can be found in the type map
+macro_rules! return_if_metadata_created_in_meantime(
+    ($cx: expr, $unique_type_id: expr) => (
+        match debug_context($cx).type_map
+                                .borrow()
+                                .find_metadata_for_unique_id($unique_type_id) {
+            Some(metadata) => return MetadataCreationResult::new(metadata, true),
+            None => { /* proceed normally */ }
+        };
+    )
+)
+
 
 /// A context object for maintaining all state needed by the debuginfo module.
 pub struct CrateDebugContext {
@@ -822,8 +842,8 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
     let cx = bcx.ccx();
     let def_map = &cx.tcx.def_map;
 
-    pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path_ref| {
-        let var_ident = ast_util::path_to_ident(path_ref);
+    pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, path1| {
+        let var_ident = path1.node;
 
         let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
             Some(datum) => datum,
@@ -870,8 +890,8 @@ pub fn create_captured_var_metadata(bcx: &Block,
         }
         Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
             match pat.node {
-                ast::PatIdent(_, ref path, _) => {
-                    ast_util::path_to_ident(path)
+                ast::PatIdent(_, ref path1, _) => {
+                    path1.node
                 }
                 _ => {
                     cx.sess()
@@ -938,22 +958,39 @@ pub fn create_captured_var_metadata(bcx: &Block,
 /// Adds the created metadata nodes directly to the crate's IR.
 pub fn create_match_binding_metadata(bcx: &Block,
                                      variable_ident: ast::Ident,
-                                     node_id: ast::NodeId,
-                                     span: Span,
-                                     datum: Datum<Lvalue>) {
+                                     binding: BindingInfo) {
     if fn_should_be_ignored(bcx.fcx) {
         return;
     }
 
-    let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
+    let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span);
+    let aops = unsafe {
+        [llvm::LLVMDIBuilderCreateOpDeref(bcx.ccx().int_type.to_ref())]
+    };
+    // Regardless of the actual type (`T`) we're always passed the stack slot (alloca)
+    // for the binding. For ByRef bindings that's a `T*` but for ByMove bindings we
+    // actually have `T**`. So to get the actual variable we need to dereference once
+    // more. For ByCopy we just use the stack slot we created for the binding.
+    let var_type = match binding.trmode {
+        TrByCopy(llbinding) => DirectVariable {
+            alloca: llbinding
+        },
+        TrByMove => IndirectVariable {
+            alloca: binding.llmatch,
+            address_operations: aops
+        },
+        TrByRef => DirectVariable {
+            alloca: binding.llmatch
+        }
+    };
 
     declare_local(bcx,
                   variable_ident,
-                  datum.ty,
+                  binding.ty,
                   scope_metadata,
-                  DirectVariable { alloca: datum.val },
+                  var_type,
                   LocalVariable,
-                  span);
+                  binding.span);
 }
 
 /// Creates debug information for the given function argument.
@@ -970,7 +1007,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
     let def_map = &cx.tcx.def_map;
     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
 
-    pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path_ref| {
+    pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, path1| {
         let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
             Some(v) => v,
             None => {
@@ -985,8 +1022,6 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
                                     Referenced variable location is not an alloca!");
         }
 
-        let argument_ident = ast_util::path_to_ident(path_ref);
-
         let argument_index = {
             let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
             let argument_index = counter.get();
@@ -995,7 +1030,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
         };
 
         declare_local(bcx,
-                      argument_ident,
+                      path1.node,
                       llarg.ty,
                       scope_metadata,
                       DirectVariable { alloca: llarg.val },
@@ -1304,9 +1339,12 @@ fn get_template_parameters(cx: &CrateContext,
         if has_self_type {
             let actual_self_type = self_type.unwrap();
             // Add self type name to <...> clause of function name
-            let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
-            name_to_append_suffix_to.push_str(
-                actual_self_type_name.as_slice());
+            let actual_self_type_name = compute_debuginfo_type_name(
+                cx,
+                actual_self_type,
+                true);
+
+            name_to_append_suffix_to.push_str(actual_self_type_name.as_slice());
 
             if generics.is_type_parameterized() {
                 name_to_append_suffix_to.push_str(",");
@@ -1343,7 +1381,9 @@ fn get_template_parameters(cx: &CrateContext,
         for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
             let actual_type = *actual_types.get(index);
             // Add actual type name to <...> clause of function name
-            let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
+            let actual_type_name = compute_debuginfo_type_name(cx,
+                                                               actual_type,
+                                                               true);
             name_to_append_suffix_to.push_str(actual_type_name.as_slice());
 
             if index != generics.ty_params.len() - 1 {
@@ -1646,7 +1686,7 @@ fn pointer_type_metadata(cx: &CrateContext,
                       -> DIType {
     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
-    let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
+    let name = compute_debuginfo_type_name(cx, pointer_type, false);
     let ptr_metadata = name.as_slice().with_c_str(|name| {
         unsafe {
             llvm::LLVMDIBuilderCreatePointerType(
@@ -1719,7 +1759,6 @@ enum RecursiveTypeDescription {
         unique_type_id: UniqueTypeId,
         metadata_stub: DICompositeType,
         llvm_type: Type,
-        file_metadata: DIFile,
         member_description_factory: MemberDescriptionFactory,
     },
     FinalMetadata(DICompositeType)
@@ -1731,7 +1770,6 @@ fn create_and_register_recursive_type_forward_declaration(
     unique_type_id: UniqueTypeId,
     metadata_stub: DICompositeType,
     llvm_type: Type,
-    file_metadata: DIFile,
     member_description_factory: MemberDescriptionFactory)
  -> RecursiveTypeDescription {
 
@@ -1745,7 +1783,6 @@ fn create_and_register_recursive_type_forward_declaration(
         unique_type_id: unique_type_id,
         metadata_stub: metadata_stub,
         llvm_type: llvm_type,
-        file_metadata: file_metadata,
         member_description_factory: member_description_factory,
     }
 }
@@ -1761,8 +1798,8 @@ fn finalize(&self, cx: &CrateContext) -> MetadataCreationResult {
                 unique_type_id,
                 metadata_stub,
                 llvm_type,
-                file_metadata,
-                ref member_description_factory
+                ref member_description_factory,
+                ..
             } => {
                 // Make sure that we have a forward declaration of the type in
                 // the TypeMap so that recursive references are possible. This
@@ -1788,9 +1825,7 @@ fn finalize(&self, cx: &CrateContext) -> MetadataCreationResult {
                 set_members_of_composite_type(cx,
                                               metadata_stub,
                                               llvm_type,
-                                              member_descriptions.as_slice(),
-                                              file_metadata,
-                                              codemap::DUMMY_SP);
+                                              member_descriptions.as_slice());
                 return MetadataCreationResult::new(metadata_stub, true);
             }
         }
@@ -1845,6 +1880,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
     }
 }
 
+
 fn prepare_struct_metadata(cx: &CrateContext,
                            struct_type: ty::t,
                            def_id: ast::DefId,
@@ -1852,21 +1888,16 @@ fn prepare_struct_metadata(cx: &CrateContext,
                            unique_type_id: UniqueTypeId,
                            span: Span)
                         -> RecursiveTypeDescription {
-    let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
+    let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
     let struct_llvm_type = type_of::type_of(cx, struct_type);
 
-    let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
-
-    let file_name = span_start(cx, definition_span).file.name.clone();
-    let file_metadata = file_metadata(cx, file_name.as_slice());
+    let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
 
     let struct_metadata_stub = create_struct_stub(cx,
                                                   struct_llvm_type,
                                                   struct_name.as_slice(),
                                                   unique_type_id,
-                                                  containing_scope,
-                                                  file_metadata,
-                                                  definition_span);
+                                                  containing_scope);
 
     let fields = ty::struct_fields(cx.tcx(), def_id, substs);
 
@@ -1876,7 +1907,6 @@ fn prepare_struct_metadata(cx: &CrateContext,
         unique_type_id,
         struct_metadata_stub,
         struct_llvm_type,
-        file_metadata,
         StructMDF(StructMemberDescriptionFactory {
             fields: fields,
             is_simd: ty::type_is_simd(cx.tcx(), struct_type),
@@ -1916,12 +1946,9 @@ fn prepare_tuple_metadata(cx: &CrateContext,
                           unique_type_id: UniqueTypeId,
                           span: Span)
                        -> RecursiveTypeDescription {
-    let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
+    let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
     let tuple_llvm_type = type_of::type_of(cx, tuple_type);
 
-    let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name.as_slice());
-
     create_and_register_recursive_type_forward_declaration(
         cx,
         tuple_type,
@@ -1930,11 +1957,8 @@ fn prepare_tuple_metadata(cx: &CrateContext,
                            tuple_llvm_type,
                            tuple_name.as_slice(),
                            unique_type_id,
-                           file_metadata,
-                           file_metadata,
-                           span),
+                           UNKNOWN_SCOPE_METADATA),
         tuple_llvm_type,
-        file_metadata,
         TupleMDF(TupleMemberDescriptionFactory {
             component_types: Vec::from_slice(component_types),
             span: span,
@@ -1982,7 +2006,6 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                                                   &**self.variants.get(i),
                                                   discriminant_info,
                                                   self.containing_scope,
-                                                  self.file_metadata,
                                                   self.span);
 
                         let member_descriptions = member_desc_factory
@@ -1991,9 +2014,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                         set_members_of_composite_type(cx,
                                                       variant_type_metadata,
                                                       variant_llvm_type,
-                                                      member_descriptions.as_slice(),
-                                                      self.file_metadata,
-                                                      codemap::DUMMY_SP);
+                                                      member_descriptions.as_slice());
                         MemberDescription {
                             name: "".to_string(),
                             llvm_type: variant_llvm_type,
@@ -2017,7 +2038,6 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                                               &**self.variants.get(0),
                                               NoDiscriminant,
                                               self.containing_scope,
-                                              self.file_metadata,
                                               self.span);
 
                     let member_descriptions =
@@ -2026,9 +2046,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                     set_members_of_composite_type(cx,
                                                   variant_type_metadata,
                                                   variant_llvm_type,
-                                                  member_descriptions.as_slice(),
-                                                  self.file_metadata,
-                                                  codemap::DUMMY_SP);
+                                                  member_descriptions.as_slice());
                     vec![
                         MemberDescription {
                             name: "".to_string(),
@@ -2119,7 +2137,6 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                                           &**self.variants.get(nndiscr as uint),
                                           OptimizedDiscriminant(ptrfield),
                                           self.containing_scope,
-                                          self.file_metadata,
                                           self.span);
 
                 let variant_member_descriptions =
@@ -2128,9 +2145,7 @@ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription
                 set_members_of_composite_type(cx,
                                               variant_type_metadata,
                                               variant_llvm_type,
-                                              variant_member_descriptions.as_slice(),
-                                              self.file_metadata,
-                                              codemap::DUMMY_SP);
+                                              variant_member_descriptions.as_slice());
 
                 // Encode the information about the null variant in the union
                 // member's name.
@@ -2195,7 +2210,6 @@ fn describe_enum_variant(cx: &CrateContext,
                          variant_info: &ty::VariantInfo,
                          discriminant_info: EnumDiscriminantInfo,
                          containing_scope: DIScope,
-                         file_metadata: DIFile,
                          span: Span)
                       -> (DICompositeType, Type, MemberDescriptionFactory) {
     let variant_llvm_type =
@@ -2207,14 +2221,6 @@ fn describe_enum_variant(cx: &CrateContext,
                       struct_def.packed);
     // Could do some consistency checks here: size, align, field count, discr type
 
-    // Find the source code location of the variant's definition
-    let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
-        cx.tcx.map.span(variant_info.id.node)
-    } else {
-        // For definitions from other crates we have no location information available.
-        codemap::DUMMY_SP
-    };
-
     let variant_name = token::get_ident(variant_info.name);
     let variant_name = variant_name.get();
     let unique_type_id = debug_context(cx).type_map
@@ -2228,9 +2234,7 @@ fn describe_enum_variant(cx: &CrateContext,
                                            variant_llvm_type,
                                            variant_name,
                                            unique_type_id,
-                                           containing_scope,
-                                           file_metadata,
-                                           variant_definition_span);
+                                           containing_scope);
 
     // Get the argument names from the enum variant info
     let mut arg_names: Vec<_> = match variant_info.arg_names {
@@ -2276,7 +2280,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                          unique_type_id: UniqueTypeId,
                          span: Span)
                       -> RecursiveTypeDescription {
-    let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
+    let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
 
     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
     let loc = span_start(cx, definition_span);
@@ -2323,8 +2327,8 @@ fn prepare_enum_metadata(cx: &CrateContext,
                             DIB(cx),
                             containing_scope,
                             name,
-                            file_metadata,
-                            loc.line as c_uint,
+                            UNKNOWN_FILE_METADATA,
+                            UNKNOWN_LINE_NUMBER,
                             bytes_to_bits(discriminant_size),
                             bytes_to_bits(discriminant_align),
                             create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
@@ -2368,8 +2372,8 @@ fn prepare_enum_metadata(cx: &CrateContext,
                 DIB(cx),
                 containing_scope,
                 enum_name,
-                file_metadata,
-                loc.line as c_uint,
+                UNKNOWN_FILE_METADATA,
+                UNKNOWN_LINE_NUMBER,
                 bytes_to_bits(enum_type_size),
                 bytes_to_bits(enum_type_align),
                 0, // Flags
@@ -2386,7 +2390,6 @@ fn prepare_enum_metadata(cx: &CrateContext,
         unique_type_id,
         enum_metadata,
         enum_llvm_type,
-        file_metadata,
         EnumMDF(EnumMemberDescriptionFactory {
             enum_type: enum_type,
             type_rep: type_rep.clone(),
@@ -2421,24 +2424,23 @@ fn composite_type_metadata(cx: &CrateContext,
                            composite_type_unique_id: UniqueTypeId,
                            member_descriptions: &[MemberDescription],
                            containing_scope: DIScope,
-                           file_metadata: DIFile,
-                           definition_span: Span)
+
+                           // Ignore source location information as long as it
+                           // can't be reconstructed for non-local crates.
+                           _file_metadata: DIFile,
+                           _definition_span: Span)
                         -> DICompositeType {
     // Create the (empty) struct metadata node ...
     let composite_type_metadata = create_struct_stub(cx,
                                                      composite_llvm_type,
                                                      composite_type_name,
                                                      composite_type_unique_id,
-                                                     containing_scope,
-                                                     file_metadata,
-                                                     definition_span);
+                                                     containing_scope);
     // ... and immediately create and add the member descriptions.
     set_members_of_composite_type(cx,
                                   composite_type_metadata,
                                   composite_llvm_type,
-                                  member_descriptions,
-                                  file_metadata,
-                                  definition_span);
+                                  member_descriptions);
 
     return composite_type_metadata;
 }
@@ -2446,9 +2448,7 @@ fn composite_type_metadata(cx: &CrateContext,
 fn set_members_of_composite_type(cx: &CrateContext,
                                  composite_type_metadata: DICompositeType,
                                  composite_llvm_type: Type,
-                                 member_descriptions: &[MemberDescription],
-                                 file_metadata: DIFile,
-                                 definition_span: Span) {
+                                 member_descriptions: &[MemberDescription]) {
     // In some rare cases LLVM metadata uniquing would lead to an existing type
     // description being used instead of a new one created in create_struct_stub.
     // This would cause a hard to trace assertion in DICompositeType::SetTypeArray().
@@ -2483,8 +2483,6 @@ fn set_members_of_composite_type(cx: &CrateContext,
         }
     }
 
-    let loc = span_start(cx, definition_span);
-
     let member_metadata: Vec<DIDescriptor> = member_descriptions
         .iter()
         .enumerate()
@@ -2501,8 +2499,8 @@ fn set_members_of_composite_type(cx: &CrateContext,
                         DIB(cx),
                         composite_type_metadata,
                         member_name,
-                        file_metadata,
-                        loc.line as c_uint,
+                        UNKNOWN_FILE_METADATA,
+                        UNKNOWN_LINE_NUMBER,
                         bytes_to_bits(member_size),
                         bytes_to_bits(member_align),
                         bytes_to_bits(member_offset),
@@ -2526,11 +2524,8 @@ fn create_struct_stub(cx: &CrateContext,
                       struct_llvm_type: Type,
                       struct_type_name: &str,
                       unique_type_id: UniqueTypeId,
-                      containing_scope: DIScope,
-                      file_metadata: DIFile,
-                      definition_span: Span)
+                      containing_scope: DIScope)
                    -> DICompositeType {
-    let loc = span_start(cx, definition_span);
     let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
 
     let unique_type_id_str = debug_context(cx).type_map
@@ -2548,8 +2543,8 @@ fn create_struct_stub(cx: &CrateContext,
                     DIB(cx),
                     containing_scope,
                     name,
-                    file_metadata,
-                    loc.line as c_uint,
+                    UNKNOWN_FILE_METADATA,
+                    UNKNOWN_LINE_NUMBER,
                     bytes_to_bits(struct_size),
                     bytes_to_bits(struct_align),
                     0,
@@ -2572,12 +2567,9 @@ fn at_box_metadata(cx: &CrateContext,
                 -> MetadataCreationResult {
     let content_type_metadata = type_metadata(cx, content_type, codemap::DUMMY_SP);
 
-    match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
-        Some(metadata) => return MetadataCreationResult::new(metadata, true),
-        None => { /* proceed */ }
-    };
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
 
-    let content_type_name = ppaux::ty_to_str(cx.tcx(), content_type);
+    let content_type_name = compute_debuginfo_type_name(cx, content_type, true);
     let content_type_name = content_type_name.as_slice();
     let content_llvm_type = type_of::type_of(cx, content_type);
 
@@ -2593,7 +2585,6 @@ fn at_box_metadata(cx: &CrateContext,
     let nil_pointer_type_metadata = type_metadata(cx,
                                                   nil_pointer_type,
                                                   codemap::DUMMY_SP);
-
     let member_descriptions = [
         MemberDescription {
             name: "refcnt".to_string(),
@@ -2627,9 +2618,6 @@ fn at_box_metadata(cx: &CrateContext,
         }
     ];
 
-    let loc = span_start(cx, codemap::DUMMY_SP);
-    let file_metadata = file_metadata(cx, loc.file.name.as_slice());
-
     let gc_box_unique_id = debug_context(cx).type_map
                                             .borrow_mut()
                                             .get_unique_type_id_of_gc_box(cx, content_type);
@@ -2640,8 +2628,8 @@ fn at_box_metadata(cx: &CrateContext,
         box_type_name.as_slice(),
         gc_box_unique_id,
         member_descriptions,
-        file_metadata,
-        file_metadata,
+        UNKNOWN_SCOPE_METADATA,
+        UNKNOWN_FILE_METADATA,
         codemap::DUMMY_SP);
 
     let gc_pointer_metadata = pointer_type_metadata(cx,
@@ -2674,10 +2662,7 @@ fn fixed_vec_metadata(cx: &CrateContext,
                    -> MetadataCreationResult {
     let element_type_metadata = type_metadata(cx, element_type, span);
 
-    match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
-        Some(metadata) => return MetadataCreationResult::new(metadata, true),
-        None => { /* proceed */ }
-    };
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
 
     let element_llvm_type = type_of::type_of(cx, element_type);
     let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
@@ -2712,13 +2697,12 @@ fn heap_vec_metadata(cx: &CrateContext,
     let element_llvm_type = type_of::type_of(cx, element_type);
     let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
 
-    match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
-        Some(metadata) => return MetadataCreationResult::new(metadata, true),
-        None => { /* proceed */ }
-    };
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
 
     let vecbox_llvm_type = Type::vec(cx, &element_llvm_type);
-    let vec_pointer_type_name = ppaux::ty_to_str(cx.tcx(), vec_pointer_type);
+    let vec_pointer_type_name = compute_debuginfo_type_name(cx,
+                                                            vec_pointer_type,
+                                                            true);
     let vec_pointer_type_name = vec_pointer_type_name.as_slice();
 
     let member_llvm_types = vecbox_llvm_type.field_types();
@@ -2769,7 +2753,7 @@ fn heap_vec_metadata(cx: &CrateContext,
                                                   vec_pointer_type_name,
                                                   vec_box_unique_id,
                                                   member_descriptions,
-                                                  file_metadata,
+                                                  UNKNOWN_SCOPE_METADATA,
                                                   file_metadata,
                                                   span);
 
@@ -2791,13 +2775,10 @@ fn vec_slice_metadata(cx: &CrateContext,
 
     let element_type_metadata = type_metadata(cx, data_ptr_type, span);
 
-    match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
-        Some(metadata) => return MetadataCreationResult::new(metadata, true),
-        None => { /* proceed */ }
-    };
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
 
     let slice_llvm_type = type_of::type_of(cx, vec_type);
-    let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
+    let slice_type_name = compute_debuginfo_type_name(cx, vec_type, true);
 
     let member_llvm_types = slice_llvm_type.field_types();
     assert!(slice_layout_is_correct(cx,
@@ -2828,7 +2809,7 @@ fn vec_slice_metadata(cx: &CrateContext,
                                            slice_type_name.as_slice(),
                                            unique_type_id,
                                            member_descriptions,
-                                           file_metadata,
+                                           UNKNOWN_SCOPE_METADATA,
                                            file_metadata,
                                            span);
     return MetadataCreationResult::new(metadata, false);
@@ -2848,8 +2829,6 @@ fn subroutine_type_metadata(cx: &CrateContext,
                             signature: &ty::FnSig,
                             span: Span)
                          -> MetadataCreationResult {
-    let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name.as_slice());
     let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
 
     // return type
@@ -2863,57 +2842,64 @@ fn subroutine_type_metadata(cx: &CrateContext,
         signature_metadata.push(type_metadata(cx, argument_type, span));
     }
 
-    match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
-        Some(metadata) => return MetadataCreationResult::new(metadata, true),
-        None => { /* proceed */ }
-    };
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
 
     return MetadataCreationResult::new(
         unsafe {
             llvm::LLVMDIBuilderCreateSubroutineType(
                 DIB(cx),
-                file_metadata,
+                UNKNOWN_FILE_METADATA,
                 create_DIArray(DIB(cx), signature_metadata.as_slice()))
         },
         false);
 }
 
-fn trait_metadata(cx: &CrateContext,
-                  def_id: ast::DefId,
-                  trait_type: ty::t,
-                  substs: &subst::Substs,
-                  trait_store: ty::TraitStore,
-                  _: &ty::BuiltinBounds,
-                  unique_type_id: UniqueTypeId)
-               -> DIType {
+fn trait_pointer_metadata(cx: &CrateContext,
+                          // trait_pointer_type must be the type of the fat
+                          // pointer to the concrete trait object
+                          trait_pointer_type: ty::t,
+                          unique_type_id: UniqueTypeId)
+                       -> DIType {
     // The implementation provided here is a stub. It makes sure that the trait
     // type is assigned the correct name, size, namespace, and source location.
     // But it does not describe the trait's methods.
-    let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
-    let ident_string = token::get_name(last.name());
-    let mut name = ppaux::trait_store_to_str(cx.tcx(), trait_store);
-    name.push_str(ident_string.get());
 
-    // Add type and region parameters
-    let trait_def = ty::lookup_trait_def(cx.tcx(), def_id);
-    let name = ppaux::parameterized(cx.tcx(), name.as_slice(),
-                                    substs, &trait_def.generics);
+    let trait_object_type = match ty::get(trait_pointer_type).sty {
+        ty::ty_uniq(pointee_type) => pointee_type,
+        ty::ty_rptr(_, ty::mt { ty, .. }) => ty,
+        _ => {
+            let pp_type_name = ppaux::ty_to_str(cx.tcx(), trait_pointer_type);
+            cx.sess().bug(format!("debuginfo: Unexpected trait-pointer type in \
+                                   trait_pointer_metadata(): {}",
+                                   pp_type_name.as_slice()).as_slice());
+        }
+    };
+
+    let def_id = match ty::get(trait_object_type).sty {
+        ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id,
+        _ => {
+            let pp_type_name = ppaux::ty_to_str(cx.tcx(), trait_object_type);
+            cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \
+                                   trait_pointer_metadata(): {}",
+                                   pp_type_name.as_slice()).as_slice());
+        }
+    };
 
-    let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
+    let trait_pointer_type_name =
+        compute_debuginfo_type_name(cx, trait_pointer_type, false);
 
-    let file_name = span_start(cx, definition_span).file.name.clone();
-    let file_metadata = file_metadata(cx, file_name.as_slice());
+    let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
 
-    let trait_llvm_type = type_of::type_of(cx, trait_type);
+    let trait_pointer_llvm_type = type_of::type_of(cx, trait_pointer_type);
 
     composite_type_metadata(cx,
-                            trait_llvm_type,
-                            name.as_slice(),
+                            trait_pointer_llvm_type,
+                            trait_pointer_type_name.as_slice(),
                             unique_type_id,
                             [],
                             containing_scope,
-                            file_metadata,
-                            definition_span)
+                            UNKNOWN_FILE_METADATA,
+                            codemap::DUMMY_SP)
 }
 
 fn type_metadata(cx: &CrateContext,
@@ -2955,15 +2941,6 @@ fn type_metadata(cx: &CrateContext,
 
     debug!("type_metadata: {:?}", ty::get(t));
 
-    macro_rules! return_if_created_in_meantime(
-        () => (
-            match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) {
-                Some(metadata) => return metadata,
-                None => { /* proceed normally */ }
-            };
-        )
-    )
-
     let sty = &ty::get(t).sty;
     let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
         ty::ty_nil      |
@@ -2993,19 +2970,22 @@ macro_rules! return_if_created_in_meantime(
                     let i8_t = ty::mk_i8();
                     heap_vec_metadata(cx, pointee_type, i8_t, unique_type_id, usage_site_span)
                 }
-                ty::ty_trait(box ty::TyTrait {
-                        def_id,
-                        ref substs,
-                        ref bounds
-                    }) => {
+                ty::ty_trait(..) => {
                     MetadataCreationResult::new(
-                        trait_metadata(cx, def_id, t, substs, ty::UniqTraitStore,
-                                       bounds, unique_type_id),
-                    false)
+                        trait_pointer_metadata(cx, t, unique_type_id),
+                        false)
                 }
                 _ => {
-                    let pointee_metadata = type_metadata(cx, pointee_type, usage_site_span);
-                    return_if_created_in_meantime!();
+                    let pointee_metadata = type_metadata(cx,
+                                                         pointee_type,
+                                                         usage_site_span);
+                    match debug_context(cx).type_map
+                                           .borrow()
+                                           .find_metadata_for_unique_id(unique_type_id) {
+                        Some(metadata) => return metadata,
+                        None => { /* proceed normally */ }
+                    };
+
                     MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
                                                 false)
                 }
@@ -3017,22 +2997,23 @@ macro_rules! return_if_created_in_meantime(
                     vec_slice_metadata(cx, t, mt.ty, unique_type_id, usage_site_span)
                 }
                 ty::ty_str => {
-                    vec_slice_metadata(cx, t, ty::mk_i8(), unique_type_id, usage_site_span)
+                    vec_slice_metadata(cx, t, ty::mk_u8(), unique_type_id, usage_site_span)
                 }
-                ty::ty_trait(box ty::TyTrait {
-                        def_id,
-                        ref substs,
-                        ref bounds
-                    }) => {
+                ty::ty_trait(..) => {
                     MetadataCreationResult::new(
-                        trait_metadata(cx, def_id, t, substs,
-                                       ty::RegionTraitStore(ty::ReStatic, mt.mutbl),
-                                       bounds, unique_type_id),
-                    false)
+                        trait_pointer_metadata(cx, t, unique_type_id),
+                        false)
                 }
                 _ => {
                     let pointee = type_metadata(cx, mt.ty, usage_site_span);
-                    return_if_created_in_meantime!();
+
+                    match debug_context(cx).type_map
+                                           .borrow()
+                                           .find_metadata_for_unique_id(unique_type_id) {
+                        Some(metadata) => return metadata,
+                        None => { /* proceed normally */ }
+                    };
+
                     MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee), false)
                 }
             }
@@ -3150,7 +3131,8 @@ fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
 
     match debug_location {
         KnownLocation { scope, line, .. } => {
-            let col = 0u; // Always set the column to zero like Clang and GCC
+            // Always set the column to zero like Clang and GCC
+            let col = UNKNOWN_COLUMN_NUMBER;
             debug!("setting debug location to {} {}", line, col);
             let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32),
                             scope, ptr::mut_null()];
@@ -3253,10 +3235,9 @@ struct ScopeStackEntry {
     // Push argument identifiers onto the stack so arguments integrate nicely
     // with variable shadowing.
     for &arg_pat in arg_pats.iter() {
-        pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path_ref| {
-            let ident = ast_util::path_to_ident(path_ref);
+        pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path1| {
             scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
-                                               ident: Some(ident) });
+                                               ident: Some(path1.node) });
         })
     }
 
@@ -3364,13 +3345,13 @@ fn walk_pattern(cx: &CrateContext,
         // ast_util::walk_pat() here because we have to visit *all* nodes in
         // order to put them into the scope map. The above functions don't do that.
         match pat.node {
-            ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
+            ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
 
                 // Check if this is a binding. If so we need to put it on the
                 // scope stack and maybe introduce an artificial scope
                 if pat_util::pat_is_binding(def_map, &*pat) {
 
-                    let ident = ast_util::path_to_ident(path_ref);
+                    let ident = path1.node;
 
                     // LLVM does not properly generate 'DW_AT_start_scope' fields
                     // for variable DIEs. For this reason we have to introduce
@@ -3700,6 +3681,265 @@ fn walk_expr(cx: &CrateContext,
 }
 
 
+//=-----------------------------------------------------------------------------
+// Type Names for Debug Info
+//=-----------------------------------------------------------------------------
+
+// Compute the name of the type as it should be stored in debuginfo. Does not do
+// any caching, i.e. calling the function twice with the same type will also do
+// the work twice. The `qualified` parameter only affects the first level of the
+// type name, further levels (i.e. type parameters) are always fully qualified.
+fn compute_debuginfo_type_name(cx: &CrateContext,
+                               t: ty::t,
+                               qualified: bool)
+                            -> String {
+    let mut result = String::with_capacity(64);
+    push_debuginfo_type_name(cx, t, qualified, &mut result);
+    result
+}
+
+// Pushes the name of the type as it should be stored in debuginfo on the
+// `output` String. See also compute_debuginfo_type_name().
+fn push_debuginfo_type_name(cx: &CrateContext,
+                            t: ty::t,
+                            qualified: bool,
+                            output:&mut String) {
+    match ty::get(t).sty {
+        ty::ty_nil               => output.push_str("()"),
+        ty::ty_bot               => output.push_str("!"),
+        ty::ty_bool              => output.push_str("bool"),
+        ty::ty_char              => output.push_str("char"),
+        ty::ty_str               => output.push_str("str"),
+        ty::ty_int(ast::TyI)     => output.push_str("int"),
+        ty::ty_int(ast::TyI8)    => output.push_str("i8"),
+        ty::ty_int(ast::TyI16)   => output.push_str("i16"),
+        ty::ty_int(ast::TyI32)   => output.push_str("i32"),
+        ty::ty_int(ast::TyI64)   => output.push_str("i64"),
+        ty::ty_uint(ast::TyU)    => output.push_str("uint"),
+        ty::ty_uint(ast::TyU8)   => output.push_str("u8"),
+        ty::ty_uint(ast::TyU16)  => output.push_str("u16"),
+        ty::ty_uint(ast::TyU32)  => output.push_str("u32"),
+        ty::ty_uint(ast::TyU64)  => output.push_str("u64"),
+        ty::ty_float(ast::TyF32) => output.push_str("f32"),
+        ty::ty_float(ast::TyF64) => output.push_str("f64"),
+        ty::ty_struct(def_id, ref substs) |
+        ty::ty_enum(def_id, ref substs) => {
+            push_item_name(cx, def_id, qualified, output);
+            push_type_params(cx, substs, output);
+        },
+        ty::ty_tup(ref component_types) => {
+            output.push_char('(');
+            for &component_type in component_types.iter() {
+                push_debuginfo_type_name(cx, component_type, true, output);
+                output.push_str(", ");
+            }
+            output.pop_char();
+            output.pop_char();
+            output.push_char(')');
+        },
+        ty::ty_uniq(inner_type) => {
+            output.push_str("Box<");
+            push_debuginfo_type_name(cx, inner_type, true, output);
+            output.push_char('>');
+        },
+        ty::ty_box(inner_type) => {
+            output.push_char('@');
+            push_debuginfo_type_name(cx, inner_type, true, output);
+        },
+        ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
+            output.push_char('*');
+            match mutbl {
+                ast::MutImmutable => output.push_str("const "),
+                ast::MutMutable => output.push_str("mut "),
+            }
+
+            push_debuginfo_type_name(cx, inner_type, true, output);
+        },
+        ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
+            output.push_char('&');
+            if mutbl == ast::MutMutable {
+                output.push_str("mut ");
+            }
+
+            push_debuginfo_type_name(cx, inner_type, true, output);
+        },
+        ty::ty_vec(ty::mt { ty: inner_type, .. }, optional_length) => {
+            output.push_char('[');
+            push_debuginfo_type_name(cx, inner_type, true, output);
+
+            match optional_length {
+                Some(len) => {
+                    output.push_str(format!(", ..{}", len).as_slice());
+                }
+                None => { /* nothing to do */ }
+            };
+
+            output.push_char(']');
+        },
+        ty::ty_trait(ref trait_data) => {
+            push_item_name(cx, trait_data.def_id, false, output);
+            push_type_params(cx, &trait_data.substs, output);
+        },
+        ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => {
+            if fn_style == ast::UnsafeFn {
+                output.push_str("unsafe ");
+            }
+
+            if abi != ::syntax::abi::Rust {
+                output.push_str("extern \"");
+                output.push_str(abi.name());
+                output.push_str("\" ");
+            }
+
+            output.push_str("fn(");
+
+            if sig.inputs.len() > 0 {
+                for &parameter_type in sig.inputs.iter() {
+                    push_debuginfo_type_name(cx, parameter_type, true, output);
+                    output.push_str(", ");
+                }
+                output.pop_char();
+                output.pop_char();
+            }
+
+            if sig.variadic {
+                if sig.inputs.len() > 0 {
+                    output.push_str(", ...");
+                } else {
+                    output.push_str("...");
+                }
+            }
+
+            output.push_char(')');
+
+            if !ty::type_is_nil(sig.output) {
+                output.push_str(" -> ");
+                push_debuginfo_type_name(cx, sig.output, true, output);
+            }
+        },
+        ty::ty_closure(box ty::ClosureTy { fn_style,
+                                           onceness,
+                                           store,
+                                           ref sig,
+                                           .. // omitting bounds ...
+                                           }) => {
+            if fn_style == ast::UnsafeFn {
+                output.push_str("unsafe ");
+            }
+
+            if onceness == ast::Once {
+                output.push_str("once ");
+            }
+
+            let param_list_closing_char;
+            match store {
+                ty::UniqTraitStore => {
+                    output.push_str("proc(");
+                    param_list_closing_char = ')';
+                }
+                ty::RegionTraitStore(_, ast::MutMutable) => {
+                    output.push_str("&mut|");
+                    param_list_closing_char = '|';
+                }
+                ty::RegionTraitStore(_, ast::MutImmutable) => {
+                    output.push_str("&|");
+                    param_list_closing_char = '|';
+                }
+            };
+
+            if sig.inputs.len() > 0 {
+                for &parameter_type in sig.inputs.iter() {
+                    push_debuginfo_type_name(cx, parameter_type, true, output);
+                    output.push_str(", ");
+                }
+                output.pop_char();
+                output.pop_char();
+            }
+
+            if sig.variadic {
+                if sig.inputs.len() > 0 {
+                    output.push_str(", ...");
+                } else {
+                    output.push_str("...");
+                }
+            }
+
+            output.push_char(param_list_closing_char);
+
+            if !ty::type_is_nil(sig.output) {
+                output.push_str(" -> ");
+                push_debuginfo_type_name(cx, sig.output, true, output);
+            }
+        },
+        ty::ty_err      |
+        ty::ty_infer(_) |
+        ty::ty_param(_) => {
+            cx.sess().bug(format!("debuginfo: Trying to create type name for \
+                unexpected type: {}", ppaux::ty_to_str(cx.tcx(), t)).as_slice());
+        }
+    }
+
+    fn push_item_name(cx: &CrateContext,
+                      def_id: ast::DefId,
+                      qualified: bool,
+                      output: &mut String) {
+        ty::with_path(cx.tcx(), def_id, |mut path| {
+            if qualified {
+                if def_id.krate == ast::LOCAL_CRATE {
+                    output.push_str(crate_root_namespace(cx));
+                    output.push_str("::");
+                }
+
+                let mut path_element_count = 0u;
+                for path_element in path {
+                    let name = token::get_name(path_element.name());
+                    output.push_str(name.get());
+                    output.push_str("::");
+                    path_element_count += 1;
+                }
+
+                if path_element_count == 0 {
+                    cx.sess().bug("debuginfo: Encountered empty item path!");
+                }
+
+                output.pop_char();
+                output.pop_char();
+            } else {
+                let name = token::get_name(path.last()
+                                               .expect("debuginfo: Empty item path?")
+                                               .name());
+                output.push_str(name.get());
+            }
+        });
+    }
+
+    // Pushes the type parameters in the given `Substs` to the output string.
+    // This ignores region parameters, since they can't reliably be
+    // reconstructed for items from non-local crates. For local crates, this
+    // would be possible but with inlining and LTO we have to use the least
+    // common denominator - otherwise we would run into conflicts.
+    fn push_type_params(cx: &CrateContext,
+                        substs: &subst::Substs,
+                        output: &mut String) {
+        if substs.types.is_empty() {
+            return;
+        }
+
+        output.push_char('<');
+
+        for &type_parameter in substs.types.iter() {
+            push_debuginfo_type_name(cx, type_parameter, true, output);
+            output.push_str(", ");
+        }
+
+        output.pop_char();
+        output.pop_char();
+
+        output.push_char('>');
+    }
+}
+
+
 //=-----------------------------------------------------------------------------
 // Namespace Handling
 //=-----------------------------------------------------------------------------
@@ -3731,14 +3971,15 @@ fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
     }
 }
 
+fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
+    cx.link_meta.crateid.name.as_slice()
+}
+
 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
     ty::with_path(cx.tcx(), def_id, |path| {
         // prepend crate name if not already present
         let krate = if def_id.krate == ast::LOCAL_CRATE {
-            let crate_namespace_ident = token::str_to_ident(cx.link_meta
-                                                              .crateid
-                                                              .name
-                                                              .as_slice());
+            let crate_namespace_ident = token::str_to_ident(crate_root_namespace(cx));
             Some(ast_map::PathMod(crate_namespace_ident.name))
         } else {
             None
index 79630be7c5e0840c21dfdf99228ed5bbede7f7ac..9629fb38af80fb62cf58726d520725b139aba143 100644 (file)
@@ -2771,8 +2771,8 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
     match cx.map.find(id) {
         Some(ast_map::NodeLocal(pat)) => {
             match pat.node {
-                ast::PatIdent(_, ref path, _) => {
-                    token::get_ident(ast_util::path_to_ident(path))
+                ast::PatIdent(_, ref path1, _) => {
+                    token::get_ident(path1.node)
                 }
                 _ => {
                     cx.sess.bug(
index 60ce9508dc46b3422eb7dc34e4c5def15d0b4297..697c5d367ee5a51ab3a65cd2a6945de0d3ae5db6 100644 (file)
@@ -485,7 +485,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         demand::suptype(fcx, pat.span, expected, const_pty.ty);
         fcx.write_ty(pat.id, const_pty.ty);
       }
-      ast::PatIdent(bm, ref name, sub) if pat_is_binding(&tcx.def_map, pat) => {
+      ast::PatIdent(bm, ref path1, sub) if pat_is_binding(&tcx.def_map, pat) => {
         let typ = fcx.local_ty(pat.span, pat.id);
 
         match bm {
@@ -507,7 +507,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
           }
         }
 
-        let canon_id = *pcx.map.get(&ast_util::path_to_ident(name));
+        let canon_id = *pcx.map.get(&path1.node);
         if canon_id != pat.id {
             let ct = fcx.local_ty(pat.span, canon_id);
             demand::eqtype(fcx, pat.span, ct, typ);
@@ -521,8 +521,10 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
           _ => ()
         }
       }
-      ast::PatIdent(_, ref path, _) => {
-        check_pat_variant(pcx, pat, path, &Some(Vec::new()), expected);
+      // it's not a binding, it's an enum in disguise:
+      ast::PatIdent(_, ref path1, _) => {
+        let path = ast_util::ident_to_path(path1.span,path1.node);
+        check_pat_variant(pcx, pat, &path, &Some(Vec::new()), expected);
       }
       ast::PatEnum(ref path, ref subpats) => {
         check_pat_variant(pcx, pat, path, subpats, expected);
index 5e675242688afc435f02b86f6bbdf33bac92d93d..b68991aed70963c53c341788689c4f11e1652a7a 100644 (file)
@@ -406,11 +406,11 @@ fn visit_local(&mut self, local: &ast::Local, _: ()) {
     // Add pattern bindings.
     fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
             match p.node {
-              ast::PatIdent(_, ref path, _)
+              ast::PatIdent(_, ref path1, _)
                   if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
                 self.assign(p.id, None);
                 debug!("Pattern binding {} is assigned to {}",
-                       token::get_ident(path.segments.get(0).identifier),
+                       token::get_ident(path1.node),
                        self.fcx.infcx().ty_to_str(
                            self.fcx.inh.locals.borrow().get_copy(&p.id)));
               }
@@ -920,49 +920,6 @@ fn compare_impl_method(tcx: &ty::ctxt,
     let it = trait_m.generics.types.get_vec(subst::FnSpace).iter()
         .zip(impl_m.generics.types.get_vec(subst::FnSpace).iter());
 
-    for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
-        // Check that the impl does not require any builtin-bounds
-        // that the trait does not guarantee:
-        let extra_bounds =
-            impl_param_def.bounds.builtin_bounds -
-            trait_param_def.bounds.builtin_bounds;
-        if !extra_bounds.is_empty() {
-           tcx.sess.span_err(
-               impl_m_span,
-               format!("in method `{}`, \
-                       type parameter {} requires `{}`, \
-                       which is not required by \
-                       the corresponding type parameter \
-                       in the trait declaration",
-                       token::get_ident(trait_m.ident),
-                       i,
-                       extra_bounds.user_string(tcx)).as_slice());
-           return;
-        }
-
-        // FIXME(#2687)---we should be checking that the bounds of the
-        // trait imply the bounds of the subtype, but it appears we
-        // are...not checking this.
-        if impl_param_def.bounds.trait_bounds.len() !=
-            trait_param_def.bounds.trait_bounds.len()
-        {
-            let found = impl_param_def.bounds.trait_bounds.len();
-            let expected =  trait_param_def.bounds.trait_bounds.len();
-            tcx.sess.span_err(
-                impl_m_span,
-                format!("in method `{}`, type parameter {} has {} trait \
-                         bound{}, but the corresponding type parameter in \
-                         the trait declaration has {} trait bound{}",
-                        token::get_ident(trait_m.ident),
-                        i,
-                        found,
-                        if found == 1 {""} else {"s"},
-                        expected,
-                        if expected == 1 {""} else {"s"}).as_slice());
-            return;
-        }
-    }
-
     // This code is best explained by example. Consider a trait:
     //
     //     trait Trait<T> {
@@ -1037,6 +994,70 @@ fn compare_impl_method(tcx: &ty::ctxt,
     let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
+    // Check bounds.
+    for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
+        // Check that the impl does not require any builtin-bounds
+        // that the trait does not guarantee:
+        let extra_bounds =
+            impl_param_def.bounds.builtin_bounds -
+            trait_param_def.bounds.builtin_bounds;
+        if !extra_bounds.is_empty() {
+           tcx.sess.span_err(
+               impl_m_span,
+               format!("in method `{}`, \
+                       type parameter {} requires `{}`, \
+                       which is not required by \
+                       the corresponding type parameter \
+                       in the trait declaration",
+                       token::get_ident(trait_m.ident),
+                       i,
+                       extra_bounds.user_string(tcx)).as_slice());
+           return;
+        }
+
+        // Check that the trait bounds of the trait imply the bounds of its
+        // implementation.
+        //
+        // FIXME(pcwalton): We could be laxer here regarding sub- and super-
+        // traits, but I doubt that'll be wanted often, so meh.
+        for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
+            let impl_trait_bound =
+                impl_trait_bound.subst(tcx, &impl_to_skol_substs);
+
+            let mut ok = false;
+            for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
+                let trait_bound =
+                    trait_bound.subst(tcx, &trait_to_skol_substs);
+                let infcx = infer::new_infer_ctxt(tcx);
+                match infer::mk_sub_trait_refs(&infcx,
+                                               true,
+                                               infer::Misc(impl_m_span),
+                                               trait_bound,
+                                               impl_trait_bound.clone()) {
+                    Ok(_) => {
+                        ok = true;
+                        break
+                    }
+                    Err(_) => continue,
+                }
+            }
+
+            if !ok {
+                tcx.sess.span_err(impl_m_span,
+                                  format!("in method `{}`, type parameter {} \
+                                           requires bound `{}`, which is not \
+                                           required by the corresponding \
+                                           type parameter in the trait \
+                                           declaration",
+                                          token::get_ident(trait_m.ident),
+                                          i,
+                                          ppaux::trait_ref_to_str(
+                                              tcx,
+                                              &*impl_trait_bound)).as_slice())
+            }
+        }
+    }
+
     // Check the impl method type IM is a subtype of the trait method
     // type TM. To see why this makes sense, think of a vtable. The
     // expected type of the function pointers in the vtable is the
index 33e0d0331be6c23d3e0725e161b083f8a74a877a..bda47d99ed7146d0ec7b12ab9dd292a8d19df9ae 100644 (file)
@@ -398,6 +398,9 @@ fn search_for_vtable(vcx: &VtableContext,
         // Resolve any sub bounds. Note that there still may be free
         // type variables in substs. This might still be OK: the
         // process of looking up bounds might constrain some of them.
+        //
+        // This does not check built-in traits because those are handled
+        // later in the kind checking pass.
         let im_generics =
             ty::lookup_item_type(tcx, impl_did).generics;
         let subres = lookup_vtables(vcx,
index f374f1dc26795104f2fc31ea551a254cbbd27c4a..2984ea086efc59064d00919ddf70c15ccf5ffa64 100644 (file)
@@ -445,7 +445,8 @@ fn check_ptr_to_unsized<C:Combine>(this: &C,
         }
       }
 
-      (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if a_p.idx == b_p.idx => {
+      (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if
+          a_p.idx == b_p.idx && a_p.space == b_p.space => {
         Ok(a)
       }
 
index f106ce18a4adb579bbed9edf275acd10b430d746..44afc04d3f0efc3984c432dbe6d077e2e835148e 100644 (file)
@@ -93,7 +93,7 @@ pub struct UnificationTable<K,V> {
 
 /**
  * At any time, users may snapshot a unification table.  The changes
- * made during the snapshot may either be *commited* or *rolled back*.
+ * made during the snapshot may either be *committed* or *rolled back*.
  */
 pub struct Snapshot<K> {
     // Ensure that this snapshot is keyed to the table type.
@@ -152,7 +152,7 @@ pub fn in_snapshot(&self) -> bool {
 
     /**
      * Starts a new snapshot. Each snapshot must be either
-     * rolled back or commited in a "LIFO" (stack) order.
+     * rolled back or committed in a "LIFO" (stack) order.
      */
     pub fn snapshot(&mut self) -> Snapshot<K> {
         let length = self.undo_log.len();
@@ -188,12 +188,12 @@ pub fn rollback_to(&mut self, tcx: &ty::ctxt, snapshot: Snapshot<K>) {
             match self.undo_log.pop().unwrap() {
                 OpenSnapshot => {
                     // This indicates a failure to obey the stack discipline.
-                    tcx.sess.bug("Cannot rollback an uncommited snapshot");
+                    tcx.sess.bug("Cannot rollback an uncommitted snapshot");
                 }
 
                 CommittedSnapshot => {
                     // This occurs when there are nested snapshots and
-                    // the inner is commited but outer is rolled back.
+                    // the inner is committed but outer is rolled back.
                 }
 
                 NewVar(i) => {
index e159d0d00c82caa624073cc8d32a69cd518d63a0..7b6935df42079a561fd0e8a12006937679511f71 100644 (file)
@@ -216,9 +216,9 @@ pub fn autoderef(expr_id: ast::NodeId, autoderef: uint) -> MethodCall {
 #[deriving(Clone)]
 pub enum vtable_origin {
     /*
-      Statically known vtable. def_id gives the class or impl item
+      Statically known vtable. def_id gives the impl item
       from whence comes the vtable, and tys are the type substs.
-      vtable_res is the vtable itself
+      vtable_res is the vtable itself.
      */
     vtable_static(ast::DefId, subst::Substs, vtable_res),
 
index 87151708812e54a5f106291d5a04fd851bf6a0dc..4808cbdb4b09b332986c01c64214088562e7a098 100644 (file)
@@ -1079,7 +1079,7 @@ pub enum Primitive {
     F32, F64,
     Char,
     Bool,
-    Nil,
+    Unit,
     Str,
     Slice,
     PrimitiveTuple,
@@ -1110,7 +1110,7 @@ fn from_str(s: &str) -> Option<Primitive> {
             "u32" => Some(U32),
             "u64" => Some(U64),
             "bool" => Some(Bool),
-            "nil" => Some(Nil),
+            "unit" => Some(Unit),
             "char" => Some(Char),
             "str" => Some(Str),
             "f32" => Some(F32),
@@ -1159,7 +1159,7 @@ pub fn to_str(&self) -> &'static str {
             Str => "str",
             Bool => "bool",
             Char => "char",
-            Nil => "()",
+            Unit => "()",
             Slice => "slice",
             PrimitiveTuple => "tuple",
         }
@@ -1167,7 +1167,7 @@ pub fn to_str(&self) -> &'static str {
 
     pub fn to_url_str(&self) -> &'static str {
         match *self {
-            Nil => "nil",
+            Unit => "unit",
             other => other.to_str(),
         }
     }
@@ -1184,7 +1184,7 @@ impl Clean<Type> for ast::Ty {
     fn clean(&self) -> Type {
         use syntax::ast::*;
         match self.node {
-            TyNil => Primitive(Nil),
+            TyNil => Primitive(Unit),
             TyPtr(ref m) => RawPointer(m.mutbl.clean(), box m.ty.clean()),
             TyRptr(ref l, ref m) =>
                 BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
@@ -1214,7 +1214,7 @@ impl Clean<Type> for ty::t {
     fn clean(&self) -> Type {
         match ty::get(*self).sty {
             ty::ty_bot => Bottom,
-            ty::ty_nil => Primitive(Nil),
+            ty::ty_nil => Primitive(Unit),
             ty::ty_bool => Primitive(Bool),
             ty::ty_char => Primitive(Char),
             ty::ty_int(ast::TyI) => Primitive(Int),
@@ -1583,8 +1583,6 @@ fn clean(&self) -> PathSegment {
 }
 
 fn path_to_str(p: &ast::Path) -> String {
-    use syntax::parse::token;
-
     let mut s = String::new();
     let mut first = true;
     for i in p.segments.iter().map(|x| token::get_ident(x.identifier)) {
@@ -1739,7 +1737,7 @@ pub struct ViewItem {
 
 impl Clean<Vec<Item>> for ast::ViewItem {
     fn clean(&self) -> Vec<Item> {
-        // We consider inlining the documentation of `pub use` statments, but we
+        // We consider inlining the documentation of `pub use` statements, but we
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
         let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
@@ -1953,7 +1951,7 @@ fn name_from_pat(p: &ast::Pat) -> String {
     match p.node {
         PatWild => "_".to_string(),
         PatWildMulti => "..".to_string(),
-        PatIdent(_, ref p, _) => path_to_str(p),
+        PatIdent(_, ref p, _) => token::get_ident(p.node).get().to_string(),
         PatEnum(ref p, _) => path_to_str(p),
         PatStruct(..) => fail!("tried to get argument name from pat_struct, \
                                 which is not allowed in function arguments"),
index 9677b9004cdf1a12e015b56191ab3426747f1e1d..cec665768d1ee86ab4aad758480f60792d7f5283 100644 (file)
@@ -362,7 +362,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        },
                        args = decl.decl.inputs,
                        arrow = match decl.decl.output {
-                           clean::Primitive(clean::Nil) => "".to_string(),
+                           clean::Primitive(clean::Unit) => "".to_string(),
                            _ => format!(" -&gt; {}", decl.decl.output),
                        },
                        bounds = {
@@ -411,7 +411,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                                m.collect::<Vec<String>>().connect(" + "))
                        },
                        arrow = match decl.decl.output {
-                           clean::Primitive(clean::Nil) => "".to_string(),
+                           clean::Primitive(clean::Unit) => "".to_string(),
                            _ => format!(" -&gt; {}", decl.decl.output)
                        })
             }
@@ -472,7 +472,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "({args}){arrow}",
                args = self.inputs,
                arrow = match self.output {
-                   clean::Primitive(clean::Nil) => "".to_string(),
+                   clean::Primitive(clean::Unit) => "".to_string(),
                    _ => format!(" -&gt; {}", self.output),
                })
     }
@@ -505,7 +505,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "({args}){arrow}",
                args = args,
                arrow = match d.output {
-                   clean::Primitive(clean::Nil) => "".to_string(),
+                   clean::Primitive(clean::Unit) => "".to_string(),
                    _ => format!(" -&gt; {}", d.output),
                })
     }
index 86b80ee24943691a4abf49bab1ad1e7f0e9508c9..d878313ee28995c0e8e2f9507ff7d540ed3ad957 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_id = "rustdoc#0.11.0-pre"]
+#![crate_id = "rustdoc#0.11.0"]
 #![experimental]
 #![desc = "rustdoc, the Rust documentation extractor"]
 #![license = "MIT/ASL2"]
index 9734ba2d7518ef90995726a20ab5b8cd906037e9..161d3ed5e65e1cf70b259481e2321f7b2ebbb754 100644 (file)
@@ -376,7 +376,7 @@ unsafe fn with_c_str_unchecked<T>(&self, f: |*const libc::c_char| -> T) -> T {
 // (without forcing an additional & around &str). So we are instead
 // temporarily adding an instance for ~str and String, so that we can
 // take ToCStr as owned. When DST lands, the string instances should
-// be revisted, and arguments bound by ToCStr should be passed by
+// be revisited, and arguments bound by ToCStr should be passed by
 // reference.
 
 impl<'a> ToCStr for &'a str {
index a040829ebe33ddf5ca7015c2a4f02e3c3ccb8585..fabef24e06ac724f5e7d2f5a0f839dabcafff553 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_id = "rustrt#0.11.0-pre"]
+#![crate_id = "rustrt#0.11.0"]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![feature(macro_rules, phase, globs, thread_local, managed_boxes, asm)]
 #![feature(linkage, lang_items, unsafe_destructor)]
index 6811a62c74f523f7cda3ed8943f2c20accc833e6..f018b3fc16b3b63a8b26145731084f6df32af474 100644 (file)
@@ -97,7 +97,7 @@ pub enum _Unwind_Context {}
 
 extern "C" {
     // iOS on armv7 uses SjLj exceptions and requires to link
-    // agains corresponding routine (..._SjLj_...)
+    // against corresponding routine (..._SjLj_...)
     #[cfg(not(target_os = "ios", target_arch = "arm"))]
     pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception)
                                   -> _Unwind_Reason_Code;
index 891d0d5a8e3592053b8c4ff14c08079a71b6abbb..59401a8b66604f0568c80a293bf0421e9ed1ecee 100644 (file)
@@ -170,7 +170,7 @@ pub fn new() -> Task {
     /// This function can be used as an emulated "try/catch" to interoperate
     /// with the rust runtime at the outermost boundary. It is not possible to
     /// use this function in a nested fashion (a try/catch inside of another
-    /// try/catch). Invoking this funciton is quite cheap.
+    /// try/catch). Invoking this function is quite cheap.
     ///
     /// If the closure `f` succeeds, then the returned task can be used again
     /// for another invocation of `run`. If the closure `f` fails then `self`
@@ -276,7 +276,7 @@ fn cleanup(~self, result: Result) -> Box<Task> {
         // 1. If TLD destruction fails, heap destruction will be attempted.
         //    There is a test for this at fail-during-tld-destroy.rs. Sadly the
         //    other way can't be tested due to point 2 above. Note that we must
-        //    immortalize the heap first becuase if any deallocations are
+        //    immortalize the heap first because if any deallocations are
         //    attempted while TLD is being dropped it will attempt to free the
         //    allocation from the wrong heap (because the current one has been
         //    replaced).
index 9908e87e86a4727a0230eba1c77c66265bf8c9fd..59784328cdb50c02448a3893b1a4776e947415e3 100644 (file)
@@ -243,7 +243,7 @@ pub unsafe fn create(stack: uint, p: Box<proc():Send>) -> rust_thread {
                 // EINVAL means |stack_size| is either too small or not a
                 // multiple of the system page size.  Because it's definitely
                 // >= PTHREAD_STACK_MIN, it must be an alignment issue.
-                // Round up to the neareast page and try again.
+                // Round up to the nearest page and try again.
                 let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint;
                 let stack_size = (stack_size + page_size - 1) &
                                  (-(page_size as int - 1) as uint - 1);
index 968a283995bef2fef78775b9594ac7a9cf47d018..c13263680aac7986a93ef11601c0e124866d3a03 100644 (file)
 
 */
 
-#![crate_id = "rustuv#0.11.0-pre"]
+#![crate_id = "rustuv#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
+       html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, unsafe_destructor)]
 #![deny(unused_result, unused_must_use)]
@@ -234,7 +238,7 @@ fn new(s: &'static str) -> ForbidUnwind {
 impl Drop for ForbidUnwind {
     fn drop(&mut self) {
         assert!(self.failing_before == task::failing(),
-                "didnt want an unwind during: {}", self.msg);
+                "didn't want an unwind during: {}", self.msg);
     }
 }
 
index f6b9226588ca34572a7ac8e87172f7c77569d989..875c2dee46b4f874f9cf84a8d293c594558f563b 100644 (file)
@@ -87,7 +87,7 @@ pub fn read(&mut self, buf: &mut [u8]) -> Result<uint, UvError> {
         // immediately as part of the call to alloc_cb. What this means is that
         // we must be ready for this to happen (by setting the data in the uv
         // handle). In theory this otherwise doesn't need to happen until after
-        // the read is succesfully started.
+        // the read is successfully started.
         unsafe { uvll::set_data_for_uv_handle(self.handle, &mut rcx) }
 
         // Send off the read request, but don't block until we're sure that the
index 9d0a56b3c851d69d82f15e3cdf4ab10a0278739b..f6c1cdd2977549f9a5ca7ebd36092fa85872b4cf 100644 (file)
@@ -77,7 +77,7 @@ impl RtioTimer for TimerWatcher {
     fn sleep(&mut self, msecs: u64) {
         // As with all of the below functions, we must be extra careful when
         // destroying the previous action. If the previous action was a channel,
-        // destroying it could invoke a context switch. For these situtations,
+        // destroying it could invoke a context switch. For these situations,
         // we must temporarily un-home ourselves, then destroy the action, and
         // then re-home again.
         let missile = self.fire_homing_missile();
index 675b2e507b3e9073448bfc99dc6369c53b39ed27..fc8aa8ac257a76f2769355979280750791041caa 100644 (file)
 //! An example version number with all five components is
 //! `0.8.1-rc.3.0+20130922.linux`.
 
-#![crate_id = "semver#0.11.0-pre"]
+#![crate_id = "semver#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 use std::char;
 use std::cmp;
index 275e5e242d66553a80aaa288f0ec056e1ef49ca1..a2a504132363332e60cffd698e95b38945388cb7 100644 (file)
 Core encoding and decoding interfaces.
 */
 
-#![crate_id = "serialize#0.11.0-pre"]
+#![crate_id = "serialize#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(macro_rules, managed_boxes, default_type_params, phase)]
 
index 2c54bd895e952f59a635bf2041f0cd8d7cb324de..ca59849202b08677e03943747fb2617d6eb6a687 100644 (file)
@@ -410,7 +410,7 @@ fn test_from_str_ipv4_in_ipv6() {
         // colon after v4
         let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
         assert_eq!(None, none);
-        // not enought groups
+        // not enough groups
         let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
         assert_eq!(None, none);
         // too many groups
index cd78898d46bb82c22c73b54f39f8d3a3bfc3e516..21903eb26439cc30c79b60d90acdd8ff29bf51a9 100644 (file)
@@ -165,7 +165,7 @@ pub fn set_ttl(&mut self, ttl: int) -> IoResult<()> {
 
     /// Sets the broadcast flag on or off
     #[experimental]
-    pub fn set_broadast(&mut self, broadcast: bool) -> IoResult<()> {
+    pub fn set_broadcast(&mut self, broadcast: bool) -> IoResult<()> {
         if broadcast {
             self.obj.hear_broadcasts()
         } else {
@@ -173,6 +173,12 @@ pub fn set_broadast(&mut self, broadcast: bool) -> IoResult<()> {
         }.map_err(IoError::from_rtio_error)
     }
 
+    /// Sets the broadcast flag on or off
+    #[deprecated="renamed to `set_broadcast`"]
+    pub fn set_broadast(&mut self, broadcast: bool) -> IoResult<()> {
+        self.set_broadcast(broadcast)
+    }
+
     /// Sets the read/write timeout for this socket.
     ///
     /// For more information, see `TcpStream::set_timeout`
index 06a1d069b6a72b25f9a75eae9c489a88b8545bd4..0e6f848fce85ab19fa9fc3d5b1d6aceba1db522c 100644 (file)
@@ -94,7 +94,7 @@
 //! all the standard macros, such as `assert!`, `fail!`, `println!`,
 //! and `format!`, also available to all Rust code.
 
-#![crate_id = "std#0.11.0-pre"]
+#![crate_id = "std#0.11.0"]
 #![unstable]
 #![comment = "The Rust standard library"]
 #![license = "MIT/ASL2"]
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, globs, managed_boxes, linkage)]
 pub use core::raw;
 pub use core::simd;
 pub use core::tuple;
+// FIXME #15320: primitive documentation needs top-level modules, this
+// should be `std::tuple::unit`.
+pub use core::unit;
 #[cfg(not(test))] pub use core::ty;
 pub use core::result;
 pub use core::option;
index 6674dd532aeb0b5f76d924b3e8c5a5555a863a00..b3f25914c8f568768c22fd62c6523e837895e9c0 100644 (file)
@@ -45,7 +45,7 @@
 use ptr::RawPtr;
 use ptr;
 use result::{Err, Ok, Result};
-use slice::{Vector, ImmutableVector, MutableVector};
+use slice::{Vector, ImmutableVector, MutableVector, ImmutableEqVector};
 use str::{Str, StrSlice, StrAllocating};
 use str;
 use string::String;
@@ -398,9 +398,9 @@ pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
-pub fn setenv(n: &str, v: &str) {
+pub fn setenv<T: BytesContainer>(n: &str, v: T) {
     #[cfg(unix)]
-    fn _setenv(n: &str, v: &str) {
+    fn _setenv(n: &str, v: &[u8]) {
         unsafe {
             with_env_lock(|| {
                 n.with_c_str(|nbuf| {
@@ -413,18 +413,20 @@ fn _setenv(n: &str, v: &str) {
     }
 
     #[cfg(windows)]
-    fn _setenv(n: &str, v: &str) {
+    fn _setenv(n: &str, v: &[u8]) {
         let n: Vec<u16> = n.utf16_units().collect();
         let n = n.append_one(0);
-        let v: Vec<u16> = v.utf16_units().collect();
+        let v: Vec<u16> = str::from_utf8(v).unwrap().utf16_units().collect();
         let v = v.append_one(0);
+
         unsafe {
             with_env_lock(|| {
                 libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
             })
         }
     }
-    _setenv(n, v)
+
+    _setenv(n, v.container_as_bytes())
 }
 
 /// Remove a variable from the environment entirely.
@@ -453,77 +455,130 @@ fn _unsetenv(n: &str) {
     _unsetenv(n);
 }
 
-#[cfg(unix)]
-/// Parse a string or vector according to the platform's conventions
-/// for the `PATH` environment variable and return a Vec<Path>.
-/// Drops empty paths.
+/// Parses input according to platform conventions for the `PATH`
+/// environment variable.
 ///
 /// # Example
 /// ```rust
 /// use std::os;
 ///
 /// let key = "PATH";
-/// match os::getenv(key) {
+/// match os::getenv_as_bytes(key) {
 ///     Some(paths) => {
 ///         for path in os::split_paths(paths).iter() {
 ///             println!("'{}'", path.display());
 ///         }
 ///     }
-///     None => println!("{} is not defined in the environnement.", key)
+///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
 pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-    unparsed.container_as_bytes()
-            .split(|b| *b == ':' as u8)
-            .filter(|s| s.len() > 0)
-            .map(Path::new)
-            .collect()
-}
+    #[cfg(unix)]
+    fn _split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
+        unparsed.container_as_bytes()
+                .split(|b| *b == b':')
+                .map(Path::new)
+                .collect()
+    }
 
-#[cfg(windows)]
-/// Parse a string or vector according to the platform's conventions
-/// for the `PATH` environment variable. Drops empty paths.
-pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-    // On Windows, the PATH environment variable is semicolon separated.  Double
-    // quotes are used as a way of introducing literal semicolons (since
-    // c:\some;dir is a valid Windows path). Double quotes are not themselves
-    // permitted in path names, so there is no way to escape a double quote.
-    // Quoted regions can appear in arbitrary locations, so
-    //
-    //   c:\foo;c:\som"e;di"r;c:\bar
-    //
-    // Should parse as [c:\foo, c:\some;dir, c:\bar].
-    //
-    // (The above is based on testing; there is no clear reference available
-    // for the grammar.)
-
-    let mut parsed = Vec::new();
-    let mut in_progress = Vec::new();
-    let mut in_quote = false;
-
-    for b in unparsed.container_as_bytes().iter() {
-        match *b as char {
-            ';' if !in_quote => {
-                // ignore zero-length path strings
-                if in_progress.len() > 0 {
+    #[cfg(windows)]
+    fn _split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
+        // On Windows, the PATH environment variable is semicolon separated.  Double
+        // quotes are used as a way of introducing literal semicolons (since
+        // c:\some;dir is a valid Windows path). Double quotes are not themselves
+        // permitted in path names, so there is no way to escape a double quote.
+        // Quoted regions can appear in arbitrary locations, so
+        //
+        //   c:\foo;c:\som"e;di"r;c:\bar
+        //
+        // Should parse as [c:\foo, c:\some;dir, c:\bar].
+        //
+        // (The above is based on testing; there is no clear reference available
+        // for the grammar.)
+
+        let mut parsed = Vec::new();
+        let mut in_progress = Vec::new();
+        let mut in_quote = false;
+
+        for b in unparsed.container_as_bytes().iter() {
+            match *b {
+                b';' if !in_quote => {
                     parsed.push(Path::new(in_progress.as_slice()));
+                    in_progress.truncate(0)
+                }
+                b'"' => {
+                    in_quote = !in_quote;
+                }
+                _  => {
+                    in_progress.push(*b);
                 }
-                in_progress.truncate(0)
-            }
-            '\"' => {
-                in_quote = !in_quote;
             }
-            _  => {
-                in_progress.push(*b);
+        }
+        parsed.push(Path::new(in_progress));
+        parsed
+    }
+
+    _split_paths(unparsed)
+}
+
+/// Joins a collection of `Path`s appropriately for the `PATH`
+/// environment variable.
+///
+/// Returns a `Vec<u8>` on success, since `Path`s are not utf-8
+/// encoded on all platforms.
+///
+/// Returns an `Err` (containing an error message) if one of the input
+/// `Path`s contains an invalid character for constructing the `PATH`
+/// variable (a double quote on Windows or a colon on Unix).
+///
+/// # Example
+///
+/// ```rust
+/// use std::os;
+/// use std::path::Path;
+///
+/// let key = "PATH";
+/// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths);
+/// paths.push(Path::new("/home/xyz/bin"));
+/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
+/// ```
+pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+    #[cfg(windows)]
+    fn _join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+        let mut joined = Vec::new();
+        let sep = b';';
+
+        for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+            if i > 0 { joined.push(sep) }
+            if path.contains(&b'"') {
+                return Err("path segment contains `\"`");
+            } else if path.contains(&sep) {
+                joined.push(b'"');
+                joined.push_all(path);
+                joined.push(b'"');
+            } else {
+                joined.push_all(path);
             }
         }
+
+        Ok(joined)
     }
 
-    if in_progress.len() > 0 {
-        parsed.push(Path::new(in_progress));
+    #[cfg(unix)]
+    fn _join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+        let mut joined = Vec::new();
+        let sep = b':';
+
+        for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+            if i > 0 { joined.push(sep) }
+            if path.contains(&sep) { return Err("path segment contains separator `:`") }
+            joined.push_all(path);
+        }
+
+        Ok(joined)
     }
 
-    parsed
+    _join_paths(paths)
 }
 
 /// A low-level OS in-memory pipe.
@@ -1767,7 +1822,7 @@ mod tests {
     use c_str::ToCStr;
     use option;
     use os::{env, getcwd, getenv, make_absolute};
-    use os::{split_paths, setenv, unsetenv};
+    use os::{split_paths, join_paths, setenv, unsetenv};
     use os;
     use rand::Rng;
     use rand;
@@ -2032,11 +2087,11 @@ fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
                 parsed.iter().map(|s| Path::new(*s)).collect()
         }
 
-        assert!(check_parse("", []));
-        assert!(check_parse(r#""""#, []));
-        assert!(check_parse(";;", []));
+        assert!(check_parse("", [""]));
+        assert!(check_parse(r#""""#, [""]));
+        assert!(check_parse(";;", ["", "", ""]));
         assert!(check_parse(r"c:\", [r"c:\"]));
-        assert!(check_parse(r"c:\;", [r"c:\"]));
+        assert!(check_parse(r"c:\;", [r"c:\", ""]));
         assert!(check_parse(r"c:\;c:\Program Files\",
                             [r"c:\", r"c:\Program Files\"]));
         assert!(check_parse(r#"c:\;c:\"foo"\"#, [r"c:\", r"c:\foo\"]));
@@ -2052,12 +2107,44 @@ fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
                 parsed.iter().map(|s| Path::new(*s)).collect()
         }
 
-        assert!(check_parse("", []));
-        assert!(check_parse("::", []));
+        assert!(check_parse("", [""]));
+        assert!(check_parse("::", ["", "", ""]));
         assert!(check_parse("/", ["/"]));
-        assert!(check_parse("/:", ["/"]));
+        assert!(check_parse("/:", ["/", ""]));
         assert!(check_parse("/:/usr/local", ["/", "/usr/local"]));
     }
 
+    #[test]
+    #[cfg(unix)]
+    fn join_paths_unix() {
+        fn test_eq(input: &[&str], output: &str) -> bool {
+            join_paths(input).unwrap().as_slice() == output.as_bytes()
+        }
+
+        assert!(test_eq([], ""));
+        assert!(test_eq(["/bin", "/usr/bin", "/usr/local/bin"],
+                        "/bin:/usr/bin:/usr/local/bin"));
+        assert!(test_eq(["", "/bin", "", "", "/usr/bin", ""],
+                        ":/bin:::/usr/bin:"));
+        assert!(join_paths(["/te:st"]).is_err());
+    }
+
+    #[test]
+    #[cfg(windows)]
+    fn join_paths_windows() {
+        fn test_eq(input: &[&str], output: &str) -> bool {
+            join_paths(input).unwrap().as_slice() == output.as_bytes()
+        }
+
+        assert!(test_eq([], ""));
+        assert!(test_eq([r"c:\windows", r"c:\"],
+                        r"c:\windows;c:\"));
+        assert!(test_eq(["", r"c:\windows", "", "", r"c:\", ""],
+                        r";c:\windows;;;c:\;"));
+        assert!(test_eq([r"c:\te;st", r"c:\"],
+                        r#""c:\te;st";c:\"#));
+        assert!(join_paths([r#"c:\te"st"#]).is_err());
+    }
+
     // More recursive_mkdir tests are in extra::tempfile
 }
index 8f51e834c6a024ec0d67b9319908fb0db88cf45d..2e0dcdd8eb69f83588a353615eba5a3cb8f7e344 100644 (file)
@@ -266,7 +266,7 @@ fn backtrace(buf: *mut *const libc::c_void,
         }
 
         // while it doesn't requires lock for work as everything is
-        // local, it still displays much nicier backtraces when a
+        // local, it still displays much nicer backtraces when a
         // couple of tasks fail simultaneously
         static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
         let _g = unsafe { LOCK.lock() };
index bf2d9aa52fd24bd9bfd9a8f1272c94a569746e5a..742686069e283531461e68cd7852e9f6d88bbc58 100644 (file)
@@ -354,7 +354,7 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
             }
 
             // We woke ourselves up from select. Assert that the task should be
-            // trashed and returne that we don't have any data.
+            // trashed and returned that we don't have any data.
             n => {
                 let t = unsafe { BlockedTask::cast_from_uint(n) };
                 t.trash();
index a50a6bbc8d31fcd6d4ee09c9db00347ff58f7294..5ad4dea5d2a89bc52df8a319d19cdecb1703ca94 100644 (file)
@@ -81,7 +81,7 @@ pub fn new() -> Packet<T> {
 
     // This function should be used after newly created Packet
     // was wrapped with an Arc
-    // In other case mutex data will be duplicated while clonning
+    // In other case mutex data will be duplicated while cloning
     // and that could cause problems on platforms where it is
     // represented by opaque data structure
     pub fn postinit_lock(&mut self) {
@@ -140,7 +140,7 @@ pub fn send(&mut self, t: T) -> Result<(), T> {
         // See Port::drop for what's going on
         if self.port_dropped.load(atomics::SeqCst) { return Err(t) }
 
-        // Note that the multiple sender case is a little tricker
+        // Note that the multiple sender case is a little trickier
         // semantically than the single sender case. The logic for
         // incrementing is "add and if disconnected store disconnected".
         // This could end up leading some senders to believe that there
index beb75bab3f6ab6c8d1d83ee24176c53cb7b879b2..4f6d1a261c4917696b56d99a628f7a4cbb69333c 100644 (file)
 //! use this crate specifically. Instead, its functionality is reexported
 //! through `std::sync`.
 
-#![crate_id = "sync#0.11.0-pre"]
+#![crate_id = "sync#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(phase, globs, macro_rules, unsafe_destructor)]
index ef558d3f9241bb0d04f6259cd0aa425fea457c00..a10ec7458690abcbf20e68bd12c2e4730dea4f76 100644 (file)
@@ -215,7 +215,7 @@ pub fn lock<'a>(&'a self) -> Guard<'a> {
             None => {}
         }
 
-        // After we've failed the fast path, then we delegate to the differnet
+        // After we've failed the fast path, then we delegate to the different
         // locking protocols for green/native tasks. This will select two tasks
         // to continue further (one native, one green).
         let t: Box<Task> = Local::take();
index 529b460adcd34d862bcb951e8ee00a8f27358d40..237d0660a41dcca5edb5f15875cd41bdc5fd2f5a 100644 (file)
@@ -293,8 +293,8 @@ pub enum Pat_ {
     // In the nullary enum case, the parser can't determine
     // which it is. The resolver determines this, and
     // records this pattern's NodeId in an auxiliary
-    // set (of "pat_idents that refer to nullary enums")
-    PatIdent(BindingMode, Path, Option<Gc<Pat>>),
+    // set (of "PatIdents that refer to nullary enums")
+    PatIdent(BindingMode, SpannedIdent, Option<Gc<Pat>>),
     PatEnum(Path, Option<Vec<Gc<Pat>>>), /* "none" means a * pattern where
                                      * we don't bind the fields to names */
     PatStruct(Path, Vec<FieldPat>, bool),
@@ -818,7 +818,7 @@ pub struct Arg {
 
 impl Arg {
     pub fn new_self(span: Span, mutability: Mutability) -> Arg {
-        let path = ast_util::ident_to_path(span, special_idents::self_);
+        let path = Spanned{span:span,node:special_idents::self_};
         Arg {
             // HACK(eddyb) fake type for the self argument.
             ty: P(Ty {
index 2a6f7bdb87e35eec4730e2d143a873b61a9fe539..036d6b4b43adc62d537c8c0f9dfc745964d6bca3 100644 (file)
@@ -33,12 +33,6 @@ pub fn path_name_i(idents: &[Ident]) -> String {
     }).collect::<Vec<String>>().connect("::")
 }
 
-// totally scary function: ignores all but the last element, should have
-// a different name
-pub fn path_to_ident(path: &Path) -> Ident {
-    path.segments.last().unwrap().identifier
-}
-
 pub fn local_def(id: NodeId) -> DefId {
     ast::DefId { krate: LOCAL_CRATE, node: id }
 }
@@ -186,6 +180,8 @@ pub fn block_from_expr(e: Gc<Expr>) -> P<Block> {
     })
 }
 
+// convert a span and an identifier to the corresponding
+// 1-segment path
 pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
     ast::Path {
         span: s,
@@ -202,7 +198,7 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
 
 pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> Gc<Pat> {
     box(GC) ast::Pat { id: id,
-                node: PatIdent(BindByValue(MutImmutable), ident_to_path(s, i), None),
+                node: PatIdent(BindByValue(MutImmutable), codemap::Spanned{span:s, node:i}, None),
                 span: s }
 }
 
index 50b1639484d9415385357240cc69d669db1a3179..f0494e181201375096c9e0417a84bce1ba43fb07 100644 (file)
@@ -16,7 +16,6 @@
 use codemap::Span;
 use ext::base;
 use ext::base::*;
-use parse;
 use parse::token::InternedString;
 use parse::token;
 
@@ -48,12 +47,7 @@ fn next(&self) -> State {
 
 pub fn expand_asm(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                   -> Box<base::MacResult> {
-    let mut p = parse::new_parser_from_tts(cx.parse_sess(),
-                                           cx.cfg(),
-                                           tts.iter()
-                                              .map(|x| (*x).clone())
-                                              .collect());
-
+    let mut p = cx.new_parser_from_tts(tts);
     let mut asm = InternedString::new("");
     let mut asm_str_style = None;
     let mut outputs = Vec::new();
index 0d8373eac3c7f5109f7b5a9c23c3231731dad924..d2e69204d333cb5cb0374857bdf9c456a0d22492 100644 (file)
@@ -15,6 +15,7 @@
 use ext;
 use ext::expand;
 use parse;
+use parse::parser;
 use parse::token;
 use parse::token::{InternedString, intern, str_to_ident};
 use util::small_vector::SmallVector;
@@ -433,6 +434,11 @@ pub fn expand_expr(&mut self, mut e: Gc<ast::Expr>) -> Gc<ast::Expr> {
         }
     }
 
+    pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree])
+        -> parser::Parser<'a> {
+        parse::tts_to_parser(self.parse_sess, Vec::from_slice(tts), self.cfg())
+    }
+
     pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
     pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
@@ -472,7 +478,7 @@ pub fn bt_pop(&mut self) {
     }
     /// Emit `msg` attached to `sp`, and stop compilation immediately.
     ///
-    /// `span_err` should be strongly prefered where-ever possible:
+    /// `span_err` should be strongly preferred where-ever possible:
     /// this should *only* be used when
     /// - continuing has a high risk of flow-on errors (e.g. errors in
     ///   declaring a macro would cause all uses of that macro to
@@ -586,11 +592,7 @@ pub fn get_single_str_from_tts(cx: &ExtCtxt,
 pub fn get_exprs_from_tts(cx: &mut ExtCtxt,
                           sp: Span,
                           tts: &[ast::TokenTree]) -> Option<Vec<Gc<ast::Expr>>> {
-    let mut p = parse::new_parser_from_tts(cx.parse_sess(),
-                                           cx.cfg(),
-                                           tts.iter()
-                                              .map(|x| (*x).clone())
-                                              .collect());
+    let mut p = cx.new_parser_from_tts(tts);
     let mut es = Vec::new();
     while p.token != token::EOF {
         es.push(cx.expand_expr(p.parse_expr()));
index 8d48401f9c2a45ec077fcc2cdb8d43d86826fa09..46bc4ec11ce4f044ac14b35d1f603042558bf089 100644 (file)
@@ -759,8 +759,7 @@ fn pat_ident_binding_mode(&self,
                               span: Span,
                               ident: ast::Ident,
                               bm: ast::BindingMode) -> Gc<ast::Pat> {
-        let path = self.path_ident(span, ident);
-        let pat = ast::PatIdent(bm, path, None);
+        let pat = ast::PatIdent(bm, Spanned{span: span, node: ident}, None);
         self.pat(span, pat)
     }
     fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<Gc<ast::Pat>> ) -> Gc<ast::Pat> {
index 3e74b2680e060444117922a830cc6d38d03ffc6b..c2930662bc459a31bbb370875ae5a2088dd1171e 100644 (file)
 use parse::attr::ParserAttr;
 use parse::token::InternedString;
 use parse::token;
-use parse;
 
 
 pub fn expand_cfg(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                   -> Box<base::MacResult> {
-    let mut p = parse::new_parser_from_tts(cx.parse_sess(),
-                                           cx.cfg(),
-                                           tts.iter()
-                                              .map(|x| (*x).clone())
-                                              .collect());
-
+    let mut p = cx.new_parser_from_tts(tts);
     let mut cfgs = Vec::new();
     // parse `cfg!(meta_item, meta_item(x,y), meta_item="foo", ...)`
     while p.token != token::EOF {
index 2b97687dbf8c99e5d19704f3c957758165d41ade..157b64fb47c0a7fa3d699681bb0d223d7a718f46 100644 (file)
@@ -834,7 +834,7 @@ fn build_enum_match(&self,
                                 generic `deriving`");
             }
 
-            // `ref` inside let matches is buggy. Causes havoc wih rusc.
+            // `ref` inside let matches is buggy. Causes havoc with rusc.
             // let (variant_index, ref self_vec) = matches_so_far[0];
             let (variant, self_vec) = match matches_so_far.get(0) {
                 &(_, v, ref s) => (v, s)
@@ -1049,7 +1049,7 @@ fn summarise_struct(&self,
 
     fn create_subpatterns(&self,
                           cx: &mut ExtCtxt,
-                          field_paths: Vec<ast::Path> ,
+                          field_paths: Vec<ast::SpannedIdent> ,
                           mutbl: ast::Mutability)
                           -> Vec<Gc<ast::Pat>> {
         field_paths.iter().map(|path| {
@@ -1095,15 +1095,10 @@ fn create_struct_pattern(&self,
                     cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`");
                 }
             };
-            let path =
-                cx.path_ident(sp,
-                              cx.ident_of(format!("{}_{}",
-                                                  prefix,
-                                                  i).as_slice()));
-            paths.push(path.clone());
+            let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
+            paths.push(codemap::Spanned{span: sp, node: ident});
             let val = cx.expr(
-                sp, ast::ExprParen(
-                    cx.expr_deref(sp, cx.expr_path(path))));
+                sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
             ident_expr.push((sp, opt_id, val));
         }
 
@@ -1145,15 +1140,11 @@ fn create_enum_variant_pattern(&self,
                 let mut ident_expr = Vec::new();
                 for (i, va) in variant_args.iter().enumerate() {
                     let sp = self.set_expn_info(cx, va.ty.span);
-                    let path =
-                        cx.path_ident(sp,
-                                      cx.ident_of(format!("{}_{}",
-                                                          prefix,
-                                                          i).as_slice()));
-
-                    paths.push(path.clone());
-                    let val = cx.expr(
-                        sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(path))));
+                    let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice());
+                    let path1 = codemap::Spanned{span: sp, node: ident};
+                    paths.push(path1);
+                    let expr_path = cx.expr_path(cx.path_ident(sp, ident));
+                    let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
                     ident_expr.push((sp, None, val));
                 }
 
index b9cedb7a7797a065a9b32a34e137ef12b1310972..c3413293e52ae4b1ac664de13b7246ccffdd5070 100644 (file)
@@ -705,22 +705,10 @@ fn visit_pat(&mut self, pattern: &ast::Pat, _: ()) {
             // we found a pat_ident!
             ast::Pat {
                 id: _,
-                node: ast::PatIdent(_, ref path, ref inner),
+                node: ast::PatIdent(_, ref path1, ref inner),
                 span: _
             } => {
-                match path {
-                    // a path of length one:
-                    &ast::Path {
-                        global: false,
-                        span: _,
-                        segments: ref segments
-                    } if segments.len() == 1 => {
-                        self.ident_accumulator.push(segments.get(0)
-                                                            .identifier)
-                    }
-                    // I believe these must be enums...
-                    _ => ()
-                }
+                self.ident_accumulator.push(path1.node);
                 // visit optional subpattern of pat_ident:
                 for subpat in inner.iter() {
                     self.visit_pat(&**subpat, ())
@@ -1307,7 +1295,7 @@ macro_rules! outer ( ($e:pat ) => (inner!($e)))
     }
 
     // create a really evil test case where a $x appears inside a binding of $x
-    // but *shouldnt* bind because it was inserted by a different macro....
+    // but *shouldn't* bind because it was inserted by a different macro....
     // can't write this test case until we have macro-generating macros.
 
     // FIXME #9383 : lambda var hygiene
index 857eadfe57cc40ea9081dbf35136eb20baa47547..f39e50ad1313f63501394e1a31da42b528c2a396 100644 (file)
@@ -16,7 +16,6 @@
 use ext::build::AstBuilder;
 use parse::token::InternedString;
 use parse::token;
-use rsparse = parse;
 
 use parse = fmt_macros;
 use std::collections::HashMap;
@@ -81,11 +80,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
     let mut names = HashMap::<String, Gc<ast::Expr>>::new();
     let mut order = Vec::new();
 
-    let mut p = rsparse::new_parser_from_tts(ecx.parse_sess(),
-                                             ecx.cfg(),
-                                             tts.iter()
-                                                .map(|x| (*x).clone())
-                                                .collect());
+    let mut p = ecx.new_parser_from_tts(tts);
     // Parse the leading function expression (maybe a block, maybe a path)
     let invocation = if allow_method {
         let e = p.parse_expr();
index 35702b1b3cd46d6dbbc9f714d96ffa30bb78c3f3..7b24b97d5da4dd6be7557657bb8019f0ba816103 100644 (file)
@@ -15,7 +15,6 @@
 use ext::build::AstBuilder;
 use parse::token::*;
 use parse::token;
-use parse;
 
 use std::gc::Gc;
 
@@ -583,11 +582,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     // it has to do with transition away from supporting old-style macros, so
     // try removing it when enough of them are gone.
 
-    let mut p = parse::new_parser_from_tts(cx.parse_sess(),
-                                           cx.cfg(),
-                                           tts.iter()
-                                              .map(|x| (*x).clone())
-                                              .collect());
+    let mut p = cx.new_parser_from_tts(tts);
     p.quote_depth += 1u;
 
     let cx_expr = p.parse_expr();
index c6177ce31f5f874a8282020d717a6ca2f1c792bf..f9d7078da3dcbe4377132259c3c5699ae66fca36 100644 (file)
@@ -791,9 +791,10 @@ pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {
     let node = match p.node {
         PatWild => PatWild,
         PatWildMulti => PatWildMulti,
-        PatIdent(binding_mode, ref pth, ref sub) => {
+        PatIdent(binding_mode, ref pth1, ref sub) => {
             PatIdent(binding_mode,
-                     folder.fold_path(pth),
+                     Spanned{span: folder.new_span(pth1.span),
+                                       node: folder.fold_ident(pth1.node)},
                      sub.map(|x| folder.fold_pat(x)))
         }
         PatLit(e) => PatLit(folder.fold_expr(e)),
index 0d6821fb30c08810471035c1c7593d3a117e257f..ce63d2bb7311acfece0c700fc8a478208822edbf 100644 (file)
 
 */
 
-#![crate_id = "syntax#0.11.0-pre"]
+#![crate_id = "syntax#0.11.0"]
 #![experimental]
 #![license = "MIT/ASL2"]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
 #![feature(quote, unsafe_destructor)]
index 331a49c83beacbeac006dc3a5666cc0e40c475de..4b5252bfba3118eb081d8a1783d18631a265b9bc 100644 (file)
@@ -594,23 +594,15 @@ fn parser_done(p: Parser){
     #[test] fn parse_ident_pat () {
         let sess = new_parse_sess();
         let mut parser = string_to_parser(&sess, "b".to_string());
-        assert!(parser.parse_pat() ==
-                   box(GC) ast::Pat{id: ast::DUMMY_NODE_ID,
-                             node: ast::PatIdent(
-                                ast::BindByValue(ast::MutImmutable),
-                                ast::Path {
-                                    span:sp(0,1),
-                                    global:false,
-                                    segments: vec!(
-                                        ast::PathSegment {
-                                            identifier: str_to_ident("b"),
-                                            lifetimes: Vec::new(),
-                                            types: OwnedSlice::empty(),
-                                        }
-                                    ),
-                                },
-                                None /* no idea */),
-                             span: sp(0,1)});
+        assert!(parser.parse_pat()
+                == box(GC) ast::Pat{
+                id: ast::DUMMY_NODE_ID,
+                node: ast::PatIdent(ast::BindByValue(ast::MutImmutable),
+                                    Spanned{ span:sp(0, 1),
+                                             node: str_to_ident("b")
+                    },
+                                    None),
+                span: sp(0,1)});
         parser_done(parser);
     }
 
@@ -643,24 +635,15 @@ fn parser_done(p: Parser){
                                         id: ast::DUMMY_NODE_ID,
                                         node: ast::PatIdent(
                                             ast::BindByValue(ast::MutImmutable),
-                                            ast::Path {
-                                                span:sp(6,7),
-                                                global:false,
-                                                segments: vec!(
-                                                    ast::PathSegment {
-                                                        identifier:
-                                                            str_to_ident("b"),
-                                                        lifetimes: Vec::new(),
-                                                        types: OwnedSlice::empty(),
-                                                    }
-                                                ),
-                                            },
-                                            None // no idea
-                                        ),
-                                        span: sp(6,7)
-                                    },
-                                    id: ast::DUMMY_NODE_ID
-                                }),
+                                                Spanned{
+                                                    span: sp(6,7),
+                                                    node: str_to_ident("b")},
+                                                None
+                                                    ),
+                                            span: sp(6,7)
+                                        },
+                                        id: ast::DUMMY_NODE_ID
+                                    }),
                                 output: ast::P(ast::Ty{id: ast::DUMMY_NODE_ID,
                                                        node: ast::TyNil,
                                                        span:sp(15,15)}), // not sure
index 0fd5a7086b78c897507508137b3d7c410242a6a5..f3789e25bc8a7e5e39bc1e1ded000561e43c4578 100644 (file)
@@ -58,7 +58,7 @@
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::Visibility;
 use ast;
-use ast_util::{as_prec, lit_is_str, operator_prec};
+use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec};
 use ast_util;
 use codemap::{Span, BytePos, Spanned, spanned, mk_sp};
 use codemap;
@@ -2854,8 +2854,7 @@ fn parse_pat_fields(&mut self) -> (Vec<ast::FieldPat> , bool) {
                 self.bump();
                 self.parse_pat()
             } else {
-                let fieldpath = ast_util::ident_to_path(self.last_span,
-                                                        fieldname);
+                let fieldpath = codemap::Spanned{span:self.last_span, node: fieldname};
                 box(GC) ast::Pat {
                     id: ast::DUMMY_NODE_ID,
                     node: PatIdent(bind_type, fieldpath, None),
@@ -2961,6 +2960,7 @@ pub fn parse_pat(&mut self) -> Gc<Pat> {
           }
           _ => {}
         }
+        // at this point, token != _, ~, &, &&, (, [
 
         if (!is_ident_or_path(&self.token) && self.token != token::MOD_SEP)
                 || self.is_keyword(keywords::True)
@@ -3017,7 +3017,9 @@ pub fn parse_pat(&mut self) -> Gc<Pat> {
                 let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);
                 pat = PatRange(start, end);
             } else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
-                let name = self.parse_path(NoTypesAllowed).path;
+                let id = self.parse_ident();
+                let id_span = self.last_span;
+                let pth1 = codemap::Spanned{span:id_span, node: id};
                 if self.eat(&token::NOT) {
                     // macro invocation
                     let ket = token::close_delimiter_for(&self.token)
@@ -3028,7 +3030,7 @@ pub fn parse_pat(&mut self) -> Gc<Pat> {
                                                     seq_sep_none(),
                                                     |p| p.parse_token_tree());
 
-                    let mac = MacInvocTT(name, tts, EMPTY_CTXT);
+                    let mac = MacInvocTT(ident_to_path(id_span,id), tts, EMPTY_CTXT);
                     pat = ast::PatMac(codemap::Spanned {node: mac, span: self.span});
                 } else {
                     let sub = if self.eat(&token::AT) {
@@ -3038,7 +3040,7 @@ pub fn parse_pat(&mut self) -> Gc<Pat> {
                         // or just foo
                         None
                     };
-                    pat = PatIdent(BindByValue(MutImmutable), name, sub);
+                    pat = PatIdent(BindByValue(MutImmutable), pth1, sub);
                 }
             } else {
                 // parse an enum pat
@@ -3084,8 +3086,11 @@ pub fn parse_pat(&mut self) -> Gc<Pat> {
                                   // or an identifier pattern, resolve
                                   // will sort it out:
                                   pat = PatIdent(BindByValue(MutImmutable),
-                                                  enum_path,
-                                                  None);
+                                                 codemap::Spanned{
+                                                    span: enum_path.span,
+                                                    node: enum_path.segments.get(0)
+                                                           .identifier},
+                                                 None);
                               } else {
                                   pat = PatEnum(enum_path, Some(args));
                               }
@@ -3115,7 +3120,7 @@ fn parse_pat_ident(&mut self,
                             "expected identifier, found path");
         }
         // why a path here, and not just an identifier?
-        let name = self.parse_path(NoTypesAllowed).path;
+        let name = codemap::Spanned{span: self.last_span, node: self.parse_ident()};
         let sub = if self.eat(&token::AT) {
             Some(self.parse_pat())
         } else {
@@ -3243,7 +3248,7 @@ fn check_expected_item(p: &mut Parser, found_attrs: bool) {
                 None      => {
                     // we only expect an ident if we didn't parse one
                     // above.
-                    let ident_str = if id == token::special_idents::invalid {
+                    let ident_str = if id.name == token::special_idents::invalid.name {
                         "identifier, "
                     } else {
                         ""
@@ -3263,7 +3268,7 @@ fn check_expected_item(p: &mut Parser, found_attrs: bool) {
             );
             let hi = self.span.hi;
 
-            if id == token::special_idents::invalid {
+            if id.name == token::special_idents::invalid.name {
                 return box(GC) spanned(lo, hi, StmtMac(
                     spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT)), false));
             } else {
index a9cf4fbd9f0f130855ce8c67d9bc5f0ab6f58a56..4660bb337ab23e1d46c4d8ad2fb608a214d5804c 100644 (file)
@@ -196,6 +196,10 @@ pub fn path_to_str(p: &ast::Path) -> String {
     to_str(|s| s.print_path(p, false))
 }
 
+pub fn ident_to_str(id: &ast::Ident) -> String {
+    to_str(|s| s.print_ident(*id))
+}
+
 pub fn fun_to_str(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
                   opt_explicit_self: Option<ast::ExplicitSelf_>,
                   generics: &ast::Generics) -> String {
@@ -1705,7 +1709,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
         match pat.node {
             ast::PatWild => try!(word(&mut self.s, "_")),
             ast::PatWildMulti => try!(word(&mut self.s, "..")),
-            ast::PatIdent(binding_mode, ref path, sub) => {
+            ast::PatIdent(binding_mode, ref path1, sub) => {
                 match binding_mode {
                     ast::BindByRef(mutbl) => {
                         try!(self.word_nbsp("ref"));
@@ -1716,7 +1720,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
                         try!(self.word_nbsp("mut"));
                     }
                 }
-                try!(self.print_path(path, true));
+                try!(self.print_ident(path1.node));
                 match sub {
                     Some(ref p) => {
                         try!(word(&mut self.s, "@"));
@@ -2148,9 +2152,8 @@ pub fn print_arg(&mut self, input: &ast::Arg) -> IoResult<()> {
             ast::TyInfer => try!(self.print_pat(&*input.pat)),
             _ => {
                 match input.pat.node {
-                    ast::PatIdent(_, ref path, _) if
-                        path.segments.len() == 1 &&
-                        path.segments.get(0).identifier.name ==
+                    ast::PatIdent(_, ref path1, _) if
+                        path1.node.name ==
                             parse::token::special_idents::invalid.name => {
                         // Do nothing.
                     }
index 6f0fc217533fc5070b25007d2bad6cfaa9aa9175..4ab064a88b7950d3ede7d4ab57d8c05591666205 100644 (file)
@@ -454,8 +454,8 @@ pub fn walk_pat<E: Clone, V: Visitor<E>>(visitor: &mut V, pattern: &Pat, env: E)
         PatRegion(ref subpattern) => {
             visitor.visit_pat(&**subpattern, env)
         }
-        PatIdent(_, ref path, ref optional_subpattern) => {
-            visitor.visit_path(path, pattern.id, env.clone());
+        PatIdent(_, ref pth1, ref optional_subpattern) => {
+            visitor.visit_ident(pth1.span, pth1.node, env.clone());
             match *optional_subpattern {
                 None => {}
                 Some(ref subpattern) => visitor.visit_pat(&**subpattern, env),
index 34d60ddbe9db9375416437d4f747508578bd2503..56694e28b666227e1a87c513d83c40c119e3c99e 100644 (file)
@@ -38,7 +38,7 @@
 //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![crate_id = "term#0.11.0-pre"]
+#![crate_id = "term#0.11.0"]
 #![experimental]
 #![comment = "Simple ANSI color library"]
 #![license = "MIT/ASL2"]
@@ -46,7 +46,7 @@
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(macro_rules, phase)]
index ec31ffc93f38e8c68c67171d3de5b19c5225ebc8..02f7ebc6d21c816d007b4a4f3c1cabb7e8c67172 100644 (file)
@@ -23,7 +23,7 @@
 // running tests while providing a base that other test frameworks may
 // build off of.
 
-#![crate_id = "test#0.11.0-pre"]
+#![crate_id = "test#0.11.0"]
 #![experimental]
 #![comment = "Rust internal test library only used by rustc"]
 #![license = "MIT/ASL2"]
@@ -31,7 +31,7 @@
 #![crate_type = "dylib"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/")]
+       html_root_url = "http://doc.rust-lang.org/0.11.0/")]
 
 #![feature(asm, macro_rules, phase)]
 
index f52a032961dd96a568628259f8d785e43ff21fbd..0e4de41959a33de9717bb41f8d73cdefac62a9a0 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Simple time handling.
 
-#![crate_id = "time#0.11.0-pre"]
+#![crate_id = "time#0.11.0"]
 #![experimental]
 
 #![crate_type = "rlib"]
@@ -18,7 +18,7 @@
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(phase)]
 
@@ -316,10 +316,24 @@ pub fn to_utc(&self) -> Tm {
     }
 
     /**
-     * Return a string of the current time in the form
-     * "Thu Jan  1 00:00:00 1970".
+     * Returns a time string formatted according to the `asctime` format in ISO
+     * C, in the local timezone.
+     *
+     * Example: "Thu Jan  1 00:00:00 1970"
+     */
+    pub fn ctime(&self) -> String {
+        self.to_local().asctime()
+    }
+
+    /**
+     * Returns a time string formatted according to the `asctime` format in ISO
+     * C.
+     *
+     * Example: "Thu Jan  1 00:00:00 1970"
      */
-    pub fn ctime(&self) -> String { self.strftime("%c") }
+    pub fn asctime(&self) -> String {
+        self.strftime("%c")
+    }
 
     /// Formats the time according to the format string.
     pub fn strftime(&self, format: &str) -> String {
@@ -330,7 +344,7 @@ pub fn strftime(&self, format: &str) -> String {
      * Returns a time string formatted according to RFC 822.
      *
      * local: "Thu, 22 Mar 2012 07:53:18 PST"
-     * utc:   "Thu, 22 Mar 2012 14:53:18 UTC"
+     * utc:   "Thu, 22 Mar 2012 14:53:18 GMT"
      */
     pub fn rfc822(&self) -> String {
         if self.tm_gmtoff == 0_i32 {
@@ -351,7 +365,8 @@ pub fn rfc822z(&self) -> String {
     }
 
     /**
-     * Returns a time string formatted according to ISO 8601.
+     * Returns a time string formatted according to RFC 3999. RFC 3999 is
+     * compatible with ISO 8601.
      *
      * local: "2012-02-22T07:53:18-07:00"
      * utc:   "2012-02-22T14:53:18Z"
@@ -1371,6 +1386,19 @@ fn test(s: &str, format: &str) -> bool {
         assert_eq!(strptime("360", "%Y-%m-%d"), Err("Invalid year".to_string()))
     }
 
+    fn test_asctime() {
+        set_time_zone();
+
+        let time = Timespec::new(1234567890, 54321);
+        let utc   = at_utc(time);
+        let local = at(time);
+
+        debug!("test_ctime: {:?} {:?}", utc.asctime(), local.asctime());
+
+        assert_eq!(utc.asctime(), "Fri Feb 13 23:31:30 2009".to_string());
+        assert_eq!(local.asctime(), "Fri Feb 13 15:31:30 2009".to_string());
+    }
+
     fn test_ctime() {
         set_time_zone();
 
@@ -1380,7 +1408,7 @@ fn test_ctime() {
 
         debug!("test_ctime: {:?} {:?}", utc.ctime(), local.ctime());
 
-        assert_eq!(utc.ctime(), "Fri Feb 13 23:31:30 2009".to_string());
+        assert_eq!(utc.ctime(), "Fri Feb 13 15:31:30 2009".to_string());
         assert_eq!(local.ctime(), "Fri Feb 13 15:31:30 2009".to_string());
     }
 
@@ -1435,11 +1463,13 @@ fn test_strftime() {
         assert_eq!(local.strftime("%z"), "-0800".to_string());
         assert_eq!(local.strftime("%%"), "%".to_string());
 
+        assert_eq!(local.asctime(), "Fri Feb 13 15:31:30 2009".to_string());
         assert_eq!(local.ctime(), "Fri Feb 13 15:31:30 2009".to_string());
         assert_eq!(local.rfc822z(), "Fri, 13 Feb 2009 15:31:30 -0800".to_string());
         assert_eq!(local.rfc3339(), "2009-02-13T15:31:30-08:00".to_string());
 
-        assert_eq!(utc.ctime(), "Fri Feb 13 23:31:30 2009".to_string());
+        assert_eq!(utc.asctime(), "Fri Feb 13 23:31:30 2009".to_string());
+        assert_eq!(utc.ctime(), "Fri Feb 13 15:31:30 2009".to_string());
         assert_eq!(utc.rfc822(), "Fri, 13 Feb 2009 23:31:30 GMT".to_string());
         assert_eq!(utc.rfc822z(), "Fri, 13 Feb 2009 23:31:30 -0000".to_string());
         assert_eq!(utc.rfc3339(), "2009-02-13T23:31:30Z".to_string());
@@ -1488,6 +1518,7 @@ fn run_tests() {
         test_to_timespec();
         test_conversions();
         test_strptime();
+        test_asctime();
         test_ctime();
         test_strftime();
         test_timespec_eq_ord();
index 577a1e8ea9e54957d1fef5952909c7251bac25af..a60cc8e992b4d58592ee11818f5a4ee84b90e207 100644 (file)
 
 //! Types/fns concerning URLs (see RFC 3986)
 
-#![crate_id = "url#0.11.0-pre"]
+#![crate_id = "url#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![feature(default_type_params)]
 
index 0e73256893e9cc1c06450b755c3fc6ccdccbdc2d..297afe4aa598e4b21ac30e5c7a55331b1fb6daa5 100644 (file)
@@ -54,14 +54,14 @@ fn main() {
 
 */
 
-#![crate_id = "uuid#0.11.0-pre"]
+#![crate_id = "uuid#0.11.0"]
 #![experimental]
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 #![license = "MIT/ASL2"]
 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/",
+       html_root_url = "http://doc.rust-lang.org/0.11.0/",
        html_playground_url = "http://play.rust-lang.org/")]
 
 #![feature(default_type_params)]
index 4491adc74bd65d9f8610e7d76d125ec1265253b2..8a48e483029da5a265b1f7251554ca17a2c01751 100644 (file)
@@ -10,5 +10,5 @@
 
 // no-prefer-dynamic
 
-#![crate_id = "url#0.11.0-pre"]
+#![crate_id = "url#0.11.0"]
 #![crate_type = "dylib"]
index d921aeda3e01a99195b832228055e64570dcaaa5..0deece53451ee84a127f70cf7c13e8690916e267 100644 (file)
@@ -10,5 +10,5 @@
 
 // no-prefer-dynamic
 
-#![crate_id = "url#0.11.0-pre"]
+#![crate_id = "url#0.11.0"]
 #![crate_type = "rlib"]
diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs
new file mode 100644 (file)
index 0000000..349a203
--- /dev/null
@@ -0,0 +1,74 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(overloaded_calls)]
+
+use std::ops::{Fn, FnMut, FnOnce};
+
+struct SFn {
+    x: int,
+    y: int,
+}
+
+impl Fn<(int,),int> for SFn {
+    fn call(&self, (z,): (int,)) -> int {
+        self.x * self.y * z
+    }
+}
+
+struct SFnMut {
+    x: int,
+    y: int,
+}
+
+impl FnMut<(int,),int> for SFnMut {
+    fn call_mut(&mut self, (z,): (int,)) -> int {
+        self.x * self.y * z
+    }
+}
+
+struct SFnOnce {
+    x: String,
+}
+
+impl FnOnce<(String,),uint> for SFnOnce {
+    fn call_once(self, (z,): (String,)) -> uint {
+        self.x.len() + z.len()
+    }
+}
+
+fn f() {
+    let mut s = SFn {
+        x: 1,
+        y: 2,
+    };
+    let sp = &mut s;
+    s(3);   //~ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+}
+
+fn g() {
+    let s = SFnMut {
+        x: 1,
+        y: 2,
+    };
+    s(3);   //~ ERROR cannot borrow immutable local variable `s` as mutable
+}
+
+fn h() {
+    let s = SFnOnce {
+        x: "hello".to_string(),
+    };
+    s(" world".to_string());
+    s(" world".to_string());    //~ ERROR use of moved value: `s`
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/issue-10536.rs b/src/test/compile-fail/issue-10536.rs
new file mode 100644 (file)
index 0000000..36afc72
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// We only want to assert that this doesn't ICE, we don't particularly care
+// about whether it nor it fails to compile.
+
+// error-pattern:
+
+#![feature(macro_rules)]
+
+macro_rules! foo{
+    () => {{
+        macro_rules! bar{() => (())}
+        1
+    }}
+}
+
+pub fn main() {
+    foo!();
+
+    assert!({one! two()});
+
+    // regardless of whether nested macro_rules works, the following should at
+    // least throw a conventional error.
+    assert!({one! two});
+}
+
diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs
new file mode 100644 (file)
index 0000000..48e1bdd
--- /dev/null
@@ -0,0 +1,39 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Issue #14061: tests the interaction between generic implementation
+// parameter bounds and trait objects.
+
+struct S<T>;
+
+trait Gettable<T> {}
+
+impl<T: Send + Copy> Gettable<T> for S<T> {}
+
+fn f<T>(val: T) {
+    let t: S<T> = S;
+    let a = &t as &Gettable<T>;
+    //~^ ERROR instantiating a type parameter with an incompatible type `T`
+    let a: &Gettable<T> = &t;
+    //~^ ERROR instantiating a type parameter with an incompatible type `T`
+}
+
+fn main() {
+    let t: S<&int> = S;
+    let a = &t as &Gettable<&int>;
+    //~^ ERROR instantiating a type parameter with an incompatible type `&int`
+    let t: Box<S<String>> = box S;
+    let a = t as Box<Gettable<String>>;
+    //~^ ERROR instantiating a type parameter with an incompatible type
+    let t: Box<S<String>> = box S;
+    let a: Box<Gettable<String>> = t;
+    //~^ ERROR instantiating a type parameter with an incompatible type
+}
+
diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs
new file mode 100644 (file)
index 0000000..eec1168
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// Make sure rustc checks the type parameter bounds in implementations of traits,
+// see #2687
+
+trait A {}
+
+trait B: A {}
+
+trait C: A {}
+
+trait Foo {
+    fn test_error1_fn<T: Eq>(&self);
+    fn test_error2_fn<T: Eq + Ord>(&self);
+    fn test_error3_fn<T: Eq + Ord>(&self);
+    fn test3_fn<T: Eq + Ord>(&self);
+    fn test4_fn<T: Eq + Ord>(&self);
+    fn test_error5_fn<T: A>(&self);
+    fn test6_fn<T: A + Eq>(&self);
+    fn test_error7_fn<T: A>(&self);
+    fn test_error8_fn<T: B>(&self);
+}
+
+impl Foo for int {
+    // invalid bound for T, was defined as Eq in trait
+    fn test_error1_fn<T: Ord>(&self) {}
+    //~^ ERROR in method `test_error1_fn`, type parameter 0 requires bound `core::cmp::Ord`
+
+    // invalid bound for T, was defined as Eq + Ord in trait
+    fn test_error2_fn<T: Eq + B>(&self) {}
+    //~^ ERROR in method `test_error2_fn`, type parameter 0 requires bound `B`
+
+    // invalid bound for T, was defined as Eq + Ord in trait
+    fn test_error3_fn<T: B + Eq>(&self) {}
+    //~^ ERROR in method `test_error3_fn`, type parameter 0 requires bound `B`
+
+    // multiple bounds, same order as in trait
+    fn test3_fn<T: Ord + Eq>(&self) {}
+
+    // multiple bounds, different order as in trait
+    fn test4_fn<T: Eq + Ord>(&self) {}
+
+    // parameters in impls must be equal or more general than in the defining trait
+    fn test_error5_fn<T: B>(&self) {}
+    //~^ ERROR in method `test_error5_fn`, type parameter 0 requires bound `B`
+
+    // bound `std::cmp::Eq` not enforced by this implementation, but this is OK
+    fn test6_fn<T: A>(&self) {}
+
+    fn test_error7_fn<T: A + Eq>(&self) {}
+    //~^ ERROR in method `test_error7_fn`, type parameter 0 requires bound `core::cmp::Eq`
+
+    fn test_error8_fn<T: C>(&self) {}
+    //~^ ERROR in method `test_error8_fn`, type parameter 0 requires bound `C`
+}
+
+
+trait Getter<T> { }
+
+trait Trait {
+    fn method<G:Getter<int>>();
+}
+
+impl Trait for uint {
+    fn method<G: Getter<uint>>() {}
+    //~^ ERROR in method `method`, type parameter 0 requires bound `Getter<uint>`
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs
new file mode 100644 (file)
index 0000000..a970a86
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Issue #5886: a complex instance of issue #2687.
+
+trait Iterator<A> {
+    fn next(&mut self) -> Option<A>;
+}
+
+trait IteratorUtil<A> {
+    fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
+}
+
+impl<A, T: Iterator<A>> IteratorUtil<A> for T {
+    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
+    //~^ ERROR in method `zip`, type parameter 1 requires bound `Iterator<B>`
+        ZipIterator{a: self, b: other}
+    }
+}
+
+struct ZipIterator<T, U> {
+    a: T, b: U
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/type-params-in-different-spaces-1.rs b/src/test/compile-fail/type-params-in-different-spaces-1.rs
new file mode 100644 (file)
index 0000000..6e32e6e
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::num::Num;
+
+trait BrokenAdd: Num {
+    fn broken_add<T>(&self, rhs: T) -> Self {
+        *self + rhs //~ ERROR mismatched types
+    }
+}
+
+impl<T: Num> BrokenAdd for T {}
+
+pub fn main() {
+    let foo: u8 = 0u8;
+    let x: u8 = foo.broken_add("hello darkness my old friend".to_string());
+    println!("{}", x);
+}
diff --git a/src/test/compile-fail/type-params-in-different-spaces-2.rs b/src/test/compile-fail/type-params-in-different-spaces-2.rs
new file mode 100644 (file)
index 0000000..955efee
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tr<T> {
+    fn op(T) -> Self;
+}
+
+// these compile as if Self: Tr<U>, even tho only Self: Tr<Self or T>
+trait A:    Tr<Self> {
+    fn test<U>(u: U) -> Self {
+        Tr::op(u)   //~ ERROR expected Tr<U>, but found Tr<Self>
+    }
+}
+trait B<T>: Tr<T> {
+    fn test<U>(u: U) -> Self {
+        Tr::op(u)   //~ ERROR expected Tr<U>, but found Tr<T>
+    }
+}
+
+impl<T> Tr<T> for T {
+    fn op(t: T) -> T { t }
+}
+impl<T> A for T {}
+
+fn main() {
+    std::io::println(A::test((&7306634593706211700, 8)));
+}
+
diff --git a/src/test/compile-fail/type-params-in-different-spaces-3.rs b/src/test/compile-fail/type-params-in-different-spaces-3.rs
new file mode 100644 (file)
index 0000000..a3d69d5
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Tr {
+    fn test<X>(u: X) -> Self {
+        u   //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
+
diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs
new file mode 100644 (file)
index 0000000..ac5fe83
--- /dev/null
@@ -0,0 +1,333 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+// ignore-lldb
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g
+// gdb-command:rbreak zzz
+// gdb-command:run
+// gdb-command:finish
+
+
+// STRUCTS
+// gdb-command:whatis simple_struct
+// gdb-check:type = struct Struct1
+
+// gdb-command:whatis generic_struct1
+// gdb-check:type = struct GenericStruct<type-names::Mod1::Struct2, type-names::Mod1::Mod2::Struct3>
+
+// gdb-command:whatis generic_struct2
+// gdb-check:type = struct GenericStruct<type-names::Struct1, extern "fastcall" fn(int) -> uint>
+
+// gdb-command:whatis mod_struct
+// gdb-check:type = struct Struct2
+
+
+// ENUMS
+// gdb-command:whatis simple_enum_1
+// gdb-check:type = union Enum1
+
+// gdb-command:whatis simple_enum_2
+// gdb-check:type = union Enum1
+
+// gdb-command:whatis simple_enum_3
+// gdb-check:type = union Enum2
+
+// gdb-command:whatis generic_enum_1
+// gdb-check:type = union Enum3<type-names::Mod1::Struct2>
+
+// gdb-command:whatis generic_enum_2
+// gdb-check:type = union Enum3<type-names::Struct1>
+
+
+// TUPLES
+// gdb-command:whatis tuple1
+// gdb-check:type = struct (u32, type-names::Struct1, type-names::Mod1::Mod2::Enum3<type-names::Mod1::Struct2>)
+
+// gdb-command:whatis tuple2
+// gdb-check:type = struct ((type-names::Struct1, type-names::Mod1::Mod2::Struct3), type-names::Mod1::Enum2, char)
+
+
+// BOX
+// gdb-command:whatis box1
+// gdb-check:type = struct (Box<f32>, i32)
+
+// gdb-command:whatis box2
+// gdb-check:type = struct (Box<type-names::Mod1::Mod2::Enum3<f32>>, i32)
+
+
+// REFERENCES
+// gdb-command:whatis ref1
+// gdb-check:type = struct (&type-names::Struct1, i32)
+
+// gdb-command:whatis ref2
+// gdb-check:type = struct (&type-names::GenericStruct<char, type-names::Struct1>, i32)
+
+// gdb-command:whatis mut_ref1
+// gdb-check:type = struct (&mut type-names::Struct1, i32)
+
+// gdb-command:whatis mut_ref2
+// gdb-check:type = struct (&mut type-names::GenericStruct<type-names::Mod1::Enum2, f64>, i32)
+
+
+// RAW POINTERS
+// gdb-command:whatis mut_ptr1
+// gdb-check:type = struct (*mut type-names::Struct1, int)
+
+// gdb-command:whatis mut_ptr2
+// gdb-check:type = struct (*mut int, int)
+
+// gdb-command:whatis mut_ptr3
+// gdb-check:type = struct (*mut type-names::Mod1::Mod2::Enum3<type-names::Struct1>, int)
+
+// gdb-command:whatis const_ptr1
+// gdb-check:type = struct (*const type-names::Struct1, int)
+
+// gdb-command:whatis const_ptr2
+// gdb-check:type = struct (*const int, int)
+
+// gdb-command:whatis const_ptr3
+// gdb-check:type = struct (*const type-names::Mod1::Mod2::Enum3<type-names::Struct1>, int)
+
+
+// VECTORS
+// gdb-command:whatis fixed_size_vec1
+// gdb-check:type = struct ([type-names::Struct1, ..3], i16)
+
+// gdb-command:whatis fixed_size_vec2
+// gdb-check:type = struct ([uint, ..3], i16)
+
+// gdb-command:whatis slice1
+// gdb-check:type = struct &[uint]
+
+// gdb-command:whatis slice2
+// gdb-check:type = struct &[type-names::Mod1::Enum2]
+
+
+// TRAITS
+// gdb-command:whatis box_trait
+// gdb-check:type = struct Box<Trait1>
+
+// gdb-command:whatis ref_trait
+// gdb-check:type = struct &Trait1
+
+// gdb-command:whatis mut_ref_trait
+// gdb-check:type = struct &mut Trait1
+
+// gdb-command:whatis generic_box_trait
+// gdb-check:type = struct Box<Trait2<i32, type-names::Mod1::Struct2>>
+
+// gdb-command:whatis generic_ref_trait
+// gdb-check:type = struct &Trait2<type-names::Struct1, type-names::Struct1>
+
+// gdb-command:whatis generic_mut_ref_trait
+// gdb-check:type = struct &mut Trait2<type-names::Mod1::Mod2::Struct3, type-names::GenericStruct<uint, int>>
+
+
+// BARE FUNCTIONS
+// gdb-command:whatis rust_fn
+// gdb-check:type = struct (fn(core::option::Option<int>, core::option::Option<&type-names::Mod1::Struct2>), uint)
+
+// gdb-command:whatis extern_c_fn
+// gdb-check:type = struct (extern "C" fn(int), uint)
+
+// gdb-command:whatis unsafe_fn
+// gdb-check:type = struct (unsafe fn(core::result::Result<char, f64>), uint)
+
+// gdb-command:whatis extern_stdcall_fn
+// gdb-check:type = struct (extern "stdcall" fn(), uint)
+
+// gdb-command:whatis rust_fn_with_return_value
+// gdb-check:type = struct (fn(f64) -> uint, uint)
+
+// gdb-command:whatis extern_c_fn_with_return_value
+// gdb-check:type = struct (extern "C" fn() -> type-names::Struct1, uint)
+
+// gdb-command:whatis unsafe_fn_with_return_value
+// gdb-check:type = struct (unsafe fn(type-names::GenericStruct<u16, u8>) -> type-names::Mod1::Struct2, uint)
+
+// gdb-command:whatis extern_stdcall_fn_with_return_value
+// gdb-check:type = struct (extern "stdcall" fn(Box<int>) -> uint, uint)
+
+// gdb-command:whatis generic_function_int
+// gdb-check:type = struct (fn(int) -> int, uint)
+
+// gdb-command:whatis generic_function_struct3
+// gdb-check:type = struct (fn(type-names::Mod1::Mod2::Struct3) -> type-names::Mod1::Mod2::Struct3, uint)
+
+// gdb-command:whatis variadic_function
+// gdb-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> int, uint)
+
+
+// CLOSURES
+// gdb-command:whatis some_proc
+// gdb-check:type = struct (once proc(int, u8) -> (int, u8), uint)
+
+// gdb-command:whatis stack_closure1
+// gdb-check:type = struct (&mut|int|, uint)
+
+// gdb-command:whatis stack_closure2
+// gdb-check:type = struct (&mut|i8, f32| -> f32, uint)
+
+use std::ptr;
+
+struct Struct1;
+struct GenericStruct<T1, T2>;
+
+enum Enum1 {
+    Variant1_1,
+    Variant1_2(int)
+}
+
+mod Mod1 {
+    pub struct Struct2;
+
+    pub enum Enum2 {
+        Variant2_1,
+        Variant2_2(super::Struct1)
+    }
+
+    pub mod Mod2 {
+        pub struct Struct3;
+
+        pub enum Enum3<T> {
+            Variant3_1,
+            Variant3_2(T),
+        }
+    }
+}
+
+trait Trait1 { }
+trait Trait2<T1, T2> { }
+
+impl Trait1 for int {}
+impl<T1, T2> Trait2<T1, T2> for int {}
+
+fn rust_fn(_: Option<int>, _: Option<&Mod1::Struct2>) {}
+extern "C" fn extern_c_fn(_: int) {}
+unsafe fn unsafe_fn(_: Result<char, f64>) {}
+extern "stdcall" fn extern_stdcall_fn() {}
+
+fn rust_fn_with_return_value(_: f64) -> uint { 4 }
+extern "C" fn extern_c_fn_with_return_value() -> Struct1 { Struct1 }
+unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> Mod1::Struct2 { Mod1::Struct2 }
+extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<int>) -> uint { 0 }
+
+fn generic_function<T>(x: T) -> T { x }
+
+extern {
+    fn printf(_:*const u8, ...) -> int;
+}
+
+// In many of the cases below, the type that is actually under test is wrapped
+// in a tuple, e.g. Box<T>, references, raw pointers, fixed-size vectors, ...
+// This is because GDB will not print the type name from DWARF debuginfo for
+// some kinds of types (pointers, arrays, functions, ...)
+// Since tuples are structs as far as GDB is concerned, their name will be
+// printed correctly, so the tests below just construct a tuple type that will
+// then *contain* the type name that we want to see.
+fn main() {
+
+    // Structs
+    let simple_struct = Struct1;
+    let generic_struct1: GenericStruct<Mod1::Struct2, Mod1::Mod2::Struct3> = GenericStruct;
+    let generic_struct2: GenericStruct<Struct1, extern "fastcall" fn(int) -> uint> = GenericStruct;
+    let mod_struct = Mod1::Struct2;
+
+    // Enums
+    let simple_enum_1 = Variant1_1;
+    let simple_enum_2 = Variant1_2(0);
+    let simple_enum_3 = Mod1::Variant2_2(Struct1);
+
+    let generic_enum_1: Mod1::Mod2::Enum3<Mod1::Struct2> = Mod1::Mod2::Variant3_1;
+    let generic_enum_2 = Mod1::Mod2::Variant3_2(Struct1);
+
+    // Tuples
+    let tuple1 = (8u32, Struct1, Mod1::Mod2::Variant3_2(Mod1::Struct2));
+    let tuple2 = ((Struct1, Mod1::Mod2::Struct3), Mod1::Variant2_1, 'x');
+
+    // Box
+    let box1 = (box 1f32, 0i32);
+    let box2 = (box Mod1::Mod2::Variant3_2(1f32), 0i32);
+
+    // References
+    let ref1 = (&Struct1, 0i32);
+    let ref2 = (&GenericStruct::<char, Struct1>, 0i32);
+
+    let mut mut_struct1 = Struct1;
+    let mut mut_generic_struct = GenericStruct::<Mod1::Enum2, f64>;
+    let mut_ref1 = (&mut mut_struct1, 0i32);
+    let mut_ref2 = (&mut mut_generic_struct, 0i32);
+
+    // Raw Pointers
+    let mut_ptr1: (*mut Struct1, int) = (ptr::mut_null(), 0);
+    let mut_ptr2: (*mut int, int) = (ptr::mut_null(), 0);
+    let mut_ptr3: (*mut Mod1::Mod2::Enum3<Struct1>, int) = (ptr::mut_null(), 0);
+
+    let const_ptr1: (*const Struct1, int) = (ptr::null(), 0);
+    let const_ptr2: (*const int, int) = (ptr::null(), 0);
+    let const_ptr3: (*const Mod1::Mod2::Enum3<Struct1>, int) = (ptr::null(), 0);
+
+    // Vectors
+    let fixed_size_vec1 = ([Struct1, Struct1, Struct1], 0i16);
+    let fixed_size_vec2 = ([0u, 1u, 2u], 0i16);
+
+    let vec1 = vec![0u, 2u, 3u];
+    let slice1 = vec1.as_slice();
+    let vec2 = vec![Mod1::Variant2_2(Struct1)];
+    let slice2 = vec2.as_slice();
+
+    // Trait Objects
+    let box_trait = (box 0i) as Box<Trait1>;
+    let ref_trait = &0i as &Trait1;
+    let mut mut_int1 = 0i;
+    let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
+
+    let generic_box_trait = (box 0i) as Box<Trait2<i32, Mod1::Struct2>>;
+    let generic_ref_trait  = (&0i) as &Trait2<Struct1, Struct1>;
+
+    let mut generic_mut_ref_trait_impl = 0i;
+    let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
+        &mut Trait2<Mod1::Mod2::Struct3, GenericStruct<uint, int>>;
+
+    // Bare Functions
+    let rust_fn = (rust_fn, 0u);
+    let extern_c_fn = (extern_c_fn, 0u);
+    let unsafe_fn = (unsafe_fn, 0u);
+    let extern_stdcall_fn = (extern_stdcall_fn, 0u);
+
+    let rust_fn_with_return_value = (rust_fn_with_return_value, 0u);
+    let extern_c_fn_with_return_value = (extern_c_fn_with_return_value, 0u);
+    let unsafe_fn_with_return_value = (unsafe_fn_with_return_value, 0u);
+    let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0u);
+
+    let generic_function_int = (generic_function::<int>, 0u);
+    let generic_function_struct3 = (generic_function::<Mod1::Mod2::Struct3>, 0u);
+
+    let variadic_function = (printf, 0u);
+
+    // Closures
+    // I (mw) am a bit unclear about the current state of closures, their
+    // various forms (boxed, unboxed, proc, capture-by-ref, by-val, once) and
+    // how that maps to rustc's internal representation of these forms.
+    // Once closures have reached their 1.0 form, the tests below should
+    // probably be expanded.
+    let some_proc = (proc(a:int, b:u8) (a, b), 0u);
+
+    let stack_closure1 = (|x:int| {}, 0u);
+    let stack_closure2 = (|x:i8, y: f32| { (x as f32) + y }, 0u);
+
+    zzz();
+}
+
+#[inline(never)]
+fn zzz() { () }
index a72e24cf2c3857441a8c33330ada8c321f0b5056..a44481b4b7f23d75f339fa247fe7729c05d8db14 100644 (file)
@@ -1,7 +1,7 @@
 -include ../tools.mk
 
 all:
-       [ `$(RUSTC) --crate-id crate.rs` = "foo#0.11.0-pre" ]
+       [ `$(RUSTC) --crate-id crate.rs` = "foo#0.11.0" ]
        [ `$(RUSTC) --crate-name crate.rs` = "foo" ]
        [ `$(RUSTC) --crate-file-name crate.rs` = "foo" ]
        [ `$(RUSTC) --crate-file-name --crate-type=lib --test crate.rs` = "foo" ]
index 31446a763e2dd978798a37ea766e35d1ce779a64..9faa7c016284bf054eec1849d20b436bb524263a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_id = "foo#0.11.0-pre"]
+#![crate_id = "foo#0.11.0"]
 
 // Querying about the crate metadata should *not* parse the entire crate, it
 // only needs the crate attributes (which are guaranteed to be at the top) be
diff --git a/src/test/run-pass/issue-12285.rs b/src/test/run-pass/issue-12285.rs
new file mode 100644 (file)
index 0000000..5637712
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S;
+
+fn main() {
+    match Some(&S) {
+        Some(&S) => {},
+        _x => unreachable!()
+    }
+    match Some(&S) {
+        Some(&S) => {},
+        None => unreachable!()
+    }
+}
diff --git a/src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs b/src/test/run-pass/trait-bounds-impl-comparison-duplicates.rs
new file mode 100644 (file)
index 0000000..55ad22d
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Tests that type parameter bounds on an implementation need not match the
+// trait exactly, as long as the implementation doesn't demand *more* bounds
+// than the trait.
+
+trait A {
+    fn foo<T: Eq + Ord>(&self);
+}
+
+impl A for int {
+    fn foo<T: Ord + Ord>(&self) {}
+}
+
+fn main() {}
+
+
index de22f428713f71be7e15441b422dc729b7415502..3f152cc10610f3ae1894c654f09f4d6a9a9f33ed 100644 (file)
@@ -15,7 +15,7 @@
 #![no_std]
 extern crate std;
 extern crate zed = "std";
-extern crate bar = "std#0.11.0-pre";
+extern crate bar = "std#0.11.0";
 
 
 use std::str;