Luke Metz <luke.metz@students.olin.edu>
Luqman Aden <me@luqman.ca> <laden@csclub.uwaterloo.ca>
Luqman Aden <me@luqman.ca> <laden@mozilla.com>
-Makoto Nakashima <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
-Makoto Nakashima <makoto.nksm+github@gmail.com> gifnksm <makoto.nksm+github@gmail.com>
-Makoto Nakashima <makoto.nksm+github@gmail.com> NAKASHIMA, Makoto <makoto.nksm+github@gmail.com>
+NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
+NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm+github@gmail.com>
Marcell Pardavi <marcell.pardavi@gmail.com>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew>
Mark Sinclair <mark.edward.x@gmail.com>
Mickaël Raybaud-Roig <raybaudroigm@gmail.com> m-r-r <raybaudroigm@gmail.com>
Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com>
Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
-NAKASHIMA, Makoto <makoto.nksm+github@gmail.com>
Nathan Wilson <wilnathan@gmail.com>
Nathaniel Herman <nherman@post.harvard.edu> Nathaniel Herman <nherman@college.harvard.edu>
Neil Pankey <npankey@gmail.com> <neil@wire.im>
-Version 1.15.1 (2017-02-08)
+Version 1.15.1 (2017-02-09)
===========================
* [Fix IntoIter::as_mut_slice's signature][39466]
+* [Compile compiler builtins with `-fPIC` on 32-bit platforms][39523]
[39466]: https://github.com/rust-lang/rust/pull/39466
+[39523]: https://github.com/rust-lang/rust/pull/39523
Version 1.15.0 (2017-02-02)
"rustc_incremental 0.0.0",
"rustc_llvm 0.0.0",
"rustc_platform_intrinsics 0.0.0",
+ "serialize 0.0.0",
"syntax 0.0.0",
"syntax_pos 0.0.0",
]
python: Option<String>,
full_bootstrap: Option<bool>,
extended: Option<bool>,
+ verbose: Option<usize>,
sanitizers: Option<bool>,
}
set(&mut config.vendor, build.vendor);
set(&mut config.full_bootstrap, build.full_bootstrap);
set(&mut config.extended, build.extended);
+ set(&mut config.verbose, build.verbose);
set(&mut config.sanitizers, build.sanitizers);
if let Some(ref install) = toml.install {
# disabled by default.
#extended = false
+# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+#verbose = 0
+
# Build the sanitizer runtimes
#sanitizers = false
[stability]: http://blog.rust-lang.org/2014/10/30/Stability.html
-To install nightly Rust, you can use `rustup.sh`:
+To install nightly Rust, you can use [rustup.rs][rustup]:
+
+[rustup]: https://rustup.rs
```bash
-$ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly
+$ curl https://sh.rustup.rs -sSf | sh
+$ rustup install nightly
```
If you're concerned about the [potential insecurity][insecurity] of using `curl
use a two-step version of the installation and examine our installation script:
```bash
-$ curl -f -L https://static.rust-lang.org/rustup.sh -O
-$ sh rustup.sh --channel=nightly
+$ curl https://sh.rustup.rs -sSf -o rustup.sh
+$ sh rustup.sh
+$ rustup install nightly
```
[insecurity]: http://curlpipesh.tumblr.com
-If you're on Windows, please download either the [32-bit installer][win32] or
-the [64-bit installer][win64] and run it.
+If you're on Windows, please download the [rustup installer][installer]
+and run it.
-[win32]: https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.msi
-[win64]: https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.msi
+[installer]: https://win.rustup.rs
## Uninstalling
If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
Not every programming language is great for everyone. Just run the uninstall
-script:
+command:
```bash
-$ sudo /usr/local/lib/rustlib/uninstall.sh
+$ rustup self uninstall
```
-If you used the Windows installer, re-run the `.msi` and it will give you
-an uninstall option.
-
Some people, and somewhat rightfully so, get very upset when we tell you to
`curl | sh`. Basically, when you do this, you are trusting that the good
people who maintain Rust aren't going to hack your computer and do bad things.
}
}
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
+ fn from(slice: &'a [T]) -> Box<[T]> {
+ let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
+ boxed.copy_from_slice(slice);
+ boxed
+ }
+}
+
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<'a> From<&'a str> for Box<str> {
+ fn from(s: &'a str) -> Box<str> {
+ let boxed: Box<[u8]> = Box::from(s.as_bytes());
+ unsafe { mem::transmute(boxed) }
+ }
+}
+
impl Box<Any> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
use core::ops::Deref;
use core::result::Result::{Err, Ok};
use core::clone::Clone;
+use core::f64;
+use core::i64;
use std::boxed::Box;
assert_eq!(19, y.get());
}
}
+
+#[test]
+fn f64_slice() {
+ let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY];
+ let boxed: Box<[f64]> = Box::from(slice);
+ assert_eq!(&*boxed, slice)
+}
+
+#[test]
+fn i64_slice() {
+ let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX];
+ let boxed: Box<[i64]> = Box::from(slice);
+ assert_eq!(&*boxed, slice)
+}
+
+#[test]
+fn str_slice() {
+ let s = "Hello, world!";
+ let boxed: Box<str> = Box::from(s);
+ assert_eq!(&*boxed, s)
+}
}
impl<T: Ord> BTreeSet<T> {
- /// Visits the values representing the difference, in ascending order.
+ /// Visits the values representing the difference,
+ /// i.e. the values that are in `self` but not in `other`,
+ /// in ascending order.
///
/// # Examples
///
}
}
- /// Visits the values representing the symmetric difference, in ascending order.
+ /// Visits the values representing the symmetric difference,
+ /// i.e. the values that are in `self` or in `other` but not in both,
+ /// in ascending order.
///
/// # Examples
///
}
}
- /// Visits the values representing the intersection, in ascending order.
+ /// Visits the values representing the intersection,
+ /// i.e. the values that are both in `self` and `other`,
+ /// in ascending order.
///
/// # Examples
///
}
}
- /// Visits the values representing the union, in ascending order.
+ /// Visits the values representing the union,
+ /// i.e. all the values in `self` or `other`, without duplicates,
+ /// in ascending order.
///
/// # Examples
///
Recover::get(&self.map, value)
}
- /// Returns `true` if the set has no elements in common with `other`.
+ /// Returns `true` if `self` has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
///
/// # Examples
self.intersection(other).next().is_none()
}
- /// Returns `true` if the set is a subset of another.
+ /// Returns `true` if the set is a subset of another,
+ /// i.e. `other` contains at least all the values in `self`.
///
/// # Examples
///
true
}
- /// Returns `true` if the set is a superset of another.
+ /// Returns `true` if the set is a superset of another,
+ /// i.e. `self` contains at least all the values in `other`.
///
/// # Examples
///
/// Reserves capacity for at least `additional` more elements to be inserted
/// in the given `Vec<T>`. The collection may reserve more space to avoid
- /// frequent reallocations.
+ /// frequent reallocations. After calling `reserve`, capacity will be
+ /// greater than or equal to `self.len() + additional`. Does nothing if
+ /// capacity is already sufficient.
///
/// # Panics
///
}
/// Reserves the minimum capacity for exactly `additional` more elements to
- /// be inserted in the given `Vec<T>`. Does nothing if the capacity is already
- /// sufficient.
+ /// be inserted in the given `Vec<T>`. After calling `reserve_exact`,
+ /// capacity will be greater than or equal to `self.len() + additional`.
+ /// Does nothing if the capacity is already sufficient.
///
/// Note that the allocator may give the collection more space than it
/// requests. Therefore capacity can not be relied upon to be precisely
pub trait Debug {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for an empty format, `{}`.
pub trait Display {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `o` character.
pub trait Octal {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `b` character.
pub trait Binary {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `x` character.
pub trait LowerHex {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `X` character.
pub trait UpperHex {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `p` character.
pub trait Pointer {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `e` character.
pub trait LowerExp {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// Format trait for the `E` character.
pub trait UpperExp {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
- fn fmt(&self, &mut Formatter) -> Result;
+ fn fmt(&self, f: &mut Formatter) -> Result;
}
/// The `write` function takes an output stream, a precompiled format string,
/// Returns the `n`th element of the iterator.
///
- /// Note that all preceding elements will be consumed (i.e. discarded).
- ///
/// Like most indexing operations, the count starts from zero, so `nth(0)`
/// returns the first value, `nth(1)` the second, and so on.
///
+ /// Note that all preceding elements, as well as the returned element, will be
+ /// consumed from the iterator. That means that the preceding elements will be
+ /// discarded, and also that calling `nth(0)` multiple times on the same iterator
+ /// will return different elements.
+ ///
/// `nth()` will return [`None`] if `n` is greater than or equal to the length of the
/// iterator.
///
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! assert_eq {
- ($left:expr , $right:expr) => ({
+ ($left:expr, $right:expr) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
}
}
});
- ($left:expr , $right:expr, $($arg:tt)*) => ({
+ ($left:expr, $right:expr, $($arg:tt)+) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
panic!("assertion failed: `(left == right)` \
(left: `{:?}`, right: `{:?}`): {}", left_val, right_val,
- format_args!($($arg)*))
+ format_args!($($arg)+))
}
}
}
#[macro_export]
#[stable(feature = "assert_ne", since = "1.12.0")]
macro_rules! assert_ne {
- ($left:expr , $right:expr) => ({
+ ($left:expr, $right:expr) => ({
match (&$left, &$right) {
(left_val, right_val) => {
if *left_val == *right_val {
}
}
});
- ($left:expr , $right:expr, $($arg:tt)*) => ({
+ ($left:expr, $right:expr, $($arg:tt)+) => ({
match (&($left), &($right)) {
(left_val, right_val) => {
if *left_val == *right_val {
panic!("assertion failed: `(left != right)` \
(left: `{:?}`, right: `{:?}`): {}", left_val, right_val,
- format_args!($($arg)*))
+ format_args!($($arg)+))
}
}
}
pub trait AddAssign<Rhs=Self> {
/// The method for the `+=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn add_assign(&mut self, Rhs);
+ fn add_assign(&mut self, rhs: Rhs);
}
macro_rules! add_assign_impl {
pub trait SubAssign<Rhs=Self> {
/// The method for the `-=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn sub_assign(&mut self, Rhs);
+ fn sub_assign(&mut self, rhs: Rhs);
}
macro_rules! sub_assign_impl {
pub trait MulAssign<Rhs=Self> {
/// The method for the `*=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn mul_assign(&mut self, Rhs);
+ fn mul_assign(&mut self, rhs: Rhs);
}
macro_rules! mul_assign_impl {
pub trait DivAssign<Rhs=Self> {
/// The method for the `/=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn div_assign(&mut self, Rhs);
+ fn div_assign(&mut self, rhs: Rhs);
}
macro_rules! div_assign_impl {
pub trait RemAssign<Rhs=Self> {
/// The method for the `%=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn rem_assign(&mut self, Rhs);
+ fn rem_assign(&mut self, rhs: Rhs);
}
macro_rules! rem_assign_impl {
pub trait BitAndAssign<Rhs=Self> {
/// The method for the `&=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn bitand_assign(&mut self, Rhs);
+ fn bitand_assign(&mut self, rhs: Rhs);
}
macro_rules! bitand_assign_impl {
pub trait BitOrAssign<Rhs=Self> {
/// The method for the `|=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn bitor_assign(&mut self, Rhs);
+ fn bitor_assign(&mut self, rhs: Rhs);
}
macro_rules! bitor_assign_impl {
pub trait BitXorAssign<Rhs=Self> {
/// The method for the `^=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn bitxor_assign(&mut self, Rhs);
+ fn bitxor_assign(&mut self, rhs: Rhs);
}
macro_rules! bitxor_assign_impl {
pub trait ShlAssign<Rhs> {
/// The method for the `<<=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn shl_assign(&mut self, Rhs);
+ fn shl_assign(&mut self, rhs: Rhs);
}
macro_rules! shl_assign_impl {
pub trait ShrAssign<Rhs=Self> {
/// The method for the `>>=` operator
#[stable(feature = "op_assign_traits", since = "1.8.0")]
- fn shr_assign(&mut self, Rhs);
+ fn shr_assign(&mut self, rhs: Rhs);
}
macro_rules! shr_assign_impl {
}
}
-impl SlicePartialOrd<u8> for [u8] {
- #[inline]
- fn partial_compare(&self, other: &[u8]) -> Option<Ordering> {
+impl<A> SlicePartialOrd<A> for [A]
+ where A: Ord
+{
+ default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
Some(SliceOrd::compare(self, other))
}
}
#[doc(hidden)]
trait CharEq {
- fn matches(&mut self, char) -> bool;
+ fn matches(&mut self, c: char) -> bool;
fn only_ascii(&self) -> bool;
}
trait TwoWayStrategy {
type Output;
fn use_early_reject() -> bool;
- fn rejecting(usize, usize) -> Self::Output;
- fn matching(usize, usize) -> Self::Output;
+ fn rejecting(a: usize, b: usize) -> Self::Output;
+ fn matching(a: usize, b: usize) -> Self::Output;
}
/// Skip to match intervals as quickly as possible
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use util::nodemap::FxHashSet;
+use util::nodemap::{FxHashMap, FxHashSet};
use ty::context::TyCtxt;
use ty::{AdtDef, VariantDef, FieldDef, TyS};
use ty::{DefId, Substs};
/// Calculate the forest of DefIds from which this adt is visibly uninhabited.
pub fn uninhabited_from(
&self,
- visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>) -> DefIdForest
{
- if !visited.insert((self.did, substs)) {
- return DefIdForest::empty();
- }
-
- let ret = DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
+ DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
v.uninhabited_from(visited, tcx, substs, self.adt_kind())
- }));
- visited.remove(&(self.did, substs));
- ret
+ }))
}
}
/// Calculate the forest of DefIds from which this variant is visibly uninhabited.
pub fn uninhabited_from(
&self,
- visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>,
adt_kind: AdtKind) -> DefIdForest
/// Calculate the forest of DefIds from which this field is visibly uninhabited.
pub fn uninhabited_from(
&self,
- visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: &'tcx Substs<'tcx>,
is_enum: bool) -> DefIdForest
{
- let mut data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(visited, tcx);
+ let mut data_uninhabitedness = move || {
+ self.ty(tcx, substs).uninhabited_from(visited, tcx)
+ };
// FIXME(canndrew): Currently enum fields are (incorrectly) stored with
// Visibility::Invisible so we need to override self.vis if we're
// dealing with an enum.
/// Calculate the forest of DefIds from which this type is visibly uninhabited.
pub fn uninhabited_from(
&self,
- visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
{
match tcx.lift_to_global(&self) {
fn uninhabited_from_inner(
&self,
- visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+ visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
{
match self.sty {
TyAdt(def, substs) => {
- def.uninhabited_from(visited, tcx, substs)
+ {
+ let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
+ if !substs_set.insert(substs) {
+ // We are already calculating the inhabitedness of this type.
+ // The type must contain a reference to itself. Break the
+ // infinite loop.
+ return DefIdForest::empty();
+ }
+ if substs_set.len() >= tcx.sess.recursion_limit.get() / 4 {
+ // We have gone very deep, reinstantiating this ADT inside
+ // itself with different type arguments. We are probably
+ // hitting an infinite loop. For example, it's possible to write:
+ // a type Foo<T>
+ // which contains a Foo<(T, T)>
+ // which contains a Foo<((T, T), (T, T))>
+ // which contains a Foo<(((T, T), (T, T)), ((T, T), (T, T)))>
+ // etc.
+ let error = format!("reached recursion limit while checking
+ inhabitedness of `{}`", self);
+ tcx.sess.fatal(&error);
+ }
+ }
+ let ret = def.uninhabited_from(visited, tcx, substs);
+ let mut substs_set = visited.get_mut(&def.did).unwrap();
+ substs_set.remove(substs);
+ ret
},
TyNever => DefIdForest::full(tcx),
use syntax::abi;
use syntax::ast::{self, Name};
use syntax::symbol::{keywords, InternedString};
-use util::nodemap::FxHashSet;
+use util::nodemap::FxHashMap;
use serialize;
/// This code should only compile in modules where the uninhabitedness of Foo is
/// visible.
pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
- let mut visited = FxHashSet::default();
+ let mut visited = FxHashMap::default();
let forest = self.uninhabited_from(&mut visited, tcx);
// To check whether this type is uninhabited at all (not just from the
use rustc_const_math::ConstInt;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::indexed_vec::Idx;
use pattern::{FieldPattern, Pattern, PatternKind};
}
ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
def.variants.iter().filter_map(|v| {
- let mut visited = FxHashSet::default();
+ let mut visited = FxHashMap::default();
let forest = v.uninhabited_from(&mut visited,
cx.tcx, substs,
AdtKind::Enum);
use std::io;
use libc;
- #[cfg(target_os = "linux")]
+ #[cfg(any(target_os = "linux", target_os = "android"))]
mod os {
use libc;
}
/// Run the translation phase to LLVM, after which the AST and analysis can
+/// be discarded.
pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
analysis: ty::CrateAnalysis,
incremental_hashes_map: &IncrementalHashesMap)
const FlagStaticMember = (1 << 12),
const FlagLValueReference = (1 << 13),
const FlagRValueReference = (1 << 14),
+ const FlagMainSubprogram = (1 << 21),
}
}
}
pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
Lang: c_uint,
- File: *const c_char,
- Dir: *const c_char,
+ File: DIFile,
Producer: *const c_char,
isOptimized: bool,
Flags: *const c_char,
}
#[repr(packed)]
-#[derive(Copy, Clone)]
+#[derive(Copy)]
struct Unaligned<T>(T);
+// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
+// the field to `T::clone`, but this reference may not be properly aligned.
+impl<T: Copy> Clone for Unaligned<T> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
impl<T> Unaligned<T> {
fn get(self) -> T { self.0 }
}
use build::matches::{Binding, MatchPair, Candidate};
use hair::*;
use rustc::mir::*;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxHashMap;
use std::mem;
if self.hir.tcx().sess.features.borrow().never_type {
let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
i == variant_index || {
- let mut visited = FxHashSet::default();
+ let mut visited = FxHashMap::default();
let node_set = v.uninhabited_from(&mut visited,
self.hir.tcx(),
substs,
rustc_incremental = { path = "../librustc_incremental" }
rustc_llvm = { path = "../librustc_llvm" }
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
+serialize = { path = "../libserialize" }
syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" }
use syntax::symbol::Symbol;
use syntax_pos::Span;
+/// The LLVM module name containing crate-metadata. This includes a `.` on
+/// purpose, so it cannot clash with the name of a user-defined module.
+pub const METADATA_MODULE_NAME: &'static str = "crate.metadata";
+/// The name of the crate-metadata object file the compiler generates. Must
+/// match up with `METADATA_MODULE_NAME`.
+pub const METADATA_OBJ_NAME: &'static str = "crate.metadata.o";
+
// RLIB LLVM-BYTECODE OBJECT LAYOUT
// Version 1
// Bytes Data
remove(sess, &obj);
}
}
- remove(sess, &outputs.with_extension("metadata.o"));
+ remove(sess, &outputs.with_extension(METADATA_OBJ_NAME));
}
out_filenames
cmd.arg(root.join(obj));
}
- if sess.target.target.options.is_like_emscripten &&
- sess.panic_strategy() == PanicStrategy::Abort {
- cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]);
+ if sess.target.target.options.is_like_emscripten {
+ cmd.arg("-s");
+ cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
+ "DISABLE_EXCEPTION_CATCHING=1"
+ } else {
+ "DISABLE_EXCEPTION_CATCHING=0"
+ });
}
{
// If we're building a dynamic library then some platforms need to make sure
// that all symbols are exported correctly from the dynamic library.
- if crate_type != config::CrateTypeExecutable {
+ if crate_type != config::CrateTypeExecutable ||
+ sess.target.target.options.is_like_emscripten {
cmd.export_symbols(tmpdir, crate_type);
}
// object file, so we link that in here.
if crate_type == config::CrateTypeDylib ||
crate_type == config::CrateTypeProcMacro {
- cmd.add_object(&outputs.with_extension("metadata.o"));
+ cmd.add_object(&outputs.with_extension(METADATA_OBJ_NAME));
}
// Try to strip as much out of the generated object by removing unused
use middle::dependency_format::Linkage;
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
use session::Session;
-use session::config::CrateType;
-use session::config;
+use session::config::{self, CrateType, OptLevel, DebugInfoLevel};
+use serialize::{json, Encoder};
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
sess: sess,
info: self
}) as Box<Linker>
+ } else if sess.target.target.options.is_like_emscripten {
+ Box::new(EmLinker {
+ cmd: cmd,
+ sess: sess,
+ info: self
+ }) as Box<Linker>
} else {
Box::new(GnuLinker {
cmd: cmd,
}
}
+pub struct EmLinker<'a> {
+ cmd: &'a mut Command,
+ sess: &'a Session,
+ info: &'a LinkerInfo
+}
+
+impl<'a> Linker for EmLinker<'a> {
+ fn include_path(&mut self, path: &Path) {
+ self.cmd.arg("-L").arg(path);
+ }
+
+ fn link_staticlib(&mut self, lib: &str) {
+ self.cmd.arg("-l").arg(lib);
+ }
+
+ fn output_filename(&mut self, path: &Path) {
+ self.cmd.arg("-o").arg(path);
+ }
+
+ fn add_object(&mut self, path: &Path) {
+ self.cmd.arg(path);
+ }
+
+ fn link_dylib(&mut self, lib: &str) {
+ // Emscripten always links statically
+ self.link_staticlib(lib);
+ }
+
+ fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+ // not supported?
+ self.link_staticlib(lib);
+ }
+
+ fn link_whole_rlib(&mut self, lib: &Path) {
+ // not supported?
+ self.link_rlib(lib);
+ }
+
+ fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+ self.link_dylib(lib);
+ }
+
+ fn link_rlib(&mut self, lib: &Path) {
+ self.add_object(lib);
+ }
+
+ fn position_independent_executable(&mut self) {
+ // noop
+ }
+
+ fn args(&mut self, args: &[String]) {
+ self.cmd.args(args);
+ }
+
+ fn framework_path(&mut self, _path: &Path) {
+ bug!("frameworks are not supported on Emscripten")
+ }
+
+ fn link_framework(&mut self, _framework: &str) {
+ bug!("frameworks are not supported on Emscripten")
+ }
+
+ fn gc_sections(&mut self, _keep_metadata: bool) {
+ // noop
+ }
+
+ fn optimize(&mut self) {
+ // Emscripten performs own optimizations
+ self.cmd.arg(match self.sess.opts.optimize {
+ OptLevel::No => "-O0",
+ OptLevel::Less => "-O1",
+ OptLevel::Default => "-O2",
+ OptLevel::Aggressive => "-O3",
+ OptLevel::Size => "-Os",
+ OptLevel::SizeMin => "-Oz"
+ });
+ // Unusable until https://github.com/rust-lang/rust/issues/38454 is resolved
+ self.cmd.args(&["--memory-init-file", "0"]);
+ }
+
+ fn debuginfo(&mut self) {
+ // Preserve names or generate source maps depending on debug info
+ self.cmd.arg(match self.sess.opts.debuginfo {
+ DebugInfoLevel::NoDebugInfo => "-g0",
+ DebugInfoLevel::LimitedDebugInfo => "-g3",
+ DebugInfoLevel::FullDebugInfo => "-g4"
+ });
+ }
+
+ fn no_default_libraries(&mut self) {
+ self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
+ }
+
+ fn build_dylib(&mut self, _out_filename: &Path) {
+ bug!("building dynamic library is unsupported on Emscripten")
+ }
+
+ fn whole_archives(&mut self) {
+ // noop
+ }
+
+ fn no_whole_archives(&mut self) {
+ // noop
+ }
+
+ fn hint_static(&mut self) {
+ // noop
+ }
+
+ fn hint_dynamic(&mut self) {
+ // noop
+ }
+
+ fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
+ let symbols = &self.info.exports[&crate_type];
+
+ debug!("EXPORTED SYMBOLS:");
+
+ self.cmd.arg("-s");
+
+ let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
+ let mut encoded = String::new();
+
+ {
+ let mut encoder = json::Encoder::new(&mut encoded);
+ let res = encoder.emit_seq(symbols.len(), |encoder| {
+ for (i, sym) in symbols.iter().enumerate() {
+ encoder.emit_seq_elt(i, |encoder| {
+ encoder.emit_str(&("_".to_string() + sym))
+ })?;
+ }
+ Ok(())
+ });
+ if let Err(e) = res {
+ self.sess.fatal(&format!("failed to encode exported symbols: {}", e));
+ }
+ }
+ debug!("{}", encoded);
+ arg.push(encoded);
+
+ self.cmd.arg(arg);
+ }
+
+ fn subsystem(&mut self, _subsystem: &str) {
+ // noop
+ }
+}
+
fn exported_symbols(scx: &SharedCrateContext,
exported_symbols: &ExportedSymbols,
crate_type: CrateType)
// Clean up unwanted temporary files.
// We create the following files by default:
- // - crate.#module-name#.bc
- // - crate.#module-name#.o
- // - crate.metadata.bc
- // - crate.metadata.o
- // - crate.o (linked from crate.##.o)
- // - crate.bc (copied from crate.##.bc)
+ // - #crate#.#module-name#.bc
+ // - #crate#.#module-name#.o
+ // - #crate#.crate.metadata.bc
+ // - #crate#.crate.metadata.o
+ // - #crate#.o (linked from crate.##.o)
+ // - #crate#.bc (copied from crate.##.bc)
// We may create additional files if requested by the user (through
// `-C save-temps` or `--emit=` flags).
}
// We leave the following files around by default:
- // - crate.o
- // - crate.metadata.o
- // - crate.bc
+ // - #crate#.o
+ // - #crate#.crate.metadata.o
+ // - #crate#.bc
// These are used in linking steps and will be cleaned up afterward.
// FIXME: time_llvm_passes support - does this use a global context or
});
let metadata_module = ModuleTranslation {
- name: "metadata".to_string(),
+ name: link::METADATA_MODULE_NAME.to_string(),
symbol_name_hash: 0, // we always rebuild metadata, at least for now
source: ModuleSource::Translated(ModuleLlvm {
llcx: shared_ccx.metadata_llcx(),
let producer = CString::new(producer).unwrap();
let flags = "\0";
let split_name = "\0";
- return unsafe {
- llvm::LLVMRustDIBuilderCreateCompileUnit(
+
+ unsafe {
+ let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
+ debug_context.builder, compile_unit_name, work_dir.as_ptr());
+
+ return llvm::LLVMRustDIBuilderCreateCompileUnit(
debug_context.builder,
DW_LANG_RUST,
- compile_unit_name,
- work_dir.as_ptr(),
+ file_metadata,
producer.as_ptr(),
sess.opts.optimize != config::OptLevel::No,
flags.as_ptr() as *const _,
let function_name = CString::new(name).unwrap();
let linkage_name = CString::new(linkage_name).unwrap();
+ let mut flags = DIFlags::FlagPrototyped;
+ match *cx.sess().entry_fn.borrow() {
+ Some((id, _)) => {
+ if local_id == Some(id) {
+ flags = flags | DIFlags::FlagMainSubprogram;
+ }
+ }
+ None => {}
+ };
+
let fn_metadata = unsafe {
llvm::LLVMRustDIBuilderCreateFunction(
DIB(cx),
is_local_to_unit,
true,
scope_line as c_uint,
- DIFlags::FlagPrototyped,
+ flags,
cx.sess().opts.optimize != config::OptLevel::No,
llfn,
template_parameters,
#[macro_use] extern crate syntax;
extern crate syntax_pos;
extern crate rustc_errors as errors;
+extern crate serialize;
pub use rustc::session;
pub use rustc::middle;
while span.expn_id != NO_EXPANSION && span.expn_id != COMMAND_LINE_EXPN {
if let Some(callsite_span) = cm.with_expn_info(span.expn_id,
|ei| ei.map(|ei| ei.call_site.clone())) {
+ // When the current function itself is a result of macro expansion,
+ // we stop at the function body level because no line stepping can occurr
+ // at the level above that.
+ if self.mir.span.expn_id != NO_EXPANSION &&
+ span.expn_id == self.mir.span.expn_id {
+ break;
+ }
span = callsite_span;
} else {
break;
}
}
let scope = self.scope_metadata_for_loc(source_info.scope, span.lo);
- // Use span of the outermost call site, while keeping the original lexical scope
+ // Use span of the outermost expansion site, while keeping the original lexical scope.
(scope, span)
}
}
self.lookup_op_method(expr, ty_mut.ty, vec![rhs_ty_var],
Symbol::intern(name), trait_def_id,
lhs_expr).is_ok() {
- err.span_note(
- lhs_expr.span,
+ err.note(
&format!(
- "this is a reference of type that `{}` can be applied to, \
- you need to dereference this variable once for this \
+ "this is a reference to a type that `{}` can be applied \
+ to; you need to dereference this variable once for this \
operation to work",
op.node.as_str()));
}
rhs_expr, rhs_ty_var, &mut err) {
// This has nothing here because it means we did string
// concatenation (e.g. "Hello " + "World!"). This means
- // we don't want the span in the else clause to be emmitted
+ // we don't want the note in the else clause to be emitted
} else {
- span_note!(&mut err, lhs_expr.span,
- "an implementation of `{}` might be missing for `{}`",
- missing_trait, lhs_ty);
+ err.note(
+ &format!("an implementation of `{}` might be missing for `{}`",
+ missing_trait, lhs_ty));
}
}
err.emit();
rhs_expr: &'gcx hir::Expr,
rhs_ty_var: Ty<'tcx>,
mut err: &mut errors::DiagnosticBuilder) -> bool {
- // If this function returns false it means we use it to make sure we print
- // out the an "implementation of span_note!" above where this function is
- // called and if true we don't.
+ // If this function returns true it means a note was printed, so we don't need
+ // to print the normal "implementation of `std::ops::Add` might be missing" note
let mut is_string_addition = false;
let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var);
if let TyRef(_, l_ty) = lhs_ty.sty {
if let TyRef(_, r_ty) = rhs_ty.sty {
if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr {
- span_note!(&mut err, lhs_expr.span,
- "`+` can't be used to concatenate two `&str` strings");
+ err.note("`+` can't be used to concatenate two `&str` strings");
let codemap = self.tcx.sess.codemap();
let suggestion =
match (codemap.span_to_snippet(lhs_expr.span),
fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
c: &clean::Constant) -> fmt::Result {
- write!(w, "<pre class='rust const'>{vis}const \
+ write!(w, "<pre class='rust const'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{vis}const \
{name}: {typ}{init}</pre>",
vis = VisSpace(&it.visibility),
name = it.name.as_ref().unwrap(),
fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
s: &clean::Static) -> fmt::Result {
- write!(w, "<pre class='rust static'>{vis}static {mutability}\
+ write!(w, "<pre class='rust static'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{vis}static {mutability}\
{name}: {typ}{init}</pre>",
vis = VisSpace(&it.visibility),
mutability = MutableSpace(s.mutability),
AbiSpace(f.abi),
it.name.as_ref().unwrap(),
f.generics).len();
- write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
+ write!(w, "<pre class='rust fn'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{vis}{constness}{unsafety}{abi}fn \
{name}{generics}{decl}{where_clause}</pre>",
vis = VisSpace(&it.visibility),
constness = ConstnessSpace(vis_constness),
}
// Output the trait definition
- write!(w, "<pre class='rust trait'>{}{}trait {}{}{}{} ",
+ write!(w, "<pre class='rust trait'>")?;
+ render_attributes(w, it)?;
+ write!(w, "{}{}trait {}{}{}{} ",
VisSpace(&it.visibility),
UnsafetySpace(t.unsafety),
it.name.as_ref().unwrap(),
fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
t: &clean::Typedef) -> fmt::Result {
let indent = format!("type {}{:#} ", it.name.as_ref().unwrap(), t.generics).len();
- write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
+ write!(w, "<pre class='rust typedef'>")?;
+ render_attributes(w, it)?;
+ write!(w, "type {}{}{where_clause} = {type_};</pre>",
it.name.as_ref().unwrap(),
t.generics,
where_clause = WhereClause(&t.generics, indent),
Iter { iter: self.map.keys() }
}
- /// Visit the values representing the difference.
+ /// Visit the values representing the difference,
+ /// i.e. the values that are in `self` but not in `other`.
///
/// # Examples
///
}
}
- /// Visit the values representing the symmetric difference.
+ /// Visit the values representing the symmetric difference,
+ /// i.e. the values that are in `self` or in `other` but not in both.
///
/// # Examples
///
SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
}
- /// Visit the values representing the intersection.
+ /// Visit the values representing the intersection,
+ /// i.e. the values that are both in `self` and `other`.
///
/// # Examples
///
}
}
- /// Visit the values representing the union.
+ /// Visit the values representing the union,
+ /// i.e. all the values in `self` or `other`, without duplicates.
///
/// # Examples
///
Recover::get(&self.map, value)
}
- /// Returns `true` if the set has no elements in common with `other`.
+ /// Returns `true` if `self` has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
///
/// # Examples
self.iter().all(|v| !other.contains(v))
}
- /// Returns `true` if the set is a subset of another.
+ /// Returns `true` if the set is a subset of another,
+ /// i.e. `other` contains at least all the values in `self`.
///
/// # Examples
///
self.iter().all(|v| other.contains(v))
}
- /// Returns `true` if the set is a superset of another.
+ /// Returns `true` if the set is a superset of another,
+ /// i.e. `self` contains at least all the values in `other`.
///
/// # Examples
///
//! * You want to find the largest or smallest key that is smaller or larger
//! than something.
//! * You want to be able to get all of the entries in order on-demand.
-//! * You want a sorted map.
+//! * You want a map sorted by its keys.
//!
//! ### Use the `Set` variant of any of these `Map`s when:
//! * You just want to remember which keys you've seen.
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unique)]
+#![feature(untagged_unions)]
#![feature(unwind_attributes)]
#![feature(vec_push_all)]
#![feature(zero_one)]
/// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
- struct Data<F, R> {
+ #[allow(unions_with_drop_fields)]
+ union Data<F, R> {
f: F,
r: R,
}
// We do some sketchy operations with ownership here for the sake of
- // performance. The `Data` structure is never actually fully valid, but
- // instead it always contains at least one uninitialized field. We can only
- // pass pointers down to `__rust_maybe_catch_panic` (can't pass objects by
- // value), so we do all the ownership tracking here manully.
+ // performance. We can only pass pointers down to
+ // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
+ // the ownership tracking here manually using a union.
//
- // Note that this is all invalid if any of these functions unwind, but the
- // whole point of this function is to prevent that! As a result we go
- // through a transition where:
+ // We go through a transition where:
//
- // * First, only the closure we're going to call is initialized. The return
- // value is uninitialized.
+ // * First, we set the data to be the closure that we're going to call.
// * When we make the function call, the `do_call` function below, we take
- // ownership of the function pointer, replacing it with uninitialized
- // data. At this point the `Data` structure is entirely uninitialized, but
- // it won't drop due to an unwind because it's owned on the other side of
- // the catch panic.
+ // ownership of the function pointer. At this point the `Data` union is
+ // entirely uninitialized.
// * If the closure successfully returns, we write the return value into the
// data's return slot. Note that `ptr::write` is used as it's overwriting
// uninitialized data.
// in one of two states:
//
// 1. The closure didn't panic, in which case the return value was
- // filled in. We have to be careful to `forget` the closure,
- // however, as ownership was passed to the `do_call` function.
+ // filled in. We move it out of `data` and return it.
// 2. The closure panicked, in which case the return value wasn't
- // filled in. In this case the entire `data` structure is invalid,
- // so we forget the entire thing.
+ // filled in. In this case the entire `data` union is invalid, so
+ // there is no need to drop anything.
//
// Once we stack all that together we should have the "most efficient'
// method of calling a catch panic whilst juggling ownership.
let mut any_vtable = 0;
let mut data = Data {
f: f,
- r: mem::uninitialized(),
};
let r = __rust_maybe_catch_panic(do_call::<F, R>,
&mut any_vtable);
return if r == 0 {
- let Data { f, r } = data;
- mem::forget(f);
debug_assert!(update_panic_count(0) == 0);
- Ok(r)
+ Ok(data.r)
} else {
- mem::forget(data);
update_panic_count(-1);
debug_assert!(update_panic_count(0) == 0);
Err(mem::transmute(raw::TraitObject {
let mut first: bool = true;
let mut v = vec![];
while !kets.contains(&&self.token) {
+ match self.token {
+ token::CloseDelim(..) | token::Eof => break,
+ _ => {}
+ };
match sep.sep {
Some(ref t) => {
if first {
return Ok((None, kleene_op));
}
- let separator = self.bump_and_get();
+ let separator = match self.token {
+ token::CloseDelim(..) => None,
+ _ => Some(self.bump_and_get()),
+ };
match parse_kleene_op(self)? {
- Some(zerok) => Ok((Some(separator), zerok)),
+ Some(zerok) => Ok((separator, zerok)),
None => return Err(self.fatal("expected `*` or `+`"))
}
}
tts: tts,
})))
},
- token::CloseDelim(_) | token::Eof => unreachable!(),
+ token::CloseDelim(..) | token::Eof => Ok(TokenTree::Token(self.span, token::Eof)),
token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => self.parse_unquoted(),
_ => Ok(TokenTree::Token(self.span, self.bump_and_get())),
}
let test_threads = match matches.opt_str("test-threads") {
Some(n_str) =>
match n_str.parse::<usize>() {
+ Ok(0) =>
+ return Some(Err(format!("argument for --test-threads must not be 0"))),
Ok(n) => Some(n),
Err(e) =>
return Some(Err(format!("argument for --test-threads must be a number > 0 \
FlagStaticMember = (1 << 12),
FlagLValueReference = (1 << 13),
FlagRValueReference = (1 << 14),
+ FlagMainSubprogram = (1 << 21),
// Do not add values that are not supported by the minimum LLVM
// version we support!
};
if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
Result |= DINode::DIFlags::FlagRValueReference;
}
+#if LLVM_RUSTLLVM || LLVM_VERSION_GE(4, 0)
+ if (isSet(Flags & LLVMRustDIFlags::FlagMainSubprogram)) {
+ Result |= DINode::DIFlags::FlagMainSubprogram;
+ }
+#endif
return Result;
}
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateCompileUnit(
- LLVMRustDIBuilderRef Builder, unsigned Lang, const char *File,
- const char *Dir, const char *Producer, bool isOptimized, const char *Flags,
+ LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMRustMetadataRef FileRef,
+ const char *Producer, bool isOptimized, const char *Flags,
unsigned RuntimeVer, const char *SplitName) {
- return wrap(Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
+ auto *File = unwrapDI<DIFile>(FileRef);
+
+#if LLVM_VERSION_GE(4, 0)
+ return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized,
Flags, RuntimeVer, SplitName));
+#else
+ return wrap(Builder->createCompileUnit(Lang, File->getFilename(),
+ File->getDirectory(), Producer, isOptimized,
+ Flags, RuntimeVer, SplitName));
+#endif
}
extern "C" LLVMRustMetadataRef
--- /dev/null
+// Copyright 2016 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.
+
+// The minimum LLVM version is set to 3.8, but really this test
+// depends on a patch that is was committed to upstream LLVM before
+// 4.0; and also backported to the Rust LLVM fork.
+
+// ignore-tidy-linelength
+// ignore-windows
+// ignore-macos
+// min-llvm-version 3.8
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DIFlagMainSubprogram{{.*}}
+
+pub fn main() {
+}
--- /dev/null
+// Copyright 2016 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.
+
+// The minimum LLVM version is set to 3.8, but really this test
+// depends on a patch that is was committed to upstream LLVM before
+// 4.0; and also backported to the Rust LLVM fork.
+
+// ignore-tidy-linelength
+// ignore-windows
+// ignore-macos
+// min-llvm-version 3.8
+
+// compile-flags: -g -C no-prepopulate-passes
+
+#![feature(start)]
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DIFlagMainSubprogram{{.*}}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+ return 0;
+}
let vr = v.iter().filter(|x| {
x % 2 == 0
//~^ ERROR binary operation `%` cannot be applied to type `&&{integer}`
- //~| NOTE this is a reference of type that `%` can be applied to
+ //~| NOTE this is a reference to a type that `%` can be applied to
//~| NOTE an implementation of `std::ops::Rem` might be missing for `&&{integer}`
});
println!("{:?}", vr);
--- /dev/null
+// 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.
+
+
+fn main() {
+ const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
+ const IDX: usize = 3;
+ const VAL: i32 = ARR[IDX];
+ const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; //~ ERROR constant evaluation error
+}
--- /dev/null
+// Copyright 2012-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.
+
+// error-pattern:reached recursion limit
+
+#![feature(never_type)]
+
+struct Foo<'a, T: 'a> {
+ ph: std::marker::PhantomData<T>,
+ foo: &'a Foo<'a, (T, T)>,
+}
+
+fn wub(f: Foo<!>) {
+ match f {}
+}
+
+fn main() {}
+
--- /dev/null
+// Copyright 2017 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.
+
+macro_rules! assign {
+ (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+`
+ $($a)* = $($b)*
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2017 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.
+
+fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
+//~| ERROR expected one of `->`, `where`, or `{`, found `]`
+// FIXME(jseyfried): avoid emitting the second error (preexisting)
+
+fn main() {}
--- /dev/null
+// Copyright 2013-2017 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.
+
+fn included() {
+ foo!(); // #inc-loc1
+
+ foo2!(); // #inc-loc2
+
+ zzz(); // #inc-loc3
+}
// gdb-command:frame
// gdb-check:[...]#loc6[...]
+// gdb-command:continue
+// gdb-command:step
+// gdb-command:frame
+// gdb-check:[...]#inc-loc1[...]
+// gdb-command:next
+// gdb-command:frame
+// gdb-check:[...]#inc-loc2[...]
+// gdb-command:next
+// gdb-command:frame
+// gdb-check:[...]#inc-loc3[...]
+
// === LLDB TESTS ==================================================================================
// lldb-command:set set stop-line-count-before 0
// lldb-command:frame select
// lldb-check:[...]#loc5[...]
+// lldb-command:continue
+// lldb-command:step
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc1[...]
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc2[...]
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc3[...]
+
macro_rules! foo {
() => {
let a = 1;
"world");
zzz(); // #loc6
+
+ included(); // #break
}
fn zzz() {()}
+
+include!("macro-stepping.inc");
+++ /dev/null
-error[E0369]: binary operation `+` cannot be applied to type `&'static str`
- --> src/test/ui/span/issue-39018.rs:2:13
- |
-2 | let x = "Hello " + "World!";
- | ^^^^^^^^
- |
-note: `+` can't be used to concatenate two `&str` strings
- --> src/test/ui/span/issue-39018.rs:2:13
- |
-2 | let x = "Hello " + "World!";
- | ^^^^^^^^
-help: to_owned() can be used to create an owned `String` from a string reference. This allows concatenation since the `String` is owned.
- | let x = "Hello ".to_owned() + "World!";
-
-error[E0369]: binary operation `+` cannot be applied to type `World`
- --> src/test/ui/span/issue-39018.rs:7:13
- |
-7 | let y = World::Hello + World::Goodbye;
- | ^^^^^^^^^^^^
- |
-note: an implementation of `std::ops::Add` might be missing for `World`
- --> src/test/ui/span/issue-39018.rs:7:13
- |
-7 | let y = World::Hello + World::Goodbye;
- | ^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
--- /dev/null
+// Copyright 2017 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.
+
+fn worker() -> ! {
+ panic!()
+}
+
+fn main() {
+ std::panic::catch_unwind(worker).unwrap_err();
+}
a: T
}
-#[repr(packed)]
-struct Packed<T: ?Sized> {
- a: u8,
- b: T
-}
-
struct HasDrop<T: ?Sized> {
ptr: Box<usize>,
data: T
// The pointers should be the same
assert_eq!(ptr1, ptr2);
- // Test that packed structs are handled correctly
- let p : Packed<usize> = Packed { a: 0, b: 13 };
- assert_eq!(p.b.get(), 13);
- let p : &Packed<Bar> = &p;
- assert_eq!(p.b.get(), 13);
-
// Test that nested DSTs work properly
let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
assert_eq!(f.b.b.get(), 17);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::fmt;
+
#[repr(C)]
enum CEnum {
Hello = 30,
}
fn test1(c: CEnum) -> i32 {
- let c2 = CEnum::Hello;
- match (c, c2) {
- (CEnum::Hello, CEnum::Hello) => 42,
- (CEnum::World, CEnum::Hello) => 0,
- _ => 1
- }
+ let c2 = CEnum::Hello;
+ match (c, c2) {
+ (CEnum::Hello, CEnum::Hello) => 42,
+ (CEnum::World, CEnum::Hello) => 0,
+ _ => 1
+ }
}
#[repr(packed)]
-#[derive(PartialEq, Debug)]
struct Pakd {
a: u64,
b: u32,
e: ()
}
+// It is unsafe to use #[derive(Debug)] on a packed struct because the code generated by the derive
+// macro takes references to the fields instead of accessing them directly.
+impl fmt::Debug for Pakd {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ // It's important that we load the fields into locals by-value here. This will do safe
+ // unaligned loads into the locals, then pass references to the properly-aligned locals to
+ // the formatting code.
+ let Pakd { a, b, c, d, e } = *self;
+ f.debug_struct("Pakd")
+ .field("a", &a)
+ .field("b", &b)
+ .field("c", &c)
+ .field("d", &d)
+ .field("e", &e)
+ .finish()
+ }
+}
+
+// It is unsafe to use #[derive(PartialEq)] on a packed struct because the code generated by the
+// derive macro takes references to the fields instead of accessing them directly.
+impl PartialEq for Pakd {
+ fn eq(&self, other: &Pakd) -> bool {
+ self.a == other.a &&
+ self.b == other.b &&
+ self.c == other.c &&
+ self.d == other.d &&
+ self.e == other.e
+ }
+}
+
impl Drop for Pakd {
fn drop(&mut self) {}
}
}
fn main() {
- assert_eq!(test1(CEnum::Hello), 42);
- assert_eq!(test1(CEnum::World), 0);
- assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () });
- assert_eq!(test3(), TupleLike(42, 42));
- let t4 = test4(TupleLike);
- assert_eq!(t4.0, t4.1);
- let t5 = test5(Some);
- assert_eq!(t5.0, t5.1);
+ assert_eq!(test1(CEnum::Hello), 42);
+ assert_eq!(test1(CEnum::World), 0);
+ assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () });
+ assert_eq!(test3(), TupleLike(42, 42));
+ let t4 = test4(TupleLike);
+ assert_eq!(t4.0, t4.1);
+ let t5 = test5(Some);
+ assert_eq!(t5.0, t5.1);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// ignore-stage0
-// ignore-stage1
-
// ignore-emscripten
#![feature(i128_type, test)]
--- /dev/null
+// Copyright 2017 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.
+
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html '//*[@class="docblock attributes"]' '#[no_mangle]'
+#[no_mangle]
+pub extern "C" fn f() {}
+
+// @has foo/fn.g.html '//*[@class="docblock attributes"]' '#[export_name = "bar"]'
+#[export_name = "bar"]
+pub extern "C" fn g() {}
+
+// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[repr(i64)]'
+// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[must_use]'
+#[repr(i64)]
+#[must_use]
+pub enum Foo {
+ Bar,
+}
--- /dev/null
+// Copyright 2017 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.
+
+fn main() {
+ assert_eq!(1, 1,);
+}
--- /dev/null
+error: unexpected end of macro invocation
+ --> $DIR/assert_eq_trailing_comma.rs:12:20
+ |
+12 | assert_eq!(1, 1,);
+ | ^
+
--- /dev/null
+// Copyright 2017 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.
+
+fn main() {
+ assert_ne!(1, 2,);
+}
--- /dev/null
+error: unexpected end of macro invocation
+ --> $DIR/assert_ne_trailing_comma.rs:12:20
+ |
+12 | assert_ne!(1, 2,);
+ | ^
+
12 | let x = "Hello " + "World!";
| ^^^^^^^^
|
-note: `+` can't be used to concatenate two `&str` strings
- --> $DIR/issue-39018.rs:12:13
- |
-12 | let x = "Hello " + "World!";
- | ^^^^^^^^
+ = note: `+` can't be used to concatenate two `&str` strings
help: to_owned() can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left.
| let x = "Hello ".to_owned() + "World!";
17 | let y = World::Hello + World::Goodbye;
| ^^^^^^^^^^^^
|
-note: an implementation of `std::ops::Add` might be missing for `World`
- --> $DIR/issue-39018.rs:17:13
- |
-17 | let y = World::Hello + World::Goodbye;
- | ^^^^^^^^^^^^
+ = note: an implementation of `std::ops::Add` might be missing for `World`
error: aborting due to 2 previous errors
// and wrap it up in a `Value::Table`.
let mut manifest = BTreeMap::new();
manifest.insert("manifest-version".to_string(),
- toml::encode(&manifest_version));
- manifest.insert("date".to_string(), toml::encode(&date));
+ toml::Value::String(manifest_version));
+ manifest.insert("date".to_string(), toml::Value::String(date));
manifest.insert("pkg".to_string(), toml::encode(&pkg));
let manifest = toml::Value::Table(manifest).to_string();
fn hash(&self, path: &Path) -> String {
let sha = t!(Command::new("shasum")
.arg("-a").arg("256")
- .arg(path)
+ .arg(path.file_name().unwrap())
+ .current_dir(path.parent().unwrap())
.output());
assert!(sha.status.success());
// FIXME get this whitelist empty.
let whitelist = vec![
"abi_ptx", "simd", "static_recursion",
- "cfg_target_has_atomic", "staged_api", "const_indexing",
+ "cfg_target_has_atomic", "staged_api",
"unboxed_closures", "stmt_expr_attributes",
"cfg_target_thread_local", "unwind_attributes",
"inclusive_range_syntax"