]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #23119: nikomatsakis/issue-23116-ref-mut
authorAlex Crichton <alex@alexcrichton.com>
Mon, 23 Mar 2015 22:07:19 +0000 (15:07 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 23 Mar 2015 22:07:19 +0000 (15:07 -0700)
Don't allow upcasting to a supertype in the type of the match discriminant. Fixes #23116.

This is a [breaking-change] in that it closes a type hole that previously existed.

r? @pnkfelix

23 files changed:
man/rustc.1
src/doc/reference.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/compound-data-types.md
src/doc/trpl/concurrency.md
src/doc/trpl/crates-and-modules.md
src/doc/trpl/standard-input.md
src/libcollections/btree/map.rs
src/librustc/README.md [new file with mode: 0644]
src/librustc/README.txt [deleted file]
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/README.txt
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_typeck/check/upvar.rs
src/libstd/collections/hash/map.rs
src/libstd/sync/mutex.rs
src/test/compile-fail-fulldeps/gated-macro-reexports.rs [new file with mode: 0644]
src/test/compile-fail/gated-box-patterns.rs [new file with mode: 0644]
src/test/compile-fail/gated-box-syntax.rs [new file with mode: 0644]
src/test/compile-fail/gated-simd-ffi.rs [new file with mode: 0644]
src/test/run-pass/issue-23550.rs [new file with mode: 0644]

index 33ef3f9ee4acba4e3078a5a3afb8ac6ccf3849d5..b15829db431dfef89f5d7b6a4fb6217c98874b3b 100644 (file)
@@ -242,7 +242,7 @@ full debug info with variable and type information.
 \fBopt\-level\fR=\fIVAL\fR
 Optimize with possible levels 0\[en]3
 
-.SH ENVIRONMENT VARIABLES
+.SH ENVIRONMENT
 
 Some of these affect the output of the compiler, while others affect programs
 which link to the standard library.
index 92573d792177362ad724278699f3d9d13cd2839c..415ec4e4fbf0a4bc661caa3ee26558908310b851 100644 (file)
@@ -1982,7 +1982,7 @@ the namespace hierarchy as it normally would.
 ## Attributes
 
 ```{.ebnf .gram}
-attribute : "#!" ? '[' meta_item ']' ;
+attribute : '#' '!' ? '[' meta_item ']' ;
 meta_item : ident [ '=' literal
                   | '(' meta_seq ')' ] ? ;
 meta_seq : meta_item [ ',' meta_seq ] ? ;
@@ -3158,7 +3158,7 @@ ten_times(|j| println!("hello, {}", j));
 ### While loops
 
 ```{.ebnf .gram}
-while_expr : "while" no_struct_literal_expr '{' block '}' ;
+while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
 ```
 
 A `while` loop begins by evaluating the boolean loop conditional expression.
@@ -3223,7 +3223,7 @@ A `continue` expression is only permitted in the body of a loop.
 ### For expressions
 
 ```{.ebnf .gram}
-for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ;
+for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
 ```
 
 A `for` expression is a syntactic construct for looping over elements provided
index 6ff51e8d1b92cb9af4426e41da40125362e1b150..76f8b6c97381818dc3a79b4e7aa87696d58a8377 100644 (file)
@@ -1,6 +1,6 @@
 # Summary
 
-* [I: The Basics](basic.md)
+* [The Basics](basic.md)
     * [Installing Rust](installing-rust.md)
     * [Hello, world!](hello-world.md)
     * [Hello, Cargo!](hello-cargo.md)
@@ -14,7 +14,7 @@
     * [Strings](strings.md)
     * [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md)
     * [Standard Input](standard-input.md)
-* [II: Intermediate Rust](intermediate.md)
+* [Intermediate Rust](intermediate.md)
     * [Crates and Modules](crates-and-modules.md)
     * [Testing](testing.md)
     * [Pointers](pointers.md)
@@ -31,7 +31,7 @@
     * [Concurrency](concurrency.md)
     * [Error Handling](error-handling.md)
     * [Documentation](documentation.md)
-* [III: Advanced Topics](advanced.md)
+* [Advanced Topics](advanced.md)
     * [FFI](ffi.md)
     * [Unsafe Code](unsafe.md)
     * [Advanced Macros](advanced-macros.md)
index e09922fd390a9b037cedaab162908449a42d2eb2..d531a22d0e0dd55d2b2a0d5d913b88f9d3912c73 100644 (file)
@@ -47,7 +47,7 @@ This pattern is very powerful, and we'll see it repeated more later.
 
 There are also a few things you can do with a tuple as a whole, without
 destructuring. You can assign one tuple into another, if they have the same
-contained types and arity. Tuples have the same arity when they have the same
+contained types and [arity]. Tuples have the same arity when they have the same
 length.
 
 ```rust
@@ -196,8 +196,9 @@ Now, we have actual names, rather than positions. Good names are important,
 and with a struct, we have actual names.
 
 There _is_ one case when a tuple struct is very useful, though, and that's a
-tuple struct with only one element. We call this a *newtype*, because it lets
-you create a new type that's similar to another one:
+tuple struct with only one element. We call this the *newtype* pattern, because
+it allows you to create a new type, distinct from that of its contained value
+and expressing its own semantic meaning:
 
 ```{rust}
 struct Inches(i32);
@@ -216,7 +217,7 @@ destructuring `let`, as we discussed previously in 'tuples.' In this case, the
 
 Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
 feature of Rust, and are used throughout the standard library. An `enum` is
-a type which ties a set of alternates to a specific name. For example, below
+a type which relates a set of alternates to a specific name. For example, below
 we define `Character` to be either a `Digit` or something else. These
 can be used via their fully scoped names: `Character::Other` (more about `::`
 below).
@@ -228,8 +229,8 @@ enum Character {
 }
 ```
 
-An `enum` variant can be defined as most normal types. Below are some example
-types which also would be allowed in an `enum`.
+Most normal types are allowed as the variant components of an `enum`. Here are
+some examples:
 
 ```rust
 struct Empty;
@@ -239,15 +240,15 @@ struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
 struct HeightDatabase(Vec<i32>);
 ```
 
-So you see that depending on the sub-datastructure, the `enum` variant, same as
-a struct, may or may not hold data. That is, in `Character`, `Digit` is a name
-tied to an `i32` where `Other` is just a name. However, the fact that they are
-distinct makes this very useful.
+You see that, depending on its type, an `enum` variant may or may not hold data.
+In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
+value, where `Other` is only a name. However, the fact that they represent
+distinct categories of `Character` is a very useful property.
 
-As with structures, enums don't by default have access to operators such as
-compare ( `==` and `!=`), binary operations (`*` and `+`), and order
-(`<` and `>=`). As such, using the previous `Character` type, the
-following code is invalid:
+As with structures, the variants of an enum by default are not comparable with
+equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not
+support other binary operations such as `*` and `+`. As such, the following code
+is invalid for the example `Character` type:
 
 ```{rust,ignore}
 // These assignments both succeed
@@ -265,9 +266,10 @@ let four_equals_ten = four == ten;
 ```
 
 This may seem rather limiting, but it's a limitation which we can overcome.
-There are two ways: by implementing equality ourselves, or by using the
-[`match`][match] keyword. We don't know enough about Rust to implement equality
-yet, but we can use the `Ordering` enum from the standard library, which does:
+There are two ways: by implementing equality ourselves, or by pattern matching
+variants with [`match`][match] expressions, which you'll learn in the next
+chapter. We don't know enough about Rust to implement equality yet, but we can
+use the `Ordering` enum from the standard library, which does:
 
 ```
 enum Ordering {
@@ -277,9 +279,8 @@ enum Ordering {
 }
 ```
 
-Because we did not define `Ordering`, we must import it (from the std
-library) with the `use` keyword. Here's an example of how `Ordering` is
-used:
+Because `Ordering` has already been defined for us, we will import it with the
+`use` keyword. Here's an example of how it is used:
 
 ```{rust}
 use std::cmp::Ordering;
@@ -313,17 +314,17 @@ the standard library if you need them.
 
 Okay, let's talk about the actual code in the example. `cmp` is a function that
 compares two things, and returns an `Ordering`. We return either
-`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if
-the two values are less, greater, or equal. Note that each variant of the
-`enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not
-`Greater`.
+`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on
+whether the first value is less than, greater than, or equal to the second. Note
+that each variant of the `enum` is namespaced under the `enum` itself: it's
+`Ordering::Greater`, not `Greater`.
 
 The `ordering` variable has the type `Ordering`, and so contains one of the
 three values. We then do a bunch of `if`/`else` comparisons to check which
 one it is.
 
-This `Ordering::Greater` notation is too long. Let's use `use` to import the
-`enum` variants instead. This will avoid full scoping:
+This `Ordering::Greater` notation is too long. Let's use another form of `use`
+to import the `enum` variants instead. This will avoid full scoping:
 
 ```{rust}
 use std::cmp::Ordering::{self, Equal, Less, Greater};
@@ -347,16 +348,18 @@ fn main() {
 ```
 
 Importing variants is convenient and compact, but can also cause name conflicts,
-so do this with caution. It's considered good style to rarely import variants
-for this reason.
+so do this with caution. For this reason, it's normally considered better style
+to `use` an enum rather than its variants directly.
 
-As you can see, `enum`s are quite a powerful tool for data representation, and are
-even more useful when they're [generic][generics] across types. Before we
-get to generics, though, let's talk about how to use them with pattern matching, a
-tool that will let us deconstruct this sum type (the type theory term for enums)
-in a very elegant way and avoid all these messy `if`/`else`s.
+As you can see, `enum`s are quite a powerful tool for data representation, and
+are even more useful when they're [generic][generics] across types. Before we
+get to generics, though, let's talk about how to use enums with pattern
+matching, a tool that will let us deconstruct sum types (the type theory term
+for enums) like `Ordering` in a very elegant way that avoids all these messy
+and brittle `if`/`else`s.
 
 
+[arity]: ./glossary.html#arity
 [match]: ./match.html
 [game]: ./guessing-game.html#comparing-guesses
 [generics]: ./generics.html
index 4a16db63950ddd0ff76983b8df988bea5b5ffc91..5d301cc0aef6ebbd31d1b78148ade07f75cdfd80 100644 (file)
@@ -40,14 +40,14 @@ us enforce that it can't leave the current thread.
 
 ### `Sync`
 
-The second of these two trait is called [`Sync`](../std/marker/trait.Sync.html).
+The second of these traits is called [`Sync`](../std/marker/trait.Sync.html).
 When a type `T` implements `Sync`, it indicates to the compiler that something
 of this type has no possibility of introducing memory unsafety when used from
 multiple threads concurrently.
 
 For example, sharing immutable data with an atomic reference count is
 threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`,
-so that it could be safely shared between threads.
+so it is safe to share between threads.
 
 These two traits allow you to use the type system to make strong guarantees
 about the properties of your code under concurrency. Before we demonstrate
@@ -69,7 +69,7 @@ fn main() {
 }
 ```
 
-The `Thread::scoped()` method accepts a closure, which is executed in a new
+The `thread::scoped()` method accepts a closure, which is executed in a new
 thread. It's called `scoped` because this thread returns a join guard:
 
 ```
@@ -208,10 +208,10 @@ Here's the error:
 
 ```text
 <anon>:11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
-<anon>:11         Thread::spawn(move || {
+<anon>:11         thread::spawn(move || {
                   ^~~~~~~~~~~~~
 <anon>:11:9: 11:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
-<anon>:11         Thread::spawn(move || {
+<anon>:11         thread::spawn(move || {
                   ^~~~~~~~~~~~~
 ```
 
@@ -322,7 +322,6 @@ While this channel is just sending a generic signal, we can send any data that
 is `Send` over the channel!
 
 ```
-use std::sync::{Arc, Mutex};
 use std::thread;
 use std::sync::mpsc;
 
index 65ff42ffdcef411804fc99d4a1967b1632d0a637..37785c030e6e5e4acc29b044690e1836089ffbef 100644 (file)
@@ -430,7 +430,7 @@ fn main() {
 }
 ```
 
-But it is not idiomatic. This is significantly more likely to introducing a
+But it is not idiomatic. This is significantly more likely to introduce a
 naming conflict. In our short program, it's not a big deal, but as it grows, it
 becomes a problem. If we have conflicting names, Rust will give a compilation
 error. For example, if we made the `japanese` functions public, and tried to do
index 794b1df7563de7cde12943cf122762f1265806e5..228891f9f052b3a33a59c5f5862155f933562ce8 100644 (file)
@@ -115,8 +115,9 @@ doesn't work, so we're okay with that. In most cases, we would want to handle
 the error case explicitly. `expect()` allows us to give an error message if
 this crash happens.
 
-We will cover the exact details of how all of this works later in the Guide.
-For now, this gives you enough of a basic understanding to work with.
+We will cover the exact details of how all of this works later in the Guide in
+[Error Handling]. For now, this gives you enough of a basic understanding to
+work with.
 
 Back to the code we were working on! Here's a refresher:
 
@@ -157,3 +158,6 @@ here.
 
 That's all you need to get basic input from the standard input! It's not too
 complicated, but there are a number of small parts.
+
+
+[Error Handling]: ./error-handling.html
index c7e1e3c91766ef297d71fbad17905910d2530c61..a9e1ce8d7ce50db9a5c0b3c3a5c75b561c0ba754 100644 (file)
@@ -24,7 +24,7 @@
 use core::fmt::Debug;
 use core::hash::{Hash, Hasher};
 use core::iter::{Map, FromIterator, IntoIterator};
-use core::ops::{Index, IndexMut};
+use core::ops::{Index};
 use core::{iter, fmt, mem, usize};
 use Bound::{self, Included, Excluded, Unbounded};
 
@@ -925,15 +925,6 @@ fn index(&self, key: &Q) -> &V {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
-    where K: Borrow<Q>, Q: Ord
-{
-    fn index_mut(&mut self, key: &Q) -> &mut V {
-        self.get_mut(key).expect("no entry found for key")
-    }
-}
-
 /// Genericises over how to get the correct type of iterator from the correct type
 /// of Node ownership.
 trait Traverse<N> {
diff --git a/src/librustc/README.md b/src/librustc/README.md
new file mode 100644 (file)
index 0000000..31812e1
--- /dev/null
@@ -0,0 +1,128 @@
+An informal guide to reading and working on the rustc compiler.
+==================================================================
+
+If you wish to expand on this document, or have a more experienced
+Rust contributor add anything else to it, please get in touch:
+
+* http://internals.rust-lang.org/
+* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
+
+or file a bug:
+
+https://github.com/rust-lang/rust/issues
+
+Your concerns are probably the same as someone else's.
+
+The crates of rustc
+===================
+
+Rustc consists of a number of crates, including `libsyntax`,
+`librustc`, `librustc_back`, `librustc_trans`, and `librustc_driver`
+(the names and divisions are not set in stone and may change;
+in general, a finer-grained division of crates is preferable):
+
+- `libsyntax` contains those things concerned purely with syntax â€“
+  that is, the AST, parser, pretty-printer, lexer, macro expander, and
+  utilities for traversing ASTs â€“ are in a separate crate called
+  "syntax", whose files are in `./../libsyntax`, where `.` is the
+  current directory (that is, the parent directory of front/, middle/,
+  back/, and so on).
+
+- `librustc` (the current directory) contains the high-level analysis
+  passes, such as the type checker, borrow checker, and so forth.
+  It is the heart of the compiler.
+
+- `librustc_back` contains some very low-level details that are
+  specific to different LLVM targets and so forth.
+
+- `librustc_trans` contains the code to convert from Rust IR into LLVM
+  IR, and then from LLVM IR into machine code, as well as the main
+  driver that orchestrates all the other passes and various other bits
+  of miscellany. In general it contains code that runs towards the
+  end of the compilation process.
+
+- `librustc_driver` invokes the compiler from `libsyntax`, then the
+  analysis phases from `librustc`, and finally the lowering and
+  codegen passes from `librustc_trans`.
+
+Roughly speaking the "order" of the three crates is as follows:
+
+    libsyntax -> librustc -> librustc_trans
+    |                                     |
+    +-----------------+-------------------+
+                      |
+              librustc_driver
+
+
+Modules in the rustc crate
+==========================
+
+The rustc crate itself consists of the following submodules
+(mostly, but not entirely, in their own directories):
+
+- session: options and data that pertain to the compilation session as
+  a whole
+- middle: middle-end: name resolution, typechecking, LLVM code
+  generation
+- metadata: encoder and decoder for data required by separate
+  compilation
+- plugin: infrastructure for compiler plugins
+- lint: infrastructure for compiler warnings
+- util: ubiquitous types and helper functions
+- lib: bindings to LLVM
+
+The entry-point for the compiler is main() in the librustc_trans
+crate.
+
+The 3 central data structures:
+------------------------------
+
+1. `./../libsyntax/ast.rs` defines the AST. The AST is treated as
+   immutable after parsing, but it depends on mutable context data
+   structures (mainly hash maps) to give it meaning.
+
+   - Many â€“ though not all â€“ nodes within this data structure are
+     wrapped in the type `spanned<T>`, meaning that the front-end has
+     marked the input coordinates of that node. The member `node` is
+     the data itself, the member `span` is the input location (file,
+     line, column; both low and high).
+
+   - Many other nodes within this data structure carry a
+     `def_id`. These nodes represent the 'target' of some name
+     reference elsewhere in the tree. When the AST is resolved, by
+     `middle/resolve.rs`, all names wind up acquiring a def that they
+     point to. So anything that can be pointed-to by a name winds
+     up with a `def_id`.
+
+2. `middle/ty.rs` defines the datatype `sty`. This is the type that
+   represents types after they have been resolved and normalized by
+   the middle-end. The typeck phase converts every ast type to a
+   `ty::sty`, and the latter is used to drive later phases of
+   compilation. Most variants in the `ast::ty` tag have a
+   corresponding variant in the `ty::sty` tag.
+
+3. `./../librustc_llvm/lib.rs` defines the exported types
+   `ValueRef`, `TypeRef`, `BasicBlockRef`, and several others.
+   Each of these is an opaque pointer to an LLVM type,
+   manipulated through the `lib::llvm` interface.
+
+
+Control and information flow within the compiler:
+-------------------------------------------------
+
+- main() in lib.rs assumes control on startup. Options are
+  parsed, platform is detected, etc.
+
+- `./../libsyntax/parse/parser.rs` parses the input files and produces
+  an AST that represents the input crate.
+
+- Multiple middle-end passes (`middle/resolve.rs`, `middle/typeck.rs`)
+  analyze the semantics of the resulting AST. Each pass generates new
+  information about the AST and stores it in various environment data
+  structures. The driver passes environments to each compiler pass
+  that needs to refer to them.
+
+- Finally, the `trans` module in `librustc_trans` translates the Rust
+  AST to LLVM bitcode in a type-directed way. When it's finished
+  synthesizing LLVM values, rustc asks LLVM to write them out in some
+  form (`.bc`, `.o`) and possibly run the system linker.
diff --git a/src/librustc/README.txt b/src/librustc/README.txt
deleted file mode 100644 (file)
index 9b36476..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-An informal guide to reading and working on the rustc compiler.
-==================================================================
-
-If you wish to expand on this document, or have a more experienced
-Rust contributor add anything else to it, please get in touch:
-
-* http://internals.rust-lang.org/
-* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
-
-or file a bug:
-
-https://github.com/rust-lang/rust/issues
-
-Your concerns are probably the same as someone else's.
-
-The crates of rustc
-===================
-
-Rustc consists of four crates altogether: `libsyntax`, `librustc`,
-`librustc_back`, and `librustc_trans` (the names and divisions are not
-set in stone and may change; in general, a finer-grained division of
-crates is preferable):
-
-- `libsyntax` contains those things concerned purely with syntax --
-  that is, the AST, parser, pretty-printer, lexer, macro expander, and
-  utilities for traversing ASTs -- are in a separate crate called
-  "syntax", whose files are in ./../libsyntax, where . is the current
-  directory (that is, the parent directory of front/, middle/, back/,
-  and so on).
-
-- `librustc` (the current directory) contains the high-level analysis
-  passes, such as the type checker, borrow checker, and so forth.
-  It is the heart of the compiler.
-
-- `librustc_back` contains some very low-level details that are
-  specific to different LLVM targets and so forth.
-
-- `librustc_trans` contains the code to convert from Rust IR into LLVM
-  IR, and then from LLVM IR into machine code, as well as the main
-  driver that orchestrates all the other passes and various other bits
-  of miscellany. In general it contains code that runs towards the
-  end of the compilation process.
-
-Roughly speaking the "order" of the three crates is as follows:
-
-    libsyntax -> librustc -> librustc_trans
-    |                                     |
-    +-----------------+-------------------+
-                      |
-             librustc_trans/driver
-
-Here the role of `librustc_trans/driver` is to invoke the compiler
-from libsyntax, then the analysis phases from librustc, and finally
-the lowering and codegen passes from librustc_trans.
-
-Modules in the rustc crate
-==========================
-
-The rustc crate itself consists of the following subdirectories
-(mostly, but not entirely, in their own directories):
-
-session  - options and data that pertain to the compilation session as a whole
-middle   - middle-end: name resolution, typechecking, LLVM code
-                  generation
-metadata - encoder and decoder for data required by
-                    separate compilation
-util     - ubiquitous types and helper functions
-lib      - bindings to LLVM
-
-The entry-point for the compiler is main() in the librustc_trans
-crate.
-
-The 3 central data structures:
-------------------------------
-
-#1: ./../libsyntax/ast.rs defines the AST. The AST is treated as immutable
-    after parsing, but it depends on mutable context data structures
-    (mainly hash maps) to give it meaning.
-
-      - Many -- though not all -- nodes within this data structure are
-        wrapped in the type `spanned<T>`, meaning that the front-end has
-        marked the input coordinates of that node. The member .node is
-        the data itself, the member .span is the input location (file,
-        line, column; both low and high).
-
-      - Many other nodes within this data structure carry a
-        def_id. These nodes represent the 'target' of some name
-        reference elsewhere in the tree. When the AST is resolved, by
-        middle/resolve.rs, all names wind up acquiring a def that they
-        point to. So anything that can be pointed-to by a name winds
-        up with a def_id.
-
-#2: middle/ty.rs defines the datatype sty.  This is the type that
-    represents types after they have been resolved and normalized by
-    the middle-end. The typeck phase converts every ast type to a
-    ty::sty, and the latter is used to drive later phases of
-    compilation.  Most variants in the ast::ty tag have a
-    corresponding variant in the ty::sty tag.
-
-#3: lib/llvm.rs (in librustc_trans) defines the exported types
-    ValueRef, TypeRef, BasicBlockRef, and several others. Each of
-    these is an opaque pointer to an LLVM type, manipulated through
-    the lib::llvm interface.
-
-
-Control and information flow within the compiler:
--------------------------------------------------
-
-- main() in lib.rs assumes control on startup. Options are
-  parsed, platform is detected, etc.
-
-- ./../libsyntax/parse/parser.rs parses the input files and produces an AST
-  that represents the input crate.
-
-- Multiple middle-end passes (middle/resolve.rs, middle/typeck.rs)
-  analyze the semantics of the resulting AST. Each pass generates new
-  information about the AST and stores it in various environment data
-  structures. The driver passes environments to each compiler pass
-  that needs to refer to them.
-
-- Finally, the `trans` module in `librustc_trans` translates the Rust
-  AST to LLVM bitcode in a type-directed way. When it's finished
-  synthesizing LLVM values, rustc asks LLVM to write them out in some
-  form (.bc, .o) and possibly run the system linker.
index b619c6a77d009597eef5b2f806a9ac4d0722d566..566af2590e6c07cd0ec1a256856951ee36478222 100644 (file)
@@ -900,7 +900,7 @@ fn record_import_use(&mut self, import_id: NodeId, name: Name) {
             return;
         }
         if self.glob_map.contains_key(&import_id) {
-            self.glob_map[import_id].insert(name);
+            self.glob_map.get_mut(&import_id).unwrap().insert(name);
             return;
         }
 
index 737ec71cab3da09273b69f94d3653d37674e91eb..46451019760dd478aa179449473532a32d15fe63 100644 (file)
@@ -603,7 +603,7 @@ fn get_binding(this: &mut Resolver,
 
         // We've successfully resolved the import. Write the results in.
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        let import_resolution = &mut (*import_resolutions)[target];
+        let import_resolution = import_resolutions.get_mut(&target).unwrap();
 
         {
             let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| {
index 3904db4433c892a69bffc712ea2d01afa73788c0..1f416d5404d2778d0fdea4768371232068e2bae8 100644 (file)
@@ -1 +1 @@
-See the README.txt in ../librustc.
+See the README.md in ../librustc.
index f584de7c47f3b88a22befaa1328e41c4d56053bb..ebd92faaf0f5328dda42d28c11fca41a6b1199ef 100644 (file)
@@ -983,56 +983,72 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 /// gives us better information about what we are loading.
 pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                            ptr: ValueRef, t: Ty<'tcx>) -> ValueRef {
-    if type_is_zero_size(cx.ccx(), t) {
-        C_undef(type_of::type_of(cx.ccx(), t))
-    } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
-        // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
-        // for this leads to bad optimizations, so its arg type is an appropriately sized integer
-        // and we have to convert it
-        Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to()))
-    } else {
-        unsafe {
-            let global = llvm::LLVMIsAGlobalVariable(ptr);
-            if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
-                let val = llvm::LLVMGetInitializer(global);
-                if !val.is_null() {
-                    // This could go into its own function, for DRY.
-                    // (something like "pre-store packing/post-load unpacking")
-                    if ty::type_is_bool(t) {
-                        return Trunc(cx, val, Type::i1(cx.ccx()));
-                    } else {
-                        return val;
-                    }
-                }
+    if cx.unreachable.get() || type_is_zero_size(cx.ccx(), t) {
+        return C_undef(type_of::type_of(cx.ccx(), t));
+    }
+
+    let ptr = to_arg_ty_ptr(cx, ptr, t);
+
+    if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
+        return Load(cx, ptr);
+    }
+
+    unsafe {
+        let global = llvm::LLVMIsAGlobalVariable(ptr);
+        if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
+            let val = llvm::LLVMGetInitializer(global);
+            if !val.is_null() {
+                return from_arg_ty(cx, val, t);
             }
         }
-        if ty::type_is_bool(t) {
-            Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx()))
-        } else if ty::type_is_char(t) {
-            // a char is a Unicode codepoint, and so takes values from 0
-            // to 0x10FFFF inclusive only.
-            LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
-        } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
-                  && !common::type_is_fat_ptr(cx.tcx(), t) {
-            LoadNonNull(cx, ptr)
-        } else {
-            Load(cx, ptr)
-        }
     }
+
+    let val =  if ty::type_is_bool(t) {
+        LoadRangeAssert(cx, ptr, 0, 2, llvm::False)
+    } else if ty::type_is_char(t) {
+        // a char is a Unicode codepoint, and so takes values from 0
+        // to 0x10FFFF inclusive only.
+        LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
+    } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
+        && !common::type_is_fat_ptr(cx.tcx(), t) {
+            LoadNonNull(cx, ptr)
+    } else {
+        Load(cx, ptr)
+    };
+
+    from_arg_ty(cx, val, t)
 }
 
 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
 /// differs from the type used for SSA values.
 pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
-    if ty::type_is_bool(t) {
-        Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
-    } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
+    Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
+}
+
+pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
+    if ty::type_is_bool(ty) {
+        ZExt(bcx, val, Type::i8(bcx.ccx()))
+    } else {
+        val
+    }
+}
+
+pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
+    if ty::type_is_bool(ty) {
+        Trunc(bcx, val, Type::i1(bcx.ccx()))
+    } else {
+        val
+    }
+}
+
+pub fn to_arg_ty_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, ty: Ty<'tcx>) -> ValueRef {
+    if type_is_immediate(bcx.ccx(), ty) && type_of::type_of(bcx.ccx(), ty).is_aggregate() {
         // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
         // for this leads to bad optimizations, so its arg type is an appropriately sized integer
         // and we have to convert it
-        Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to()));
+        BitCast(bcx, ptr, type_of::arg_type_of(bcx.ccx(), ty).ptr_to())
     } else {
-        Store(cx, v, dst);
+        ptr
     }
 }
 
index 69ca9a5e81cbc81b933e4ac5ed62022cdb261787..d158cfa7b88765b77f12dba0808328ebd9ef630b 100644 (file)
@@ -446,10 +446,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                              call_debug_location)
         }
         (_, "volatile_load") => {
-            VolatileLoad(bcx, llargs[0])
+            let tp_ty = *substs.types.get(FnSpace, 0);
+            let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+            from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty)
         },
         (_, "volatile_store") => {
-            VolatileStore(bcx, llargs[1], llargs[0]);
+            let tp_ty = *substs.types.get(FnSpace, 0);
+            let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+            let val = to_arg_ty(bcx, llargs[1], tp_ty);
+            VolatileStore(bcx, val, ptr);
             C_nil(ccx)
         },
 
@@ -709,8 +714,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                             llvm::SequentiallyConsistent
                     };
 
-                    let res = AtomicCmpXchg(bcx, llargs[0], llargs[1],
-                                            llargs[2], order,
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let cmp = to_arg_ty(bcx, llargs[1], tp_ty);
+                    let src = to_arg_ty(bcx, llargs[2], tp_ty);
+                    let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
                                             strongest_failure_ordering);
                     if unsafe { llvm::LLVMVersionMinor() >= 5 } {
                         ExtractValue(bcx, res, 0)
@@ -720,10 +728,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 }
 
                 "load" => {
-                    AtomicLoad(bcx, llargs[0], order)
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    from_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
                 }
                 "store" => {
-                    AtomicStore(bcx, llargs[1], llargs[0], order);
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let val = to_arg_ty(bcx, llargs[1], tp_ty);
+                    AtomicStore(bcx, val, ptr, order);
                     C_nil(ccx)
                 }
 
@@ -749,7 +762,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         _ => ccx.sess().fatal("unknown atomic operation")
                     };
 
-                    AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order)
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let val = to_arg_ty(bcx, llargs[1], tp_ty);
+                    AtomicRMW(bcx, atom_op, ptr, val, order)
                 }
             }
 
index 09592db8a116d399abd4bf2d815942672ff56e9c..ce4bb4465517b21ef55189e1fc99f2312fae03ee 100644 (file)
@@ -380,7 +380,7 @@ fn try_adjust_upvar_deref(&self,
                 // borrow_kind of the upvar to make sure it
                 // is inferred to mutable if necessary
                 let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut();
-                let ub = &mut upvar_capture_map[upvar_id];
+                let ub = upvar_capture_map.get_mut(&upvar_id).unwrap();
                 self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind);
 
                 // also need to be in an FnMut closure since this is not an ImmBorrow
index 60b1738d2c98918351082c0da31efbfc78b08aed..9139e182ce479594ba38b0ccc132a33f2f9b98a5 100644 (file)
@@ -23,7 +23,7 @@
 use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
 use marker::Sized;
 use mem::{self, replace};
-use ops::{Deref, FnMut, Index, IndexMut};
+use ops::{Deref, FnMut, Index};
 use option::Option::{self, Some, None};
 use rand::{self, Rng};
 use result::Result::{self, Ok, Err};
@@ -1258,18 +1258,6 @@ fn index<'a>(&'a self, index: &Q) -> &'a V {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
-    where K: Eq + Hash + Borrow<Q>,
-          Q: Eq + Hash,
-          S: HashState,
-{
-    #[inline]
-    fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
-        self.get_mut(index).expect("no entry found for key")
-    }
-}
-
 /// HashMap iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, K: 'a, V: 'a> {
index 1cbfbbf29278f1b03663400c2ea0fddc459c0a8a..130fd1d7dc83b36841ee5ca4afbf89ec575188f5 100644 (file)
@@ -40,7 +40,7 @@
 /// among threads to ensure that a possibly invalid invariant is not witnessed.
 ///
 /// A poisoned mutex, however, does not prevent all access to the underlying
-/// data. The `PoisonError` type has an `into_guard` method which will return
+/// data. The `PoisonError` type has an `into_inner` method which will return
 /// the guard that would have otherwise been returned on a successful lock. This
 /// allows access to the data, despite the lock being poisoned.
 ///
 /// // pattern matched on to return the underlying guard on both branches.
 /// let mut guard = match lock.lock() {
 ///     Ok(guard) => guard,
-///     Err(poisoned) => poisoned.into_guard(),
+///     Err(poisoned) => poisoned.into_inner(),
 /// };
 ///
 /// *guard += 1;
diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs
new file mode 100644 (file)
index 0000000..a88445b
--- /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.
+
+// Test that macro reexports item are gated by `macro_reexport` feature gate.
+
+// aux-build:macro_reexport_1.rs
+// ignore-stage1
+
+#![crate_type = "dylib"]
+
+#[macro_reexport(reexported)]
+#[macro_use] #[no_link]
+extern crate macro_reexport_1;
+//~^ ERROR macros reexports are experimental and possibly buggy
+//~| HELP add #![feature(macro_reexport)] to the crate attributes to enable
diff --git a/src/test/compile-fail/gated-box-patterns.rs b/src/test/compile-fail/gated-box-patterns.rs
new file mode 100644 (file)
index 0000000..abaa256
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that patterns including the box syntax are gated by `box_patterns` feature gate.
+
+fn main() {
+    let x = Box::new(1);
+
+    match x {
+        box 1 => (),
+        //~^ box pattern syntax is experimental
+        //~| add #![feature(box_patterns)] to the crate attributes to enable
+        _     => ()
+    };
+}
diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/compile-fail/gated-box-syntax.rs
new file mode 100644 (file)
index 0000000..3e08c1f
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the use of the box syntax is gated by `box_syntax` feature gate.
+
+fn main() {
+    let x = box 3;
+    //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
+    //~| HELP add #![feature(box_syntax)] to the crate attributes to enable
+}
diff --git a/src/test/compile-fail/gated-simd-ffi.rs b/src/test/compile-fail/gated-simd-ffi.rs
new file mode 100644 (file)
index 0000000..c0a251e
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the use of smid types in the ffi is gated by `smid_ffi` feature gate.
+
+#![feature(simd)]
+
+#[repr(C)]
+#[derive(Copy)]
+#[simd]
+pub struct f32x4(f32, f32, f32, f32);
+
+#[allow(dead_code)]
+extern {
+    fn foo(x: f32x4);
+    //~^ ERROR use of SIMD type `f32x4` in FFI is highly experimental and may result in invalid code
+    //~| HELP add #![feature(simd_ffi)] to the crate attributes to enable
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-23550.rs b/src/test/run-pass/issue-23550.rs
new file mode 100644 (file)
index 0000000..97357c1
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(core)]
+#![allow(warnings)]
+
+use std::intrinsics;
+
+#[derive(Copy)]
+struct Wrap(i64);
+
+// These volatile and atomic intrinsics used to cause an ICE
+
+unsafe fn test_bool(p: &mut bool, v: bool) {
+    intrinsics::volatile_load(p);
+    intrinsics::volatile_store(p, v);
+    intrinsics::atomic_load(p);
+    intrinsics::atomic_cxchg(p, v, v);
+    intrinsics::atomic_store(p, v);
+    intrinsics::atomic_xchg(p, v);
+}
+
+unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) {
+    intrinsics::volatile_load(p);
+    intrinsics::volatile_store(p, v);
+    intrinsics::atomic_load(p);
+    intrinsics::atomic_cxchg(p, v, v);
+    intrinsics::atomic_store(p, v);
+    intrinsics::atomic_xchg(p, v);
+}
+
+fn main() {}