diff options
Diffstat (limited to 'src')
24 files changed, 543 insertions, 236 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md index de9352a4275..b1aa400d1e2 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -147,11 +147,11 @@ a form of constant expression, so is evaluated (primarily) at compile time. | | Example | `#` sets | Characters | Escapes | |----------------------------------------------|-----------------|------------|-------------|---------------------| -| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | `\'` & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | -| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | `\"` & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | +| [Character](#character-literals) | `'H'` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | +| [String](#string-literals) | `"hello"` | `N/A` | All Unicode | [Quote](#quote-escapes) & [Byte](#byte-escapes) & [Unicode](#unicode-escapes) | | [Raw](#raw-string-literals) | `r#"hello"#` | `0...` | All Unicode | `N/A` | -| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | `\'` & [Byte](#byte-escapes) | -| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | `\"` & [Byte](#byte-escapes) | +| [Byte](#byte-literals) | `b'H'` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | +| [Byte string](#byte-string-literals) | `b"hello"` | `N/A` | All ASCII | [Quote](#quote-escapes) & [Byte](#byte-escapes) | | [Raw byte string](#raw-byte-string-literals) | `br#"hello"#` | `0...` | All ASCII | `N/A` | ##### Byte escapes @@ -163,12 +163,19 @@ a form of constant expression, so is evaluated (primarily) at compile time. | `\r` | Carriage return | | `\t` | Tab | | `\\` | Backslash | +| `\0` | Null | ##### Unicode escapes | | Name | |---|------| | `\u{7FFF}` | 24-bit Unicode character code (up to 6 digits) | +##### Quote escapes +| | Name | +|---|------| +| `\'` | Single quote | +| `\"` | Double quote | + ##### Numbers | [Number literals](#number-literals)`*` | Example | Exponentiation | Suffixes | @@ -2415,9 +2422,9 @@ in meaning to declaring the item outside the statement block. > **Note**: there is no implicit capture of the function's dynamic environment when > declaring a function-local item. -#### Variable declarations +#### `let` statements -A _variable declaration_ introduces a new set of variable, given by a pattern. The +A _`let` statement_ introduces a new set of variables, given by a pattern. The pattern may be followed by a type annotation, and/or an initializer expression. When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference. @@ -3190,10 +3197,11 @@ let message = match maybe_digit { ### `if let` expressions -An `if let` expression is semantically identical to an `if` expression but in place -of a condition expression it expects a refutable let statement. If the value of the -expression on the right hand side of the let statement matches the pattern, the corresponding -block will execute, otherwise flow proceeds to the first `else` block that follows. +An `if let` expression is semantically identical to an `if` expression but in +place of a condition expression it expects a `let` statement with a refutable +pattern. If the value of the expression on the right hand side of the `let` +statement matches the pattern, the corresponding block will execute, otherwise +flow proceeds to the first `else` block that follows. ``` let dish = ("Ham", "Eggs"); @@ -3211,11 +3219,11 @@ if let ("Ham", b) = dish { ### `while let` loops -A `while let` loop is semantically identical to a `while` loop but in place of a -condition expression it expects a refutable let statement. If the value of the -expression on the right hand side of the let statement matches the pattern, the -loop body block executes and control returns to the pattern matching statement. -Otherwise, the while expression completes. +A `while let` loop is semantically identical to a `while` loop but in place of +a condition expression it expects `let` statement with a refutable pattern. If +the value of the expression on the right hand side of the `let` statement +matches the pattern, the loop body block executes and control returns to the +pattern matching statement. Otherwise, the while expression completes. ### `return` expressions diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md index 7a58a327b9f..d949bf33b6e 100644 --- a/src/doc/trpl/ffi.md +++ b/src/doc/trpl/ffi.md @@ -8,6 +8,23 @@ foreign code. Rust is currently unable to call directly into a C++ library, but snappy includes a C interface (documented in [`snappy-c.h`](https://github.com/google/snappy/blob/master/snappy-c.h)). +## A note about libc + +Many of these examples use [the `libc` crate][libc], which provides various +type definitions for C types, among other things. If you’re trying these +examples yourself, you’ll need to add `libc` to your `Cargo.toml`: + +```toml +[dependencies] +libc = "0.2.0" +``` + +[libc]: https://crates.io/crates/libc + +and add `extern crate libc;` to your crate root. + +## Calling foreign functions + The following is a minimal example of calling a foreign function which will compile if snappy is installed: diff --git a/src/doc/trpl/lifetimes.md b/src/doc/trpl/lifetimes.md index 13265ab1eba..68bbd0c9899 100644 --- a/src/doc/trpl/lifetimes.md +++ b/src/doc/trpl/lifetimes.md @@ -116,7 +116,8 @@ reference to an `i32` with the lifetime `'a`’. # In `struct`s -You’ll also need explicit lifetimes when working with [`struct`][structs]s: +You’ll also need explicit lifetimes when working with [`struct`][structs]s that +contain references: ```rust struct Foo<'a> { diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index bf75c598cc7..80774fc2acf 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2375,32 +2375,118 @@ impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I { } /// Conversion from an `Iterator`. +/// +/// By implementing `FromIterator` for a type, you define how it will be +/// created from an iterator. This is common for types which describe a +/// collection of some kind. +/// +/// `FromIterator`'s [`from_iter()`] is rarely called explicitly, and is instead +/// used through [`Iterator`]'s [`collect()`] method. See [`collect()`]'s +/// documentation for more examples. +/// +/// [`from_iter()`]: #tymethod.from_iter +/// [`Iterator`]: trait.Iterator.html +/// [`collect()`]: trait.Iterator.html#method.collect +/// +/// See also: [`IntoIterator`]. +/// +/// [`IntoIterator`]: trait.IntoIterator.html +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use std::iter::FromIterator; +/// +/// let five_fives = std::iter::repeat(5).take(5); +/// +/// let v = Vec::from_iter(five_fives); +/// +/// assert_eq!(v, vec![5, 5, 5, 5, 5]); +/// ``` +/// +/// Using [`collect()`] to implicitly use `FromIterator`: +/// +/// ``` +/// let five_fives = std::iter::repeat(5).take(5); +/// +/// let v: Vec<i32> = five_fives.collect(); +/// +/// assert_eq!(v, vec![5, 5, 5, 5, 5]); +/// ``` +/// +/// Implementing `FromIterator` for your type: +/// +/// ``` +/// use std::iter::FromIterator; +/// +/// // A sample collection, that's just a wrapper over Vec<T> +/// #[derive(Debug)] +/// struct MyCollection(Vec<i32>); +/// +/// // Let's give it some methods so we can create one and add things +/// // to it. +/// impl MyCollection { +/// fn new() -> MyCollection { +/// MyCollection(Vec::new()) +/// } +/// +/// fn add(&mut self, elem: i32) { +/// self.0.push(elem); +/// } +/// } +/// +/// // and we'll implement FromIterator +/// impl FromIterator<i32> for MyCollection { +/// fn from_iter<I: IntoIterator<Item=i32>>(iterator: I) -> Self { +/// let mut c = MyCollection::new(); +/// +/// for i in iterator { +/// c.add(i); +/// } +/// +/// c +/// } +/// } +/// +/// // Now we can make a new iterator... +/// let iter = (0..5).into_iter(); +/// +/// // ... and make a MyCollection out of it +/// let c = MyCollection::from_iter(iter); +/// +/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]); +/// +/// // collect works too! +/// +/// let iter = (0..5).into_iter(); +/// let c: MyCollection = iter.collect(); +/// +/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ built from an iterator over elements of type `{A}`"] pub trait FromIterator<A>: Sized { - /// Builds a container with elements from something iterable. + /// Creates a value from an iterator. + /// + /// See the [module-level documentation] for more. + /// + /// [module-level documentation]: trait.FromIterator.html /// /// # Examples /// - /// ``` - /// use std::collections::HashSet; - /// use std::iter::FromIterator; + /// Basic usage: /// - /// let colors_vec = vec!["red", "red", "yellow", "blue"]; - /// let colors_set = HashSet::<&str>::from_iter(colors_vec); - /// assert_eq!(colors_set.len(), 3); /// ``` + /// use std::iter::FromIterator; /// - /// `FromIterator` is more commonly used implicitly via the - /// `Iterator::collect` method: + /// let five_fives = std::iter::repeat(5).take(5); /// - /// ``` - /// use std::collections::HashSet; + /// let v = Vec::from_iter(five_fives); /// - /// let colors_vec = vec!["red", "red", "yellow", "blue"]; - /// let colors_set = colors_vec.into_iter().collect::<HashSet<&str>>(); - /// assert_eq!(colors_set.len(), 3); + /// assert_eq!(v, vec![5, 5, 5, 5, 5]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn from_iter<T: IntoIterator<Item=A>>(iterator: T) -> Self; @@ -2415,9 +2501,13 @@ pub trait FromIterator<A>: Sized { /// One benefit of implementing `IntoIterator` is that your type will [work /// with Rust's `for` loop syntax](index.html#for-loops-and-intoiterator). /// +/// See also: [`FromIterator`]. +/// +/// [`FromIterator`]: trait.FromIterator.html +/// /// # Examples /// -/// Vectors implement `IntoIterator`: +/// Basic usage: /// /// ``` /// let v = vec![1, 2, 3]; @@ -2489,7 +2579,33 @@ pub trait IntoIterator { #[stable(feature = "rust1", since = "1.0.0")] type IntoIter: Iterator<Item=Self::Item>; - /// Consumes `Self` and returns an iterator over it. + /// Creates an iterator from a value. + /// + /// See the [module-level documentation] for more. + /// + /// [module-level documentation]: trait.IntoIterator.html + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let v = vec![1, 2, 3]; + /// + /// let mut iter = v.into_iter(); + /// + /// let n = iter.next(); + /// assert_eq!(Some(1), n); + /// + /// let n = iter.next(); + /// assert_eq!(Some(2), n); + /// + /// let n = iter.next(); + /// assert_eq!(Some(3), n); + /// + /// let n = iter.next(); + /// assert_eq!(None, n); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn into_iter(self) -> Self::IntoIter; } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index df7b7c437c3..c97f8e529a2 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -10,12 +10,15 @@ //! # The Rust Core Library //! -//! The Rust Core Library is the dependency-free foundation of [The +//! The Rust Core Library is the dependency-free[^free] foundation of [The //! Rust Standard Library](../std/index.html). It is the portable glue //! between the language and its libraries, defining the intrinsic and //! primitive building blocks of all Rust code. It links to no //! upstream libraries, no system libraries, and no libc. //! +//! [^free]: Strictly speaking, there are some symbols which are needed but +//! they aren't always necessary. +//! //! The core library is *minimal*: it isn't even aware of heap allocation, //! nor does it provide concurrency or I/O. These things require //! platform integration, and this library is platform-agnostic. @@ -63,7 +66,6 @@ #![doc(test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_core] -#![allow(raw_pointer_derive)] #![deny(missing_docs)] #![feature(allow_internal_unstable)] diff --git a/src/liblibc b/src/liblibc -Subproject b1a043feeae3a67f45e75eaf10aa900a1f6832f +Subproject 8531cc11e196b7ae9072ae7b384a930ff7b00df diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 2660b6447fa..832baa1515f 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -390,6 +390,8 @@ pub struct ConstEvalErr { pub enum ErrKind { CannotCast, CannotCastTo(&'static str), + InvalidOpForInts(hir::BinOp_), + InvalidOpForUInts(hir::BinOp_), InvalidOpForBools(hir::BinOp_), InvalidOpForFloats(hir::BinOp_), InvalidOpForIntUint(hir::BinOp_), @@ -428,6 +430,8 @@ impl ConstEvalErr { match self.kind { CannotCast => "can't cast this type".into_cow(), CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(), + InvalidOpForInts(_) => "can't do this op on signed integrals".into_cow(), + InvalidOpForUInts(_) => "can't do this op on unsigned integrals".into_cow(), InvalidOpForBools(_) => "can't do this op on bools".into_cow(), InvalidOpForFloats(_) => "can't do this op on floats".into_cow(), InvalidOpForIntUint(..) => "can't do this op on an isize and usize".into_cow(), @@ -764,8 +768,6 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, e: &Expr, ty_hint: EvalHint<'tcx>, fn_args: FnArgMap) -> EvalResult { - fn fromb(b: bool) -> ConstVal { Int(b as i64) } - // Try to compute the type of the expression based on the EvalHint. // (See also the definition of EvalHint, and the FIXME above EvalHint.) let ety = match ty_hint { @@ -837,13 +839,13 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, hir::BiMul => Float(a * b), hir::BiDiv => Float(a / b), hir::BiRem => Float(a % b), - hir::BiEq => fromb(a == b), - hir::BiLt => fromb(a < b), - hir::BiLe => fromb(a <= b), - hir::BiNe => fromb(a != b), - hir::BiGe => fromb(a >= b), - hir::BiGt => fromb(a > b), - _ => signal!(e, InvalidOpForFloats(op.node)) + hir::BiEq => Bool(a == b), + hir::BiLt => Bool(a < b), + hir::BiLe => Bool(a <= b), + hir::BiNe => Bool(a != b), + hir::BiGe => Bool(a >= b), + hir::BiGt => Bool(a > b), + _ => signal!(e, InvalidOpForFloats(op.node)), } } (Int(a), Int(b)) => { @@ -853,17 +855,18 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, hir::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)), hir::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)), hir::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)), - hir::BiAnd | hir::BiBitAnd => Int(a & b), - hir::BiOr | hir::BiBitOr => Int(a | b), + hir::BiBitAnd => Int(a & b), + hir::BiBitOr => Int(a | b), hir::BiBitXor => Int(a ^ b), hir::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)), hir::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)), - hir::BiEq => fromb(a == b), - hir::BiLt => fromb(a < b), - hir::BiLe => fromb(a <= b), - hir::BiNe => fromb(a != b), - hir::BiGe => fromb(a >= b), - hir::BiGt => fromb(a > b) + hir::BiEq => Bool(a == b), + hir::BiLt => Bool(a < b), + hir::BiLe => Bool(a <= b), + hir::BiNe => Bool(a != b), + hir::BiGe => Bool(a >= b), + hir::BiGt => Bool(a > b), + _ => signal!(e, InvalidOpForInts(op.node)), } } (Uint(a), Uint(b)) => { @@ -873,17 +876,18 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, hir::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)), hir::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)), hir::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)), - hir::BiAnd | hir::BiBitAnd => Uint(a & b), - hir::BiOr | hir::BiBitOr => Uint(a | b), + hir::BiBitAnd => Uint(a & b), + hir::BiBitOr => Uint(a | b), hir::BiBitXor => Uint(a ^ b), hir::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)), hir::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)), - hir::BiEq => fromb(a == b), - hir::BiLt => fromb(a < b), - hir::BiLe => fromb(a <= b), - hir::BiNe => fromb(a != b), - hir::BiGe => fromb(a >= b), - hir::BiGt => fromb(a > b), + hir::BiEq => Bool(a == b), + hir::BiLt => Bool(a < b), + hir::BiLe => Bool(a <= b), + hir::BiNe => Bool(a != b), + hir::BiGe => Bool(a >= b), + hir::BiGt => Bool(a > b), + _ => signal!(e, InvalidOpForUInts(op.node)), } } // shifts can have any integral type as their rhs diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 0d53b0db34e..1bfb7471daa 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -351,6 +351,7 @@ impl Target { key!(no_default_libraries, bool); key!(pre_link_args, list); key!(post_link_args, list); + key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index eb542adef00..5db3ee59cae 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -167,7 +167,7 @@ pub fn compile_input(sess: Session, tcx.print_debug_stats(); } let trans = phase_4_translate_to_llvm(tcx, - &mir_map, + mir_map, analysis); if log_enabled!(::log::INFO) { @@ -848,7 +848,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, /// Run the translation phase to LLVM, after which the AST and analysis can /// be discarded. pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>, - mir_map: &MirMap<'tcx>, + mut mir_map: MirMap<'tcx>, analysis: ty::CrateAnalysis) -> trans::CrateTranslation { let time_passes = tcx.sess.time_passes(); @@ -857,10 +857,14 @@ pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>, "resolving dependency formats", || dependency_format::calculate(&tcx.sess)); + time(time_passes, + "erasing regions from MIR", + || mir::transform::erase_regions::erase_regions(tcx, &mut mir_map)); + // Option dance to work around the lack of stack once closures. time(time_passes, "translation", - move || trans::trans_crate(tcx, mir_map, analysis)) + move || trans::trans_crate(tcx, &mir_map, analysis)) } /// Run LLVM itself, producing a bitcode file, assembly file or object file diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 516c9dcae71..3e43a2240de 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -46,7 +46,7 @@ use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::{self, Span}; use rustc_front::hir; -use rustc_front::visit::{self, FnKind, Visitor}; +use rustc_front::visit::FnKind; use bad_style::{MethodLateContext, method_context}; @@ -139,92 +139,6 @@ impl LateLintPass for BoxPointers { } declare_lint! { - RAW_POINTER_DERIVE, - Warn, - "uses of #[derive] with raw pointers are rarely correct" -} - -struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { - cx: &'a LateContext<'a, 'tcx> -} - -impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &hir::Ty) { - const MSG: &'static str = "use of `#[derive]` with a raw pointer"; - if let hir::TyPtr(..) = ty.node { - self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG); - } - visit::walk_ty(self, ty); - } - // explicit override to a no-op to reduce code bloat - fn visit_expr(&mut self, _: &hir::Expr) {} - fn visit_block(&mut self, _: &hir::Block) {} -} - -pub struct RawPointerDerive { - checked_raw_pointers: NodeSet, -} - -impl RawPointerDerive { - pub fn new() -> RawPointerDerive { - RawPointerDerive { - checked_raw_pointers: NodeSet(), - } - } -} - -impl LintPass for RawPointerDerive { - fn get_lints(&self) -> LintArray { - lint_array!(RAW_POINTER_DERIVE) - } -} - -impl LateLintPass for RawPointerDerive { - fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { - if !attr::contains_name(&item.attrs, "automatically_derived") { - return; - } - let did = match item.node { - hir::ItemImpl(_, _, _, ref t_ref_opt, _, _) => { - // Deriving the Copy trait does not cause a warning - if let &Some(ref trait_ref) = t_ref_opt { - let def_id = cx.tcx.trait_ref_to_def_id(trait_ref); - if Some(def_id) == cx.tcx.lang_items.copy_trait() { - return; - } - } - - match cx.tcx.node_id_to_type(item.id).sty { - ty::TyEnum(def, _) => def.did, - ty::TyStruct(def, _) => def.did, - _ => return, - } - } - _ => return, - }; - let node_id = if let Some(node_id) = cx.tcx.map.as_local_node_id(did) { - node_id - } else { - return; - }; - let item = match cx.tcx.map.find(node_id) { - Some(hir_map::NodeItem(item)) => item, - _ => return, - }; - if !self.checked_raw_pointers.insert(item.id) { - return; - } - match item.node { - hir::ItemStruct(..) | hir::ItemEnum(..) => { - let mut visitor = RawPtrDeriveVisitor { cx: cx }; - visit::walk_item(&mut visitor, &item); - } - _ => {} - } - } -} - -declare_lint! { NON_SHORTHAND_FIELD_PATTERNS, Warn, "using `Struct { x: x }` instead of `Struct { x }`" diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 920e0341372..2613115d805 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -135,7 +135,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { add_builtin_with_new!(sess, TypeLimits, - RawPointerDerive, MissingDoc, MissingDebugImplementations, ); @@ -152,8 +151,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { store.register_late_pass(sess, false, box lint::GatherNodeLevels); // Insert temporary renamings for a one-time deprecation - store.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); - store.register_renamed("unknown_features", "unused_features"); store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index e6350ae44d4..c09048d677e 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -37,7 +37,6 @@ impl OptimizationDiagnosticKind { } } -#[allow(raw_pointer_derive)] #[derive(Copy, Clone)] pub struct OptimizationDiagnostic { pub kind: OptimizationDiagnosticKind, diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs new file mode 100644 index 00000000000..e156fbf004f --- /dev/null +++ b/src/librustc_mir/transform/erase_regions.rs @@ -0,0 +1,234 @@ +// 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. + +//! This pass erases all early-bound regions from the types occuring in the MIR. +//! We want to do this once just before trans, so trans does not have to take +//! care erasing regions all over the place. + +use repr::*; +use rustc::middle::ty; +use transform::MirPass; +use mir_map::MirMap; + +pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) { + let mut eraser = EraseRegions::new(tcx); + + for mir in mir_map.iter_mut().map(|(_, v)| v) { + eraser.run_on_mir(mir); + } +} + +pub struct EraseRegions<'a, 'tcx: 'a> { + tcx: &'a ty::ctxt<'tcx>, +} + +impl<'a, 'tcx> MirPass<'tcx> for EraseRegions<'a, 'tcx> { + + fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) { + + for basic_block in &mut mir.basic_blocks { + self.erase_regions_basic_block(basic_block); + } + + self.erase_regions_return_ty(&mut mir.return_ty); + + self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty)); + self.erase_regions_tys(mir.arg_decls.iter_mut().map(|d| &mut d.ty)); + self.erase_regions_tys(mir.temp_decls.iter_mut().map(|d| &mut d.ty)); + } +} + +impl<'a, 'tcx> EraseRegions<'a, 'tcx> { + + pub fn new(tcx: &'a ty::ctxt<'tcx>) -> EraseRegions<'a, 'tcx> { + EraseRegions { + tcx: tcx + } + } + + fn erase_regions_basic_block(&mut self, + basic_block: &mut BasicBlockData<'tcx>) { + for statement in &mut basic_block.statements { + self.erase_regions_statement(statement); + } + + self.erase_regions_terminator(&mut basic_block.terminator); + } + + fn erase_regions_statement(&mut self, + statement: &mut Statement<'tcx>) { + match statement.kind { + StatementKind::Assign(ref mut lvalue, ref mut rvalue) => { + self.erase_regions_lvalue(lvalue); + self.erase_regions_rvalue(rvalue); + } + StatementKind::Drop(_, ref mut lvalue) => { + self.erase_regions_lvalue(lvalue); + } + } + } + + fn erase_regions_terminator(&mut self, + terminator: &mut Terminator<'tcx>) { + match *terminator { + Terminator::Goto { .. } | + Terminator::Diverge | + Terminator::Return | + Terminator::Panic { .. } => { + /* nothing to do */ + } + Terminator::If { ref mut cond, .. } => { + self.erase_regions_operand(cond); + } + Terminator::Switch { ref mut discr, .. } => { + self.erase_regions_lvalue(discr); + } + Terminator::SwitchInt { + ref mut discr, + ref mut switch_ty, + .. + } => { + self.erase_regions_lvalue(discr); + *switch_ty = self.tcx.erase_regions(switch_ty); + }, + Terminator::Call { + data: CallData { + ref mut destination, + ref mut func, + ref mut args + }, + .. + } => { + self.erase_regions_lvalue(destination); + self.erase_regions_operand(func); + for arg in &mut *args { + self.erase_regions_operand(arg); + } + } + } + } + + fn erase_regions_operand(&mut self, operand: &mut Operand<'tcx>) { + match *operand { + Operand::Consume(ref mut lvalue) => { + self.erase_regions_lvalue(lvalue); + } + Operand::Constant(ref mut constant) => { + self.erase_regions_constant(constant); + } + } + } + + fn erase_regions_lvalue(&mut self, lvalue: &mut Lvalue<'tcx>) { + match *lvalue { + Lvalue::Var(_) | + Lvalue::Temp(_) | + Lvalue::Arg(_) | + Lvalue::Static(_) | + Lvalue::ReturnPointer => {} + Lvalue::Projection(ref mut lvalue_projection) => { + self.erase_regions_lvalue(&mut lvalue_projection.base); + match lvalue_projection.elem { + ProjectionElem::Deref | + ProjectionElem::Field(_) | + ProjectionElem::Downcast(..) | + ProjectionElem::ConstantIndex {..} => { /* nothing to do */ } + ProjectionElem::Index(ref mut index) => { + self.erase_regions_operand(index); + } + } + } + } + } + + fn erase_regions_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>) { + match *rvalue { + Rvalue::Use(ref mut operand) => { + self.erase_regions_operand(operand) + } + Rvalue::Repeat(ref mut operand, ref mut constant) => { + self.erase_regions_operand(operand); + self.erase_regions_constant(constant); + } + Rvalue::Ref(ref mut region, _, ref mut lvalue) => { + *region = ty::ReStatic; + self.erase_regions_lvalue(lvalue); + } + Rvalue::Len(ref mut lvalue) => self.erase_regions_lvalue(lvalue), + Rvalue::Cast(_, ref mut operand, ref mut ty) => { + self.erase_regions_operand(operand); + *ty = self.tcx.erase_regions(ty); + } + Rvalue::BinaryOp(_, ref mut operand1, ref mut operand2) => { + self.erase_regions_operand(operand1); + self.erase_regions_operand(operand2); + } + Rvalue::UnaryOp(_, ref mut operand) => { + self.erase_regions_operand(operand); + } + Rvalue::Box(ref mut ty) => *ty = self.tcx.erase_regions(ty), + Rvalue::Aggregate(ref mut aggregate_kind, ref mut operands) => { + match *aggregate_kind { + AggregateKind::Vec | + AggregateKind::Tuple => {}, + AggregateKind::Adt(_, _, ref mut substs) => { + let erased = self.tcx.erase_regions(*substs); + *substs = self.tcx.mk_substs(erased); + } + AggregateKind::Closure(def_id, ref mut closure_substs) => { + let cloned = Box::new(closure_substs.clone()); + let ty = self.tcx.mk_closure_from_closure_substs(def_id, + cloned); + let erased = self.tcx.erase_regions(&ty); + *closure_substs = match erased.sty { + ty::TyClosure(_, ref closure_substs) => &*closure_substs, + _ => unreachable!() + }; + } + } + for operand in &mut *operands { + self.erase_regions_operand(operand); + } + } + Rvalue::Slice { ref mut input, .. } => { + self.erase_regions_lvalue(input); + } + Rvalue::InlineAsm(_) => {}, + } + } + + fn erase_regions_constant(&mut self, constant: &mut Constant<'tcx>) { + constant.ty = self.tcx.erase_regions(&constant.ty); + match constant.literal { + Literal::Item { ref mut substs, .. } => { + *substs = self.tcx.mk_substs(self.tcx.erase_regions(substs)); + } + Literal::Value { .. } => { /* nothing to do */ } + } + } + + fn erase_regions_return_ty(&mut self, fn_output: &mut ty::FnOutput<'tcx>) { + match *fn_output { + ty::FnConverging(ref mut ty) => { + *ty = self.tcx.erase_regions(ty); + }, + ty::FnDiverging => {} + } + } + + fn erase_regions_tys<'b, T>(&mut self, tys: T) + where T: Iterator<Item = &'b mut ty::Ty<'tcx>>, + 'tcx: 'b + { + for ty in tys { + *ty = self.tcx.erase_regions(ty); + } + } +} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index bee6d4d7ddd..9bec934143f 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -9,10 +9,11 @@ // except according to those terms. pub mod simplify_cfg; +pub mod erase_regions; mod util; use repr::Mir; -pub trait MirPass { - fn run_on_mir(&mut self, mir: &mut Mir); +pub trait MirPass<'tcx> { + fn run_on_mir(&mut self, mir: &mut Mir<'tcx>); } diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 71dd2f077fe..ee9dcbf1203 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -120,8 +120,8 @@ impl SimplifyCfg { } } -impl MirPass for SimplifyCfg { - fn run_on_mir(&mut self, mir: &mut Mir) { +impl<'tcx> MirPass<'tcx> for SimplifyCfg { + fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) { let mut changed = true; while changed { changed = self.simplify_branches(mir); diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index 8c0d8b10bfe..9af5bb43318 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use middle::ty::Ty; +use middle::ty::{Ty, HasTypeFlags}; use rustc::middle::const_eval::ConstVal; use rustc_mir::repr as mir; use trans::consts::{self, TrueConst}; @@ -63,6 +63,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { unimplemented!() } }; + + assert!(!ty.has_erasable_regions()); + OperandRef { ty: ty, val: val diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs index ff80451d2b1..1f39a2aa048 100644 --- a/src/librustc_trans/trans/mir/lvalue.rs +++ b/src/librustc_trans/trans/mir/lvalue.rs @@ -9,7 +9,7 @@ // except according to those terms. use llvm::ValueRef; -use rustc::middle::ty::{self, Ty}; +use rustc::middle::ty::{self, Ty, HasTypeFlags}; use rustc_mir::repr as mir; use rustc_mir::tcx::LvalueTy; use trans::adt; @@ -45,6 +45,7 @@ impl<'tcx> LvalueRef<'tcx> { name: &str) -> LvalueRef<'tcx> { + assert!(!ty.has_erasable_regions()); let lltemp = base::alloc_ty(bcx, ty, name); LvalueRef::new_sized(lltemp, LvalueTy::from_ty(ty)) } diff --git a/src/librustc_trans/trans/mir/operand.rs b/src/librustc_trans/trans/mir/operand.rs index 63abdfe2dd9..75d7b574382 100644 --- a/src/librustc_trans/trans/mir/operand.rs +++ b/src/librustc_trans/trans/mir/operand.rs @@ -9,7 +9,7 @@ // except according to those terms. use llvm::ValueRef; -use rustc::middle::ty::Ty; +use rustc::middle::ty::{Ty, HasTypeFlags}; use rustc_mir::repr as mir; use trans::base; use trans::common::{self, Block}; @@ -122,6 +122,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } datum::ByRef => OperandValue::Ref(tr_lvalue.llval) }; + + assert!(!ty.has_erasable_regions()); + OperandRef { val: val, ty: ty diff --git a/src/libstd/process.rs b/src/libstd/process.rs index 9d03022bb84..d26641dbfcf 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -20,11 +20,10 @@ use ffi::OsStr; use fmt; use io::{self, Error, ErrorKind}; use path; -use sync::mpsc::{channel, Receiver}; use sys::pipe::{self, AnonPipe}; use sys::process as imp; use sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; -use thread; +use thread::{self, JoinHandle}; /// Representation of a running or exited child process. /// @@ -542,29 +541,24 @@ impl Child { #[stable(feature = "process", since = "1.0.0")] pub fn wait_with_output(mut self) -> io::Result<Output> { drop(self.stdin.take()); - fn read<T: Read + Send + 'static>(stream: Option<T>) -> Receiver<io::Result<Vec<u8>>> { - let (tx, rx) = channel(); - match stream { - Some(stream) => { - thread::spawn(move || { - let mut stream = stream; - let mut ret = Vec::new(); - let res = stream.read_to_end(&mut ret); - tx.send(res.map(|_| ret)).unwrap(); - }); - } - None => tx.send(Ok(Vec::new())).unwrap() - } - rx + fn read<R>(mut input: R) -> JoinHandle<io::Result<Vec<u8>>> + where R: Read + Send + 'static + { + thread::spawn(move || { + let mut ret = Vec::new(); + input.read_to_end(&mut ret).map(|_| ret) + }) } - let stdout = read(self.stdout.take()); - let stderr = read(self.stderr.take()); + let stdout = self.stdout.take().map(read); + let stderr = self.stderr.take().map(read); let status = try!(self.wait()); + let stdout = stdout.and_then(|t| t.join().unwrap().ok()); + let stderr = stderr.and_then(|t| t.join().unwrap().ok()); Ok(Output { status: status, - stdout: stdout.recv().unwrap().unwrap_or(Vec::new()), - stderr: stderr.recv().unwrap().unwrap_or(Vec::new()), + stdout: stdout.unwrap_or(Vec::new()), + stderr: stderr.unwrap_or(Vec::new()), }) } } diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index dbec1a8851c..a2f37426210 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -91,6 +91,22 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('י', "Hebrew Letter Yod", '\''), ('ߴ', "Nko High Tone Apostrophe", '\''), ('ߵ', "Nko Low Tone Apostrophe", '\''), + ('"', "Fullwidth Quotation Mark", '"'), + ('“', "Left Double Quotation Mark", '"'), + ('”', "Right Double Quotation Mark", '"'), + ('‟', "Double High-Reversed-9 Quotation Mark", '"'), + ('″', "Double Prime", '"'), + ('‶', "Reversed Double Prime", '"'), + ('〃', "Ditto Mark", '"'), + ('״', "Hebrew Punctuation Gershayim", '"'), + ('˝', "Double Acute Accent", '"'), + ('ʺ', "Modifier Letter Double Prime", '"'), + ('˶', "Modifier Letter Middle Double Acute Accent", '"'), + ('˵', "Modifier Letter Middle Double Grave Accent", '"'), + ('ˮ', "Modifier Letter Double Apostrophe", '"'), + ('ײ', "Hebrew Ligature Yiddish Double Yod", '"'), + ('❞', "Heavy Double Comma Quotation Mark Ornament", '"'), + ('❝', "Heavy Double Turned Comma Quotation Mark Ornament", '"'), ('[', "Fullwidth Left Square Bracket", '('), ('❨', "Medium Left Parenthesis Ornament", '('), ('❲', "Light Left Tortoise Shell Bracket Ornament", '('), @@ -149,6 +165,7 @@ const ASCII_ARRAY: &'static [(char, &'static str)] = &[ ('?', "Question Mark"), ('.', "Period"), ('\'', "Single Quote"), + ('"', "Quotation Mark"), ('(', "Left Parenthesis"), (')', "Right Parenthesis"), ('{', "Left Curly Brace"), diff --git a/src/test/compile-fail/const-integer-bool-ops.rs b/src/test/compile-fail/const-integer-bool-ops.rs new file mode 100644 index 00000000000..37a93ec954d --- /dev/null +++ b/src/test/compile-fail/const-integer-bool-ops.rs @@ -0,0 +1,46 @@ +// 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. + +const X: usize = 42 && 39; //~ ERROR: can't do this op on unsigned integrals +const ARR: [i32; X] = [99; 34]; //~ NOTE: for array length here + +const X1: usize = 42 || 39; //~ ERROR: can't do this op on unsigned integrals +const ARR1: [i32; X1] = [99; 47]; //~ NOTE: for array length here + +// FIXME: the error should be `on signed integrals` +const X2: usize = -42 || -39; //~ ERROR: can't do this op on unsigned integrals +const ARR2: [i32; X2] = [99; 18446744073709551607]; //~ NOTE: for array length here + +// FIXME: the error should be `on signed integrals` +const X3: usize = -42 && -39; //~ ERROR: can't do this op on unsigned integrals +const ARR3: [i32; X3] = [99; 6]; //~ NOTE: for array length here + +const Y: usize = 42.0 == 42.0; +const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected constant integer expression for array length +const Y1: usize = 42.0 >= 42.0; +const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected constant integer expression for array length +const Y2: usize = 42.0 <= 42.0; +const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected constant integer expression for array length +const Y3: usize = 42.0 > 42.0; +const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected constant integer expression for array length +const Y4: usize = 42.0 < 42.0; +const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected constant integer expression for array length +const Y5: usize = 42.0 != 42.0; +const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected constant integer expression for array length + +fn main() { + let _ = ARR; + let _ = ARRR; + let _ = ARRR1; + let _ = ARRR2; + let _ = ARRR3; + let _ = ARRR4; + let _ = ARRR5; +} diff --git a/src/test/compile-fail/lint-raw-ptr-derive.rs b/src/test/compile-fail/lint-raw-ptr-derive.rs deleted file mode 100644 index 4320b3e7441..00000000000 --- a/src/test/compile-fail/lint-raw-ptr-derive.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <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. - -#![allow(dead_code)] -#![deny(raw_pointer_derive)] - -#[derive(Clone)] -struct Foo { - x: *const isize //~ ERROR use of `#[derive]` with a raw pointer -} - -#[derive(Clone)] -struct Bar(*mut isize); //~ ERROR use of `#[derive]` with a raw pointer - -#[derive(Clone)] -enum Baz { - A(*const isize), //~ ERROR use of `#[derive]` with a raw pointer - B { x: *mut isize } //~ ERROR use of `#[derive]` with a raw pointer -} - -#[derive(Clone)] -struct Buzz { - x: (*const isize, //~ ERROR use of `#[derive]` with a raw pointer - *const usize) //~ ERROR use of `#[derive]` with a raw pointer -} - -fn main() {} diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index f2dd155595a..8ca64e866a0 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -231,7 +231,7 @@ fn compile_program(input: &str, sysroot: PathBuf) driver::phase_3_run_analysis_passes( &sess, ast_map, &arenas, &id, MakeGlobMap::No, |tcx, mir_map, analysis| { - let trans = driver::phase_4_translate_to_llvm(tcx, &mir_map, analysis); + let trans = driver::phase_4_translate_to_llvm(tcx, mir_map, analysis); let crates = tcx.sess.cstore.get_used_crates(RequireDynamic); diff --git a/src/test/run-pass/issue-21296.rs b/src/test/run-pass/issue-21296.rs deleted file mode 100644 index 5e2ac61caa2..00000000000 --- a/src/test/run-pass/issue-21296.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -// pretty-expanded FIXME #23616 - -#[forbid(raw_pointer_derive)] -#[derive(Copy)] -struct Test(*const i32); - -impl Clone for Test { - fn clone(&self) -> Test { *self } -} - -fn main() {} |
