Merge branch 'master' of github.com:1011X/rust

This commit is contained in:
1011X 2018-03-08 22:57:54 -05:00
commit 39c3a37018
160 changed files with 2361 additions and 1388 deletions

5
src/Cargo.lock generated
View file

@ -2585,6 +2585,11 @@ dependencies = [
[[package]]
name = "tidy"
version = "0.1.0"
dependencies = [
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"

View file

@ -810,6 +810,7 @@ impl Step for Src {
"src/libterm",
"src/jemalloc",
"src/libprofiler_builtins",
"src/stdsimd",
];
let std_src_dirs_exclude = [
"src/libcompiler_builtins/compiler-rt/test",

View file

@ -528,6 +528,7 @@ impl Step for Tidy {
println!("tidy check ({})", host);
let mut cmd = builder.tool_cmd(Tool::Tidy);
cmd.arg(build.src.join("src"));
cmd.arg(&build.initial_cargo);
if !build.config.vendor {
cmd.arg("--no-vendor");
}

View file

@ -1,93 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2012-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.
#
# this script attempts to turn doc comment attributes (#[doc = "..."])
# into sugared-doc-comments (/** ... */ and /// ...)
#
# it sugarises all .rs/.rc files underneath the working directory
#
import sys
import os
import fnmatch
import re
DOC_PATTERN = '^(?P<indent>[\\t ]*)#\\[(\\s*)doc(\\s*)=' + \
'(\\s*)"(?P<text>(\\"|[^"])*?)"(\\s*)\\]' + \
'(?P<semi>;)?'
ESCAPES = [("\\'", "'"),
('\\"', '"'),
("\\n", "\n"),
("\\r", "\r"),
("\\t", "\t")]
def unescape(s):
for (find, repl) in ESCAPES:
s = s.replace(find, repl)
return s
def block_trim(s):
lns = s.splitlines()
# remove leading/trailing whitespace-lines
while lns and not lns[0].strip():
lns = lns[1:]
while lns and not lns[-1].strip():
lns = lns[:-1]
# remove leading horizontal whitespace
n = sys.maxsize
for ln in lns:
if ln.strip():
n = min(n, len(re.search('^\s*', ln).group()))
if n != sys.maxsize:
lns = [ln[n:] for ln in lns]
# strip trailing whitespace
lns = [ln.rstrip() for ln in lns]
return lns
def replace_doc(m):
indent = m.group('indent')
text = block_trim(unescape(m.group('text')))
if len(text) > 1:
inner = '!' if m.group('semi') else '*'
starify = lambda s: indent + ' *' + (' ' + s if s else '')
text = '\n'.join(map(starify, text))
repl = indent + '/*' + inner + '\n' + text + '\n' + indent + ' */'
else:
inner = '!' if m.group('semi') else '/'
repl = indent + '//' + inner + ' ' + text[0]
return repl
def sugarise_file(path):
s = open(path).read()
r = re.compile(DOC_PATTERN, re.MULTILINE | re.DOTALL)
ns = re.sub(r, replace_doc, s)
if s != ns:
open(path, 'w').write(ns)
for (dirpath, dirnames, filenames) in os.walk('.'):
for name in fnmatch.filter(filenames, '*.r[sc]'):
sugarise_file(os.path.join(dirpath, name))

View file

@ -964,7 +964,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
/// An owning iterator over the elements of a `BinaryHeap`.
@ -1019,7 +1019,7 @@ impl<T> ExactSizeIterator for IntoIter<T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
/// A draining iterator over the elements of a `BinaryHeap`.
@ -1065,7 +1065,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T: 'a> FusedIterator for Drain<'a, T> {}
#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]

View file

@ -722,7 +722,7 @@ impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}

View file

@ -1156,7 +1156,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1235,7 +1235,7 @@ impl<'a, K: 'a, V: 'a> ExactSizeIterator for IterMut<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1365,7 +1365,7 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<K, V> FusedIterator for IntoIter<K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1395,7 +1395,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1432,7 +1432,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1482,7 +1482,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
@ -1561,7 +1561,7 @@ impl<'a, K, V> Range<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for Range<'a, K, V> {}
#[stable(feature = "btree_range", since = "1.17.0")]
@ -1630,7 +1630,7 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, K, V> FusedIterator for RangeMut<'a, K, V> {}
impl<'a, K, V> RangeMut<'a, K, V> {

View file

@ -946,7 +946,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {
fn len(&self) -> usize { self.iter.len() }
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -971,7 +971,7 @@ impl<T> ExactSizeIterator for IntoIter<T> {
fn len(&self) -> usize { self.iter.len() }
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
#[stable(feature = "btree_range", since = "1.17.0")]
@ -997,7 +997,7 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Range<'a, T> {}
/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None
@ -1044,7 +1044,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T: Ord> FusedIterator for Difference<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1078,7 +1078,7 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T: Ord> FusedIterator for SymmetricDifference<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1116,7 +1116,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T: Ord> FusedIterator for Intersection<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -1150,5 +1150,5 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T: Ord> FusedIterator for Union<'a, T> {}

View file

@ -96,7 +96,6 @@
#![feature(fmt_internals)]
#![feature(from_ref)]
#![feature(fundamental)]
#![feature(fused)]
#![feature(generic_param_attrs)]
#![feature(i128_type)]
#![feature(inclusive_range)]
@ -124,8 +123,9 @@
#![feature(allocator_internals)]
#![feature(on_unimplemented)]
#![feature(exact_chunks)]
#![feature(pointer_methods)]
#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))]
#![cfg_attr(not(test), feature(fn_traits, placement_new_protocol, swap_with_slice, i128))]
#![cfg_attr(test, feature(test, box_heap))]
// Allow testing this library

View file

@ -897,7 +897,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -946,7 +946,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
impl<'a, T> IterMut<'a, T> {
@ -1117,7 +1117,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IntoIter<T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -43,6 +43,7 @@ use core::str as core_str;
use core::str::pattern::Pattern;
use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
use core::mem;
use core::ptr;
use core::iter::FusedIterator;
use std_unicode::str::{UnicodeStr, Utf16Encoder};
@ -171,7 +172,7 @@ impl<'a> Iterator for EncodeUtf16<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for EncodeUtf16<'a> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -2066,9 +2067,59 @@ impl str {
/// ```
#[stable(feature = "repeat_str", since = "1.16.0")]
pub fn repeat(&self, n: usize) -> String {
let mut s = String::with_capacity(self.len() * n);
s.extend((0..n).map(|_| self));
s
if n == 0 {
return String::new();
}
// If `n` is larger than zero, it can be split as
// `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`.
// `2^expn` is the number represented by the leftmost '1' bit of `n`,
// and `rem` is the remaining part of `n`.
// Using `Vec` to access `set_len()`.
let mut buf = Vec::with_capacity(self.len() * n);
// `2^expn` repetition is done by doubling `buf` `expn`-times.
buf.extend(self.as_bytes());
{
let mut m = n >> 1;
// If `m > 0`, there are remaining bits up to the leftmost '1'.
while m > 0 {
// `buf.extend(buf)`:
unsafe {
ptr::copy_nonoverlapping(
buf.as_ptr(),
(buf.as_mut_ptr() as *mut u8).add(buf.len()),
buf.len(),
);
// `buf` has capacity of `self.len() * n`.
let buf_len = buf.len();
buf.set_len(buf_len * 2);
}
m >>= 1;
}
}
// `rem` (`= n - 2^expn`) repetition is done by copying
// first `rem` repetitions from `buf` itself.
let rem_len = self.len() * n - buf.len(); // `self.len() * rem`
if rem_len > 0 {
// `buf.extend(buf[0 .. rem_len])`:
unsafe {
// This is non-overlapping since `2^expn > rem`.
ptr::copy_nonoverlapping(
buf.as_ptr(),
(buf.as_mut_ptr() as *mut u8).add(buf.len()),
rem_len,
);
// `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`).
let buf_cap = buf.capacity();
buf.set_len(buf_cap);
}
}
unsafe { String::from_utf8_unchecked(buf) }
}
/// Checks if all characters in this string are within the ASCII range.

View file

@ -2254,5 +2254,5 @@ impl<'a> DoubleEndedIterator for Drain<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for Drain<'a> {}

View file

@ -2273,7 +2273,7 @@ impl<T> ExactSizeIterator for IntoIter<T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -2379,7 +2379,7 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Drain<'a, T> {}
/// A place for insertion at the back of a `Vec`.

View file

@ -1991,7 +1991,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
@ -2084,7 +2084,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
/// An owning iterator over the elements of a `VecDeque`.
@ -2140,7 +2140,7 @@ impl<T> ExactSizeIterator for IntoIter<T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
/// A draining iterator over the elements of a `VecDeque`.
@ -2247,7 +2247,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
#[stable(feature = "drain", since = "1.6.0")]
impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T: 'a> FusedIterator for Drain<'a, T> {}
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -136,7 +136,7 @@ impl DoubleEndedIterator for EscapeDefault {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for EscapeDefault {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDefault {}
#[stable(feature = "std_debug", since = "1.16.0")]

View file

@ -10,6 +10,24 @@
//! Shareable mutable containers.
//!
//! Rust memory safety is based on this rule: Given an object `T`, it is only possible to
//! have one of the following:
//!
//! - Having several immutable references (`&T`) to the object (also known as **aliasing**).
//! - Having one mutable reference (`&mut T`) to the object (also known as **mutability**).
//!
//! This is enforced by the Rust compiler. However, there are situations where this rule is not
//! flexible enough. Sometimes it is required to have multiple references to an object and yet
//! mutate it.
//!
//! Shareable mutable containers exist to permit mutability in a controlled manner, even in the
//! presence of aliasing. Both `Cell<T>` and `RefCell<T>` allows to do this in a single threaded
//! way. However, neither `Cell<T>` nor `RefCell<T>` are thread safe (they do not implement
//! `Sync`). If you need to do aliasing and mutation between multiple threads it is possible to
//! use [`Mutex`](../../std/sync/struct.Mutex.html),
//! [`RwLock`](../../std/sync/struct.RwLock.html) or
//! [`atomic`](../../core/sync/atomic/index.html) types.
//!
//! Values of the `Cell<T>` and `RefCell<T>` types may be mutated through shared references (i.e.
//! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`)
//! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast

View file

@ -79,7 +79,7 @@ pub const MAX: char = '\u{10ffff}';
/// Converts a `u32` to a `char`.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be casted to one with
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// [`as`]:
///
/// ```
@ -131,7 +131,7 @@ pub fn from_u32(i: u32) -> Option<char> {
/// Converts a `u32` to a `char`, ignoring validity.
///
/// Note that all [`char`]s are valid [`u32`]s, and can be casted to one with
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
/// [`as`]:
///
/// ```
@ -643,7 +643,7 @@ impl ExactSizeIterator for EscapeUnicode {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeUnicode {}
#[stable(feature = "char_struct_display", since = "1.16.0")]
@ -756,7 +756,7 @@ impl ExactSizeIterator for EscapeDefault {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDefault {}
#[stable(feature = "char_struct_display", since = "1.16.0")]
@ -790,7 +790,7 @@ impl Iterator for EscapeDebug {
#[stable(feature = "char_escape_debug", since = "1.20.0")]
impl ExactSizeIterator for EscapeDebug { }
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl FusedIterator for EscapeDebug {}
#[stable(feature = "char_escape_debug", since = "1.20.0")]
@ -904,5 +904,5 @@ impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "decode_utf8", issue = "33906")]
impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {}

View file

@ -1292,6 +1292,10 @@ extern "rust-intrinsic" {
/// Reverses the bytes in an integer type `T`.
pub fn bswap<T>(x: T) -> T;
/// Reverses the bits in an integer type `T`.
#[cfg(not(stage0))]
pub fn bitreverse<T>(x: T) -> T;
/// Performs checked integer addition.
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `overflowing_add` method. For example,

View file

@ -1180,19 +1180,19 @@ pub trait Iterator {
///
/// // this iterator sequence is complex.
/// let sum = a.iter()
/// .cloned()
/// .filter(|&x| x % 2 == 0)
/// .fold(0, |sum, i| sum + i);
/// .cloned()
/// .filter(|x| x % 2 == 0)
/// .fold(0, |sum, i| sum + i);
///
/// println!("{}", sum);
///
/// // let's add some inspect() calls to investigate what's happening
/// let sum = a.iter()
/// .cloned()
/// .inspect(|x| println!("about to filter: {}", x))
/// .filter(|&x| x % 2 == 0)
/// .inspect(|x| println!("made it through filter: {}", x))
/// .fold(0, |sum, i| sum + i);
/// .cloned()
/// .inspect(|x| println!("about to filter: {}", x))
/// .filter(|x| x % 2 == 0)
/// .inspect(|x| println!("made it through filter: {}", x))
/// .fold(0, |sum, i| sum + i);
///
/// println!("{}", sum);
/// ```
@ -1200,6 +1200,7 @@ pub trait Iterator {
/// This will print:
///
/// ```text
/// 6
/// about to filter: 1
/// about to filter: 4
/// made it through filter: 4
@ -1230,8 +1231,7 @@ pub trait Iterator {
///
/// let iter = a.into_iter();
///
/// let sum: i32 = iter.take(5)
/// .fold(0, |acc, &i| acc + i );
/// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i );
///
/// assert_eq!(sum, 6);
///
@ -1245,9 +1245,7 @@ pub trait Iterator {
/// let mut iter = a.into_iter();
///
/// // instead, we add in a .by_ref()
/// let sum: i32 = iter.by_ref()
/// .take(2)
/// .fold(0, |acc, &i| acc + i );
/// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i );
///
/// assert_eq!(sum, 3);
///
@ -1304,9 +1302,7 @@ pub trait Iterator {
///
/// let a = [1, 2, 3];
///
/// let doubled: VecDeque<i32> = a.iter()
/// .map(|&x| x * 2)
/// .collect();
/// let doubled: VecDeque<i32> = a.iter().map(|&x| x * 2).collect();
///
/// assert_eq!(2, doubled[0]);
/// assert_eq!(4, doubled[1]);
@ -1318,9 +1314,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3];
///
/// let doubled = a.iter()
/// .map(|&x| x * 2)
/// .collect::<Vec<i32>>();
/// let doubled = a.iter().map(|x| x * 2).collect::<Vec<i32>>();
///
/// assert_eq!(vec![2, 4, 6], doubled);
/// ```
@ -1331,9 +1325,7 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3];
///
/// let doubled = a.iter()
/// .map(|&x| x * 2)
/// .collect::<Vec<_>>();
/// let doubled = a.iter().map(|x| x * 2).collect::<Vec<_>>();
///
/// assert_eq!(vec![2, 4, 6], doubled);
/// ```
@ -1344,9 +1336,9 @@ pub trait Iterator {
/// let chars = ['g', 'd', 'k', 'k', 'n'];
///
/// let hello: String = chars.iter()
/// .map(|&x| x as u8)
/// .map(|x| (x + 1) as char)
/// .collect();
/// .map(|&x| x as u8)
/// .map(|x| (x + 1) as char)
/// .collect();
///
/// assert_eq!("hello", hello);
/// ```
@ -1393,8 +1385,9 @@ pub trait Iterator {
/// ```
/// let a = [1, 2, 3];
///
/// let (even, odd): (Vec<i32>, Vec<i32>) = a.into_iter()
/// .partition(|&n| n % 2 == 0);
/// let (even, odd): (Vec<i32>, Vec<i32>) = a
/// .into_iter()
/// .partition(|&n| n % 2 == 0);
///
/// assert_eq!(even, vec![2]);
/// assert_eq!(odd, vec![1, 3]);
@ -1457,8 +1450,7 @@ pub trait Iterator {
/// let a = [1, 2, 3];
///
/// // the checked sum of all of the elements of the array
/// let sum = a.iter()
/// .try_fold(0i8, |acc, &x| acc.checked_add(x));
/// let sum = a.iter().try_fold(0i8, |acc, &x| acc.checked_add(x));
///
/// assert_eq!(sum, Some(6));
/// ```
@ -1556,8 +1548,7 @@ pub trait Iterator {
/// let a = [1, 2, 3];
///
/// // the sum of all of the elements of the array
/// let sum = a.iter()
/// .fold(0, |acc, &x| acc + x);
/// let sum = a.iter().fold(0, |acc, x| acc + x);
///
/// assert_eq!(sum, 6);
/// ```

View file

@ -344,7 +344,7 @@ pub use self::sources::{Once, once};
pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::traits::{ExactSizeIterator, Sum, Product};
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
pub use self::traits::FusedIterator;
#[unstable(feature = "trusted_len", issue = "37572")]
pub use self::traits::TrustedLen;
@ -506,7 +506,7 @@ impl<I> ExactSizeIterator for Rev<I>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Rev<I>
where I: FusedIterator + DoubleEndedIterator {}
@ -589,7 +589,7 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, I, T: 'a> FusedIterator for Cloned<I>
where I: FusedIterator<Item=&'a T>, T: Clone
{}
@ -662,7 +662,7 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}
/// An iterator for stepping iterators by a custom amount.
@ -1002,7 +1002,7 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
}
// Note: *both* must be fused to handle double-ended iterators.
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A, B> FusedIterator for Chain<A, B>
where A: FusedIterator,
B: FusedIterator<Item=A::Item>,
@ -1262,7 +1262,7 @@ unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A, B> FusedIterator for Zip<A, B>
where A: FusedIterator, B: FusedIterator, {}
@ -1404,7 +1404,7 @@ impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<B, I: FusedIterator, F> FusedIterator for Map<I, F>
where F: FnMut(I::Item) -> B {}
@ -1553,7 +1553,7 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I: FusedIterator, P> FusedIterator for Filter<I, P>
where P: FnMut(&I::Item) -> bool {}
@ -1663,7 +1663,7 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<B, I: FusedIterator, F> FusedIterator for FilterMap<I, F>
where F: FnMut(I::Item) -> Option<B> {}
@ -1818,7 +1818,7 @@ unsafe impl<I> TrustedRandomAccess for Enumerate<I>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Enumerate<I> where I: FusedIterator {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -1938,7 +1938,7 @@ impl<I: Iterator> Iterator for Peekable<I> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator> ExactSizeIterator for Peekable<I> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I: FusedIterator> FusedIterator for Peekable<I> {}
impl<I: Iterator> Peekable<I> {
@ -2072,7 +2072,7 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I, P> FusedIterator for SkipWhile<I, P>
where I: FusedIterator, P: FnMut(&I::Item) -> bool {}
@ -2151,7 +2151,7 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I, P> FusedIterator for TakeWhile<I, P>
where I: FusedIterator, P: FnMut(&I::Item) -> bool {}
@ -2290,7 +2290,7 @@ impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSize
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Skip<I> where I: FusedIterator {}
/// An iterator that only iterates over the first `n` iterations of `iter`.
@ -2371,7 +2371,7 @@ impl<I> Iterator for Take<I> where I: Iterator{
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Take<I> where I: FusedIterator {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -2517,7 +2517,7 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {}
@ -2605,7 +2605,7 @@ impl<I, U> DoubleEndedIterator for Flatten<I>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I, U> FusedIterator for Flatten<I>
where I: FusedIterator, U: Iterator,
I::Item: IntoIterator<IntoIter = U, Item = U::Item> {}
@ -2765,7 +2765,7 @@ pub struct Fuse<I> {
done: bool
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> FusedIterator for Fuse<I> where I: Iterator {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -2896,7 +2896,7 @@ unsafe impl<I> TrustedRandomAccess for Fuse<I>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> Iterator for Fuse<I> where I: FusedIterator {
#[inline]
fn next(&mut self) -> Option<<I as Iterator>::Item> {
@ -2938,7 +2938,7 @@ impl<I> Iterator for Fuse<I> where I: FusedIterator {
}
}
#[unstable(feature = "fused", reason = "recently added", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I> DoubleEndedIterator for Fuse<I>
where I: DoubleEndedIterator + FusedIterator
{
@ -3082,6 +3082,6 @@ impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F>
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<I: FusedIterator, F> FusedIterator for Inspect<I, F>
where F: FnMut(&I::Item) {}

View file

@ -295,7 +295,7 @@ impl<A: Step> DoubleEndedIterator for ops::Range<A> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::Range<A> {}
#[stable(feature = "rust1", since = "1.0.0")]
@ -322,7 +322,7 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -463,5 +463,5 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}

View file

@ -41,7 +41,7 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> {
fn next_back(&mut self) -> Option<A> { Some(self.element.clone()) }
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A: Clone> FusedIterator for Repeat<A> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -135,7 +135,7 @@ impl<A, F: FnMut() -> A> DoubleEndedIterator for RepeatWith<F> {
fn next_back(&mut self) -> Option<A> { self.next() }
}
#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "iterator_repeat_with", issue = "48169")]
impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -259,7 +259,7 @@ impl<T> ExactSizeIterator for Empty<T> {
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T> TrustedLen for Empty<T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for Empty<T> {}
// not #[derive] because that adds a Clone bound on T,
@ -340,7 +340,7 @@ impl<T> ExactSizeIterator for Once<T> {
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<T> TrustedLen for Once<T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for Once<T> {}
/// Creates an iterator that yields an element exactly once.

View file

@ -959,10 +959,10 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E>
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [`Iterator::fuse`]: ../../std/iter/trait.Iterator.html#method.fuse
/// [`Fuse`]: ../../std/iter/struct.Fuse.html
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
pub trait FusedIterator: Iterator {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {}
/// An iterator that reports an accurate length using size_hint.

View file

@ -321,6 +321,33 @@ $EndFeature, "
(self as $UnsignedT).swap_bytes() as Self
}
/// Reverses the bit pattern of the integer.
///
/// # Examples
///
/// Please note that this example is shared between integer types.
/// Which explains why `i16` is used here.
///
/// Basic usage:
///
/// ```
/// #![feature(reverse_bits)]
///
/// let n: i16 = 0b0000000_01010101;
/// assert_eq!(n, 85);
///
/// let m = n.reverse_bits();
///
/// assert_eq!(m as u16, 0b10101010_00000000);
/// assert_eq!(m, -22016);
/// ```
#[unstable(feature = "reverse_bits", issue = "48763")]
#[cfg(not(stage0))]
#[inline]
pub fn reverse_bits(self) -> Self {
(self as $UnsignedT).reverse_bits() as Self
}
doc_comment! {
concat!("Converts an integer from big endian to the target's endianness.
@ -1773,6 +1800,33 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
unsafe { intrinsics::bswap(self as $ActualT) as Self }
}
/// Reverses the bit pattern of the integer.
///
/// # Examples
///
/// Basic usage:
///
/// Please note that this example is shared between integer types.
/// Which explains why `u16` is used here.
///
/// ```
/// #![feature(reverse_bits)]
///
/// let n: u16 = 0b0000000_01010101;
/// assert_eq!(n, 85);
///
/// let m = n.reverse_bits();
///
/// assert_eq!(m, 0b10101010_00000000);
/// assert_eq!(m, 43520);
/// ```
#[unstable(feature = "reverse_bits", issue = "48763")]
#[cfg(not(stage0))]
#[inline]
pub fn reverse_bits(self) -> Self {
unsafe { intrinsics::bitreverse(self as $ActualT) as Self }
}
doc_comment! {
concat!("Converts an integer from big endian to the target's endianness.

View file

@ -233,11 +233,11 @@ impl<T> Option<T> {
/// [`usize`]: ../../std/primitive.usize.html
///
/// ```
/// let num_as_str: Option<String> = Some("10".to_string());
/// let text: Option<String> = Some("Hello, world!".to_string());
/// // First, cast `Option<String>` to `Option<&String>` with `as_ref`,
/// // then consume *that* with `map`, leaving `num_as_str` on the stack.
/// let num_as_int: Option<usize> = num_as_str.as_ref().map(|n| n.len());
/// println!("still can print num_as_str: {:?}", num_as_str);
/// // then consume *that* with `map`, leaving `text` on the stack.
/// let text_length: Option<usize> = text.as_ref().map(|s| s.len());
/// println!("still can print text: {:?}", text);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -1051,7 +1051,7 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, A> FusedIterator for Iter<'a, A> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -1096,7 +1096,7 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, A> FusedIterator for IterMut<'a, A> {}
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {}
@ -1133,7 +1133,7 @@ impl<A> DoubleEndedIterator for IntoIter<A> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> ExactSizeIterator for IntoIter<A> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<A> FusedIterator for IntoIter<A> {}
#[unstable(feature = "trusted_len", issue = "37572")]

View file

@ -1038,7 +1038,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -1082,7 +1082,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -1125,7 +1125,7 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IntoIter<T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<T> FusedIterator for IntoIter<T> {}
#[unstable(feature = "trusted_len", issue = "37572")]

View file

@ -1455,7 +1455,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -1583,7 +1583,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -1731,7 +1731,7 @@ impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {}
/// An iterator over the subslices of the vector which are separated
@ -1829,7 +1829,7 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
/// An iterator over subslices separated by elements that match a predicate
@ -1886,7 +1886,6 @@ impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
}
}
//#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
@ -1945,7 +1944,6 @@ impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
}
}
//#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "slice_rsplit", issue = "41020")]
impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
@ -2082,7 +2080,7 @@ macro_rules! forward_iterator {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P>
where P: FnMut(&T) -> bool {}
}
@ -2188,7 +2186,7 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Windows<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Windows<'a, T> {}
#[doc(hidden)]
@ -2307,7 +2305,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Chunks<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for Chunks<'a, T> {}
#[doc(hidden)]
@ -2423,7 +2421,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, T> FusedIterator for ChunksMut<'a, T> {}
#[doc(hidden)]
@ -2533,7 +2531,7 @@ impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "exact_chunks", issue = "47115")]
impl<'a, T> FusedIterator for ExactChunks<'a, T> {}
#[doc(hidden)]
@ -2630,7 +2628,7 @@ impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[unstable(feature = "exact_chunks", issue = "47115")]
impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {}
#[doc(hidden)]

View file

@ -609,7 +609,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for Chars<'a> {}
impl<'a> Chars<'a> {
@ -702,7 +702,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for CharIndices<'a> {}
impl<'a> CharIndices<'a> {
@ -817,7 +817,7 @@ impl<'a> ExactSizeIterator for Bytes<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for Bytes<'a> {}
#[unstable(feature = "trusted_len", issue = "37572")]
@ -977,10 +977,10 @@ macro_rules! generate_pattern_iterators {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a, P: Pattern<'a>> FusedIterator for $reverse_iterator<'a, P>
where P::Searcher: ReverseSearcher<'a> {}
@ -1337,7 +1337,7 @@ impl<'a> DoubleEndedIterator for Lines<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
impl<'a> FusedIterator for Lines<'a> {}
/// Created with the method [`lines_any`].
@ -1403,7 +1403,7 @@ impl<'a> DoubleEndedIterator for LinesAny<'a> {
}
}
#[unstable(feature = "fused", issue = "35602")]
#[stable(feature = "fused", since = "1.26.0")]
#[allow(deprecated)]
impl<'a> FusedIterator for LinesAny<'a> {}

View file

@ -46,6 +46,7 @@
#![feature(try_trait)]
#![feature(exact_chunks)]
#![feature(atomic_nand)]
#![feature(reverse_bits)]
extern crate core;
extern crate test;

View file

@ -97,6 +97,17 @@ mod tests {
assert_eq!(_1.swap_bytes(), _1);
}
#[test]
fn test_reverse_bits() {
assert_eq!(A.reverse_bits().reverse_bits(), A);
assert_eq!(B.reverse_bits().reverse_bits(), B);
assert_eq!(C.reverse_bits().reverse_bits(), C);
// Swapping these should make no difference
assert_eq!(_0.reverse_bits(), _0);
assert_eq!(_1.reverse_bits(), _1);
}
#[test]
fn test_le() {
assert_eq!($T::from_le(A.to_le()), A);

View file

@ -436,6 +436,9 @@ impl DepKind {
}
define_dep_nodes!( <'tcx>
// We use this for most things when incr. comp. is turned off.
[] Null,
// Represents the `Krate` as a whole (the `hir::Krate` value) (as
// distinct from the krate module). This is basically a hash of
// the entire krate, so if you read from `Krate` (e.g., by calling
@ -553,7 +556,7 @@ define_dep_nodes!( <'tcx>
[] RvaluePromotableMap(DefId),
[] ImplParent(DefId),
[] TraitOfItem(DefId),
[] IsExportedSymbol(DefId),
[] IsReachableNonGeneric(DefId),
[] IsMirAvailable(DefId),
[] ItemAttrs(DefId),
[] FnArgNames(DefId),
@ -571,7 +574,7 @@ define_dep_nodes!( <'tcx>
[] GetPanicStrategy(CrateNum),
[] IsNoBuiltins(CrateNum),
[] ImplDefaultness(DefId),
[] ExportedSymbolIds(CrateNum),
[] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] DeriveRegistrarFn(CrateNum),
@ -605,8 +608,8 @@ define_dep_nodes!( <'tcx>
[input] MissingExternCrateItem(CrateNum),
[input] UsedCrateSource(CrateNum),
[input] PostorderCnums,
[input] HasCloneClosures(CrateNum),
[input] HasCopyClosures(CrateNum),
[] HasCloneClosures(CrateNum),
[] HasCopyClosures(CrateNum),
// This query is not expected to have inputs -- as a result, it's
// not a good candidate for "replay" because it's essentially a
@ -630,8 +633,6 @@ define_dep_nodes!( <'tcx>
[] CompileCodegenUnit(InternedString),
[input] OutputFilenames,
[anon] NormalizeTy,
// We use this for most things when incr. comp. is turned off.
[] Null,
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
@ -642,6 +643,7 @@ define_dep_nodes!( <'tcx>
[] GetSymbolExportLevel(DefId),
[input] Features,
);
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {

View file

@ -550,7 +550,7 @@ impl<'a> LoweringContext<'a> {
{
assert!(!self.is_collecting_in_band_lifetimes);
assert!(self.lifetimes_to_define.is_empty());
self.is_collecting_in_band_lifetimes = self.sess.features.borrow().in_band_lifetimes;
self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes;
assert!(self.in_band_ty_params.is_empty());
@ -964,7 +964,7 @@ impl<'a> LoweringContext<'a> {
let span = t.span;
match itctx {
ImplTraitContext::Existential => {
let has_feature = self.sess.features.borrow().conservative_impl_trait;
let has_feature = self.sess.features_untracked().conservative_impl_trait;
if !t.span.allows_unstable() && !has_feature {
emit_feature_err(&self.sess.parse_sess, "conservative_impl_trait",
t.span, GateIssue::Language,
@ -988,7 +988,7 @@ impl<'a> LoweringContext<'a> {
}, lifetimes)
},
ImplTraitContext::Universal(def_id) => {
let has_feature = self.sess.features.borrow().universal_impl_trait;
let has_feature = self.sess.features_untracked().universal_impl_trait;
if !t.span.allows_unstable() && !has_feature {
emit_feature_err(&self.sess.parse_sess, "universal_impl_trait",
t.span, GateIssue::Language,
@ -3713,7 +3713,7 @@ impl<'a> LoweringContext<'a> {
}
fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) {
if self.sess.features.borrow().dyn_trait {
if self.sess.features_untracked().dyn_trait {
self.sess.buffer_lint_with_diagnostic(
builtin::BARE_TRAIT_OBJECT, id, span,
"trait objects without an explicit `dyn` are deprecated",

View file

@ -2208,13 +2208,8 @@ impl<'a> State<'a> {
if self.next_comment().is_none() {
self.s.hardbreak()?;
}
loop {
match self.next_comment() {
Some(ref cmnt) => {
self.print_comment(cmnt)?;
}
_ => break,
}
while let Some(ref cmnt) = self.next_comment() {
self.print_comment(cmnt)?
}
Ok(())
}

View file

@ -17,6 +17,7 @@ use std::hash as std_hash;
use std::mem;
use syntax::ast;
use syntax::feature_gate;
use syntax::parse::token;
use syntax::symbol::InternedString;
use syntax::tokenstream;
@ -460,3 +461,21 @@ fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar,
(pos.0 - filemap_start.0, width as u32)
}
impl<'gcx> HashStable<StableHashingContext<'gcx>> for feature_gate::Features {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
// Unfortunately we cannot exhaustively list fields here, since the
// struct is macro generated.
self.declared_stable_lang_features.hash_stable(hcx, hasher);
self.declared_lib_features.hash_stable(hcx, hasher);
self.walk_feature_fields(|feature_name, value| {
feature_name.hash_stable(hcx, hasher);
value.hash_stable(hcx, hasher);
});
}
}

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,6 @@ use ich;
use ty::{self, TyCtxt};
use session::{Session, CrateDisambiguator};
use session::search_paths::PathKind;
use util::nodemap::NodeSet;
use std::any::Any;
use std::collections::BTreeMap;
@ -258,8 +257,7 @@ pub trait CrateStore {
// utility functions
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet)
link_meta: &LinkMeta)
-> EncodedMetadata;
fn metadata_encoding_version(&self) -> &[u8];
}
@ -342,8 +340,7 @@ impl CrateStore for DummyCrateStore {
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet)
link_meta: &LinkMeta)
-> EncodedMetadata {
bug!("encode_metadata")
}

View file

@ -8,12 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use hir::def_id::{DefId, LOCAL_CRATE};
use std::cmp;
use ty;
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
/// kind of crate, including cdylibs which export very few things.
/// `Rust` will only be exported if the crate produced is a Rust
/// dylib.
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum SymbolExportLevel {
C,
Rust,
@ -34,3 +38,58 @@ impl SymbolExportLevel {
}
}
}
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum ExportedSymbol {
NonGeneric(DefId),
NoDefId(ty::SymbolName),
}
impl ExportedSymbol {
pub fn symbol_name(&self, tcx: ty::TyCtxt) -> ty::SymbolName {
match *self {
ExportedSymbol::NonGeneric(def_id) => {
tcx.symbol_name(ty::Instance::mono(tcx, def_id))
}
ExportedSymbol::NoDefId(symbol_name) => {
symbol_name
}
}
}
pub fn compare_stable(&self, tcx: ty::TyCtxt, other: &ExportedSymbol) -> cmp::Ordering {
match *self {
ExportedSymbol::NonGeneric(self_def_id) => {
match *other {
ExportedSymbol::NonGeneric(other_def_id) => {
tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
}
ExportedSymbol::NoDefId(_) => {
cmp::Ordering::Less
}
}
}
ExportedSymbol::NoDefId(self_symbol_name) => {
match *other {
ExportedSymbol::NonGeneric(_) => {
cmp::Ordering::Greater
}
ExportedSymbol::NoDefId(ref other_symbol_name) => {
self_symbol_name.cmp(other_symbol_name)
}
}
}
}
}
}
impl_stable_hash_for!(enum self::ExportedSymbol {
NonGeneric(def_id),
NoDefId(symbol_name)
});
pub fn metadata_symbol_name(tcx: ty::TyCtxt) -> String {
format!("rust_metadata_{}_{}",
tcx.original_crate_name(LOCAL_CRATE),
tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex())
}

View file

@ -206,11 +206,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// Step 2: Mark all symbols that the symbols on the worklist touch.
fn propagate(&mut self) {
let mut scanned = FxHashSet();
loop {
let search_item = match self.worklist.pop() {
Some(item) => item,
None => break,
};
while let Some(search_item) = self.worklist.pop() {
if !scanned.insert(search_item) {
continue
}

View file

@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
item_sp: Span, kind: AnnotationKind, visit_children: F)
where F: FnOnce(&mut Self)
{
if self.tcx.sess.features.borrow().staged_api {
if self.tcx.features().staged_api {
// This crate explicitly wants staged API.
debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) {
@ -398,7 +398,7 @@ impl<'a, 'tcx> Index<'tcx> {
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
let is_staged_api =
tcx.sess.opts.debugging_opts.force_unstable_if_unmarked ||
tcx.sess.features.borrow().staged_api;
tcx.features().staged_api;
let mut staged_api = FxHashMap();
staged_api.insert(LOCAL_CRATE, is_staged_api);
let mut index = Index {
@ -408,7 +408,7 @@ impl<'a, 'tcx> Index<'tcx> {
active_features: FxHashSet(),
};
let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
let ref active_lib_features = tcx.features().declared_lib_features;
// Put the active features into a map for quick lookup
index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect();
@ -677,7 +677,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
// There's no good place to insert stability check for non-Copy unions,
// so semi-randomly perform it here in stability.rs
hir::ItemUnion(..) if !self.tcx.sess.features.borrow().untagged_unions => {
hir::ItemUnion(..) if !self.tcx.features().untagged_unions => {
let def_id = self.tcx.hir.local_def_id(item.id);
let adt_def = self.tcx.adt_def(def_id);
let ty = self.tcx.type_of(def_id);
@ -721,8 +721,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// were expected to be library features), and the list of features used from
/// libraries, identify activated features that don't exist and error about them.
pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let sess = &tcx.sess;
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
if tcx.stability().staged_api[&LOCAL_CRATE] {
@ -736,12 +734,12 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
krate.visit_all_item_likes(&mut missing.as_deep_visitor());
}
let ref declared_lib_features = sess.features.borrow().declared_lib_features;
let ref declared_lib_features = tcx.features().declared_lib_features;
let mut remaining_lib_features: FxHashMap<Symbol, Span>
= declared_lib_features.clone().into_iter().collect();
remaining_lib_features.remove(&Symbol::intern("proc_macro"));
for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features {
for &(ref stable_lang_feature, span) in &tcx.features().declared_stable_lang_features {
let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str())
.expect("unexpectedly couldn't find version feature was stabilized");
tcx.lint_node(lint::builtin::STABLE_FEATURES,

View file

@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics;
use middle::allocator::AllocatorKind;
use middle::dependency_format;
use session::search_paths::PathKind;
use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch};
use session::config::{DebugInfoLevel, OutputType, Epoch};
use ty::tls;
use util::nodemap::{FxHashMap, FxHashSet};
use util::common::{duration_to_secs_str, ErrorReported};
@ -93,7 +93,8 @@ pub struct Session {
/// multiple crates with the same name to coexist. See the
/// trans::back::symbol_names module for more information.
pub crate_disambiguator: RefCell<Option<CrateDisambiguator>>,
pub features: RefCell<feature_gate::Features>,
features: RefCell<Option<feature_gate::Features>>,
/// The maximum recursion limit for potentially infinitely recursive
/// operations such as auto-dereference and monomorphization.
@ -194,6 +195,7 @@ impl Session {
None => bug!("accessing disambiguator before initialization"),
}
}
pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
sp: S,
msg: &str)
@ -456,16 +458,22 @@ impl Session {
self.opts.debugging_opts.print_llvm_passes
}
/// If true, we should use NLL-style region checking instead of
/// lexical style.
pub fn nll(&self) -> bool {
self.features.borrow().nll || self.opts.debugging_opts.nll
/// Get the features enabled for the current compilation session.
/// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents
/// dependency tracking. Use tcx.features() instead.
#[inline]
pub fn features_untracked(&self) -> cell::Ref<feature_gate::Features> {
let features = self.features.borrow();
if features.is_none() {
bug!("Access to Session::features before it is initialized");
}
cell::Ref::map(features, |r| r.as_ref().unwrap())
}
/// If true, we should use the MIR-based borrowck (we may *also* use
/// the AST-based borrowck).
pub fn use_mir(&self) -> bool {
self.borrowck_mode().use_mir()
pub fn init_features(&self, features: feature_gate::Features) {
*(self.features.borrow_mut()) = Some(features);
}
/// If true, we should gather causal information during NLL
@ -475,42 +483,6 @@ impl Session {
self.opts.debugging_opts.nll_dump_cause
}
/// If true, we should enable two-phase borrows checks. This is
/// done with either `-Ztwo-phase-borrows` or with
/// `#![feature(nll)]`.
pub fn two_phase_borrows(&self) -> bool {
self.features.borrow().nll || self.opts.debugging_opts.two_phase_borrows
}
/// What mode(s) of borrowck should we run? AST? MIR? both?
/// (Also considers the `#![feature(nll)]` setting.)
pub fn borrowck_mode(&self) -> BorrowckMode {
match self.opts.borrowck_mode {
mode @ BorrowckMode::Mir |
mode @ BorrowckMode::Compare => mode,
mode @ BorrowckMode::Ast => {
if self.nll() {
BorrowckMode::Mir
} else {
mode
}
}
}
}
/// Should we emit EndRegion MIR statements? These are consumed by
/// MIR borrowck, but not when NLL is used. They are also consumed
/// by the validation stuff.
pub fn emit_end_regions(&self) -> bool {
// FIXME(#46875) -- we should not emit end regions when NLL is enabled,
// but for now we can't stop doing so because it causes false positives
self.opts.debugging_opts.emit_end_regions ||
self.opts.debugging_opts.mir_emit_validate > 0 ||
self.use_mir()
}
/// Calculates the flavor of LTO to use for this compilation.
pub fn lto(&self) -> config::Lto {
// If our target has codegen requirements ignore the command line
@ -1029,7 +1001,7 @@ pub fn build_session_(sopts: config::Options,
crate_types: RefCell::new(Vec::new()),
dependency_formats: RefCell::new(FxHashMap()),
crate_disambiguator: RefCell::new(None),
features: RefCell::new(feature_gate::Features::new()),
features: RefCell::new(None),
recursion_limit: Cell::new(64),
type_length_limit: Cell::new(1048576),
next_node_id: Cell::new(NodeId::new(1)),

View file

@ -164,7 +164,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// The feature gate should prevent introducing new specializations, but not
// taking advantage of upstream ones.
if !tcx.sess.features.borrow().specialization &&
if !tcx.features().specialization &&
(impl1_def_id.is_local() || impl2_def_id.is_local()) {
return false;
}

View file

@ -14,7 +14,7 @@ use dep_graph::DepGraph;
use dep_graph::{DepNode, DepConstructor};
use errors::DiagnosticBuilder;
use session::Session;
use session::config::OutputFilenames;
use session::config::{BorrowckMode, OutputFilenames};
use middle;
use hir::{TraitCandidate, HirId, ItemLocalId};
use hir::def::{Def, Export};
@ -46,7 +46,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout};
use ty::maps;
use ty::steal::Steal;
use ty::BindingMode;
use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
use util::nodemap::{FxHashMap, FxHashSet};
use rustc_data_structures::accumulate_vec::AccumulateVec;
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
@ -71,6 +71,7 @@ use syntax::abi;
use syntax::ast::{self, Name, NodeId};
use syntax::attr;
use syntax::codemap::MultiSpan;
use syntax::feature_gate;
use syntax::symbol::{Symbol, keywords};
use syntax_pos::Span;
@ -1255,6 +1256,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.all_crate_nums(LOCAL_CRATE)
}
pub fn features(self) -> Lrc<feature_gate::Features> {
self.features_query(LOCAL_CRATE)
}
pub fn def_key(self, id: DefId) -> hir_map::DefKey {
if id.is_local() {
self.hir.def_key(id)
@ -1362,13 +1367,60 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder)
}
/// If true, we should use NLL-style region checking instead of
/// lexical style.
pub fn nll(self) -> bool {
self.features().nll || self.sess.opts.debugging_opts.nll
}
/// If true, we should use the MIR-based borrowck (we may *also* use
/// the AST-based borrowck).
pub fn use_mir(self) -> bool {
self.borrowck_mode().use_mir()
}
/// If true, we should enable two-phase borrows checks. This is
/// done with either `-Ztwo-phase-borrows` or with
/// `#![feature(nll)]`.
pub fn two_phase_borrows(self) -> bool {
self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows
}
/// What mode(s) of borrowck should we run? AST? MIR? both?
/// (Also considers the `#![feature(nll)]` setting.)
pub fn borrowck_mode(&self) -> BorrowckMode {
match self.sess.opts.borrowck_mode {
mode @ BorrowckMode::Mir |
mode @ BorrowckMode::Compare => mode,
mode @ BorrowckMode::Ast => {
if self.nll() {
BorrowckMode::Mir
} else {
mode
}
}
}
}
/// Should we emit EndRegion MIR statements? These are consumed by
/// MIR borrowck, but not when NLL is used. They are also consumed
/// by the validation stuff.
pub fn emit_end_regions(self) -> bool {
// FIXME(#46875) -- we should not emit end regions when NLL is enabled,
// but for now we can't stop doing so because it causes false positives
self.sess.opts.debugging_opts.emit_end_regions ||
self.sess.opts.debugging_opts.mir_emit_validate > 0 ||
self.use_mir()
}
}
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
pub fn encode_metadata(self, link_meta: &LinkMeta, reachable: &NodeSet)
pub fn encode_metadata(self, link_meta: &LinkMeta)
-> EncodedMetadata
{
self.cstore.encode_metadata(self, link_meta, reachable)
self.cstore.encode_metadata(self, link_meta)
}
}
@ -2020,7 +2072,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
pub fn mk_diverging_default(self) -> Ty<'tcx> {
if self.sess.features.borrow().never_type {
if self.features().never_type {
self.types.never
} else {
self.intern_tup(&[], true)
@ -2395,13 +2447,25 @@ pub fn provide(providers: &mut ty::maps::Providers) {
};
providers.has_copy_closures = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
tcx.sess.features.borrow().copy_closures
tcx.features().copy_closures
};
providers.has_clone_closures = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
tcx.sess.features.borrow().clone_closures
tcx.features().clone_closures
};
providers.fully_normalize_monormophic_ty = |tcx, ty| {
tcx.fully_normalize_associated_types_in(&ty)
};
providers.features_query = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(tcx.sess.features_untracked().clone())
};
providers.is_panic_runtime = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime")
};
providers.is_compiler_builtins = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins")
};
}

View file

@ -212,9 +212,9 @@ impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> {
}
}
impl<'tcx> QueryDescription<'tcx> for queries::is_exported_symbol<'tcx> {
impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> {
fn describe(_: TyCtxt, _: DefId) -> String {
bug!("is_exported_symbol")
bug!("is_reachable_non_generic")
}
}
@ -383,7 +383,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> {
}
}
impl<'tcx> QueryDescription<'tcx> for queries::exported_symbol_ids<'tcx> {
impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("looking up the exported symbols of a crate")
}
@ -593,6 +593,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::fully_normalize_monormophic_ty<'t
}
}
impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("looking up enabled feature gates")
}
}
impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> {
#[inline]
fn cache_on_disk(def_id: Self::Key) -> bool {

View file

@ -26,7 +26,7 @@ use middle::region;
use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault};
use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem};
use middle::exported_symbols::SymbolExportLevel;
use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
use mir::mono::{CodegenUnit, Stats};
use mir;
use session::{CompileResult, CrateDisambiguator};
@ -52,6 +52,7 @@ use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::symbol::InternedString;
use syntax::attr;
use syntax::ast;
use syntax::feature_gate;
use syntax::symbol::Symbol;
#[macro_use]
@ -237,7 +238,6 @@ define_maps! { <'tcx>
[] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
[] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
[] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
[] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
[] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
[] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>,
@ -289,7 +289,23 @@ define_maps! { <'tcx>
[] fn lint_levels: lint_levels_node(CrateNum) -> Lrc<lint::LintLevelMap>,
[] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
[] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Lrc<DefIdSet>,
// The DefIds of all non-generic functions and statics in the given crate
// that can be reached from outside the crate.
//
// We expect this items to be available for being linked to.
//
// This query can also be called for LOCAL_CRATE. In this case it will
// compute which items will be reachable to other crates, taking into account
// the kind of crate that is currently compiled. Crates with only a
// C interface have fewer reachable things.
//
// Does not include external symbols that don't have a corresponding DefId,
// like the compiler-generated `main` function and so on.
[] fn reachable_non_generics: ReachableNonGenerics(CrateNum) -> Lrc<DefIdSet>,
[] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool,
[] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
[] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
@ -342,7 +358,7 @@ define_maps! { <'tcx>
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
[] fn exported_symbols: ExportedSymbols(CrateNum)
-> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
-> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
[] fn collect_and_partition_translation_items:
collect_and_partition_translation_items_node(CrateNum)
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
@ -374,12 +390,19 @@ define_maps! { <'tcx>
// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
[] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>)
-> usize,
[] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
}
//////////////////////////////////////////////////////////////////////
// These functions are little shims used to find the dep-node for a
// given query when there is not a *direct* mapping:
fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::Features
}
fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
DepConstructor::EraseRegionsTy { ty }
}

View file

@ -851,7 +851,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
DepKind::ImplParent => { force!(impl_parent, def_id!()); }
DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); }
DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
@ -868,7 +868,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
DepKind::ExportedSymbolIds => { force!(exported_symbol_ids, krate!()); }
DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
DepKind::DeriveRegistrarFn => { force!(derive_registrar_fn, krate!()); }
@ -936,6 +936,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
}
true

View file

@ -2335,7 +2335,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns true if the impls are the same polarity and are implementing
/// a trait which contains no items
pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
if !self.sess.features.borrow().overlapping_marker_traits {
if !self.features().overlapping_marker_traits {
return false;
}
let trait1_is_empty = self.impl_trait_ref(def_id1)
@ -2806,7 +2806,7 @@ impl<'tcx> DtorckConstraint<'tcx> {
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub struct SymbolName {
// FIXME: we don't rely on interning or equality here - better have
// this be a `&'tcx str`.
@ -2817,6 +2817,14 @@ impl_stable_hash_for!(struct self::SymbolName {
name
});
impl SymbolName {
pub fn new(name: &str) -> SymbolName {
SymbolName {
name: Symbol::intern(name).as_str()
}
}
}
impl Deref for SymbolName {
type Target = str;
@ -2828,3 +2836,9 @@ impl fmt::Display for SymbolName {
fmt::Display::fmt(&self.name, fmt)
}
}
impl fmt::Debug for SymbolName {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.name, fmt)
}
}

View file

@ -276,7 +276,7 @@ impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
o: Origin)
-> DiagnosticBuilder<'a>
{
if !o.should_emit_errors(self.tcx.sess.borrowck_mode()) {
if !o.should_emit_errors(self.tcx.borrowck_mode()) {
self.tcx.sess.diagnostic().cancel(&mut diag);
}
diag

View file

@ -201,7 +201,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
}
fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
if self.tcx.sess.features.borrow().never_type {
if self.tcx.features().never_type {
self.tcx.is_ty_uninhabited_from(self.module, ty)
} else {
false
@ -227,7 +227,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
substs: &'tcx ty::subst::Substs<'tcx>)
-> bool
{
if self.tcx.sess.features.borrow().never_type {
if self.tcx.features().never_type {
self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
} else {
false

View file

@ -212,7 +212,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
let pat_ty = self.tables.node_id_to_type(scrut.hir_id);
let module = self.tcx.hir.get_module_parent(scrut.id);
if inlined_arms.is_empty() {
let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
let scrutinee_is_uninhabited = if self.tcx.features().never_type {
self.tcx.is_ty_uninhabited_from(module, pat_ty)
} else {
self.conservative_is_uninhabited(pat_ty)

View file

@ -398,7 +398,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
}).collect::<Result<Vec<_>, _>>()?))))
}
hir::ExprIndex(ref arr, ref idx) => {
if !tcx.sess.features.borrow().const_indexing {
if !tcx.features().const_indexing {
signal!(e, IndexOpFeatureGated);
}
let arr = cx.eval(arr)?;

View file

@ -415,13 +415,7 @@ impl<O: ForestObligation> ObligationForest<O> {
}
}
loop {
// non-standard `while let` to bypass #6393
let i = match error_stack.pop() {
Some(i) => i,
None => break
};
while let Some(i) = error_stack.pop() {
let node = &self.nodes[i];
match node.state.get() {

View file

@ -650,7 +650,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test);
// these need to be set "early" so that expansion sees `quote` if enabled.
*sess.features.borrow_mut() = features;
sess.init_features(features);
*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
@ -699,7 +699,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
let mut registry = registry.unwrap_or(Registry::new(sess, krate.span));
time(time_passes, "plugin registration", || {
if sess.features.borrow().rustc_diagnostic_macros {
if sess.features_untracked().rustc_diagnostic_macros {
registry.register_macro("__diagnostic_used",
diagnostics::plugin::expand_diagnostic_used);
registry.register_macro("__register_diagnostic",
@ -749,7 +749,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
crate_loader,
&resolver_arenas);
resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives;
syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote);
syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote);
krate = time(time_passes, "expansion", || {
// Windows dlls do not have rpaths, so they don't know how to find their
@ -780,7 +780,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
.filter(|p| env::join_paths(iter::once(p)).is_ok()))
.unwrap());
}
let features = sess.features.borrow();
let features = sess.features_untracked();
let cfg = syntax::ext::expand::ExpansionConfig {
features: Some(&features),
recursion_limit: sess.recursion_limit.get(),
@ -819,7 +819,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
sess.opts.test,
krate,
sess.diagnostic(),
&sess.features.borrow())
&sess.features_untracked())
});
// If we're actually rustdoc then there's no need to actually compile
@ -886,7 +886,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
sess.track_errors(|| {
syntax::feature_gate::check_crate(&krate,
&sess.parse_sess,
&sess.features.borrow(),
&sess.features_untracked(),
&attributes,
sess.opts.unstable_features);
})

View file

@ -69,7 +69,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
// if the `rustc_attrs` feature is not enabled, then the
// attributes we are interested in cannot be present anyway, so
// skip the walk.
if !tcx.sess.features.borrow().rustc_attrs {
if !tcx.features().rustc_attrs {
return;
}

View file

@ -219,7 +219,7 @@ impl Assertion {
pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
// can't add `#[rustc_dirty]` etc without opting in to this feature
if !tcx.sess.features.borrow().rustc_attrs {
if !tcx.features().rustc_attrs {
return;
}

View file

@ -1356,7 +1356,7 @@ impl UnreachablePub {
// visibility is token at start of declaration (can be macro
// variable rather than literal `pub`)
let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' ');
let replacement = if cx.tcx.sess.features.borrow().crate_visibility_modifier {
let replacement = if cx.tcx.features().crate_visibility_modifier {
"crate"
} else {
"pub(crate)"

View file

@ -150,11 +150,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
// Detect literal value out of range [min, max] inclusive
// avoiding use of -min to prevent overflow/panic
if (negative && v > max + 1) ||
(!negative && v > max) {
cx.span_lint(OVERFLOWING_LITERALS,
e.span,
&format!("literal out of range for {:?}", t));
if (negative && v > max + 1) || (!negative && v > max) {
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
report_bin_hex_error(
cx,
e,
ty::TyInt(t),
repr_str,
v,
negative,
);
return;
}
cx.span_lint(
OVERFLOWING_LITERALS,
e.span,
&format!("literal out of range for {:?}", t),
);
return;
}
}
@ -182,7 +194,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
let mut err = cx.struct_span_lint(
OVERFLOWING_LITERALS,
parent_expr.span,
"only u8 can be casted into char");
"only u8 can be cast into char");
err.span_suggestion(parent_expr.span,
&"use a char literal instead",
format!("'\\u{{{:X}}}'", lit_val));
@ -191,9 +203,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
}
}
}
cx.span_lint(OVERFLOWING_LITERALS,
e.span,
&format!("literal out of range for {:?}", t));
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
report_bin_hex_error(
cx,
e,
ty::TyUint(t),
repr_str,
lit_val,
false,
);
return;
}
cx.span_lint(
OVERFLOWING_LITERALS,
e.span,
&format!("literal out of range for {:?}", t),
);
}
}
ty::TyFloat(t) => {
@ -338,6 +363,120 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
_ => false,
}
}
fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option<String> {
let src = cx.sess().codemap().span_to_snippet(lit.span).ok()?;
let firstch = src.chars().next()?;
if firstch == '0' {
match src.chars().nth(1) {
Some('x') | Some('b') => return Some(src),
_ => return None,
}
}
None
}
// This function finds the next fitting type and generates a suggestion string.
// It searches for fitting types in the following way (`X < Y`):
// - `iX`: if literal fits in `uX` => `uX`, else => `iY`
// - `-iX` => `iY`
// - `uX` => `uY`
//
// No suggestion for: `isize`, `usize`.
fn get_type_suggestion<'a>(
t: &ty::TypeVariants,
val: u128,
negative: bool,
) -> Option<String> {
use syntax::ast::IntTy::*;
use syntax::ast::UintTy::*;
macro_rules! find_fit {
($ty:expr, $val:expr, $negative:expr,
$($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
{
let _neg = if negative { 1 } else { 0 };
match $ty {
$($type => {
$(if !negative && val <= uint_ty_range($utypes).1 {
return Some(format!("{:?}", $utypes))
})*
$(if val <= int_ty_range($itypes).1 as u128 + _neg {
return Some(format!("{:?}", $itypes))
})*
None
},)*
_ => None
}
}
}
}
match t {
&ty::TyInt(i) => find_fit!(i, val, negative,
I8 => [U8] => [I16, I32, I64, I128],
I16 => [U16] => [I32, I64, I128],
I32 => [U32] => [I64, I128],
I64 => [U64] => [I128],
I128 => [U128] => []),
&ty::TyUint(u) => find_fit!(u, val, negative,
U8 => [U8, U16, U32, U64, U128] => [],
U16 => [U16, U32, U64, U128] => [],
U32 => [U32, U64, U128] => [],
U64 => [U64, U128] => [],
U128 => [U128] => []),
_ => None,
}
}
fn report_bin_hex_error(
cx: &LateContext,
expr: &hir::Expr,
ty: ty::TypeVariants,
repr_str: String,
val: u128,
negative: bool,
) {
let (t, actually) = match ty {
ty::TyInt(t) => {
let bits = int_ty_bits(t, cx.sess().target.isize_ty);
let actually = (val << (128 - bits)) as i128 >> (128 - bits);
(format!("{:?}", t), actually.to_string())
}
ty::TyUint(t) => {
let bits = uint_ty_bits(t, cx.sess().target.usize_ty);
let actually = (val << (128 - bits)) >> (128 - bits);
(format!("{:?}", t), actually.to_string())
}
_ => bug!(),
};
let mut err = cx.struct_span_lint(
OVERFLOWING_LITERALS,
expr.span,
&format!("literal out of range for {}", t),
);
err.note(&format!(
"the literal `{}` (decimal `{}`) does not fit into \
an `{}` and will become `{}{}`",
repr_str, val, t, actually, t
));
if let Some(sugg_ty) =
get_type_suggestion(&cx.tables.node_id_to_type(expr.hir_id).sty, val, negative)
{
if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
let (sans_suffix, _) = repr_str.split_at(pos);
err.span_suggestion(
expr.span,
&format!("consider using `{}` instead", sugg_ty),
format!("{}{}", sans_suffix, sugg_ty),
);
} else {
err.help(&format!("consider using `{}` instead", sugg_ty));
}
}
err.emit();
}
}
}

View file

@ -72,7 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
let mut fn_warned = false;
let mut op_warned = false;
if cx.tcx.sess.features.borrow().fn_must_use {
if cx.tcx.features().fn_must_use {
let maybe_def = match expr.node {
hir::ExprCall(ref callee, _) => {
match callee.node {

View file

@ -225,9 +225,6 @@ impl<'a> CrateLoader<'a> {
crate_root.def_path_table.decode((&metadata, self.sess))
});
let exported_symbols = crate_root.exported_symbols
.decode((&metadata, self.sess))
.collect();
let trait_impls = crate_root
.impls
.decode((&metadata, self.sess))
@ -238,7 +235,6 @@ impl<'a> CrateLoader<'a> {
name,
extern_crate: Cell::new(None),
def_path_table: Lrc::new(def_path_table),
exported_symbols,
trait_impls,
proc_macros: crate_root.macro_derive_registrar.map(|_| {
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)

View file

@ -78,8 +78,6 @@ pub struct CrateMetadata {
/// compilation support.
pub def_path_table: Lrc<DefPathTable>,
pub exported_symbols: FxHashSet<DefIndex>,
pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
pub dep_kind: Cell<DepKind>,

View file

@ -18,6 +18,7 @@ use rustc::ty::maps::QueryConfig;
use rustc::middle::cstore::{CrateStore, DepKind,
MetadataLoader, LinkMeta,
LoadedMacro, EncodedMetadata, NativeLibraryKind};
use rustc::middle::exported_symbols::ExportedSymbol;
use rustc::middle::stability::DeprecationEntry;
use rustc::hir::def;
use rustc::session::{CrateDisambiguator, Session};
@ -27,10 +28,11 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
use rustc::hir::map::{DefKey, DefPath, DefPathHash};
use rustc::hir::map::blocks::FnLikeNode;
use rustc::hir::map::definitions::DefPathTable;
use rustc::util::nodemap::{NodeSet, DefIdMap};
use rustc::util::nodemap::DefIdMap;
use std::any::Any;
use rustc_data_structures::sync::Lrc;
use std::sync::Arc;
use syntax::ast;
use syntax::attr;
@ -160,9 +162,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
impl_parent => { cdata.get_parent_impl(def_id.index) }
trait_of_item => { cdata.get_trait_of_item(def_id.index) }
is_exported_symbol => {
cdata.exported_symbols.contains(&def_id.index)
}
item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
const_is_rvalue_promotable_to_static => {
cdata.const_is_rvalue_promotable_to_static(def_id.index)
@ -179,7 +178,21 @@ provide! { <'tcx> tcx, def_id, other, cdata,
extern_crate => { Lrc::new(cdata.extern_crate.get()) }
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
exported_symbol_ids => { Lrc::new(cdata.get_exported_symbols()) }
reachable_non_generics => {
let reachable_non_generics = tcx
.exported_symbols(cdata.cnum)
.iter()
.filter_map(|&(exported_symbol, _)| {
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
return Some(def_id)
} else {
None
}
})
.collect();
Lrc::new(reachable_non_generics)
}
native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
plugin_registrar_fn => {
cdata.root.plugin_registrar_fn.map(|index| {
@ -238,6 +251,19 @@ provide! { <'tcx> tcx, def_id, other, cdata,
has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
exported_symbols => {
let cnum = cdata.cnum;
assert!(cnum != LOCAL_CRATE);
// If this crate is a custom derive crate, then we're not even going to
// link those in so we skip those crates.
if cdata.root.macro_derive_registrar.is_some() {
return Arc::new(Vec::new())
}
Arc::new(cdata.exported_symbols())
}
}
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
@ -520,11 +546,10 @@ impl CrateStore for cstore::CStore {
fn encode_metadata<'a, 'tcx>(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
reachable: &NodeSet)
link_meta: &LinkMeta)
-> EncodedMetadata
{
encoder::encode_metadata(tcx, link_meta, reachable)
encoder::encode_metadata(tcx, link_meta)
}
fn metadata_encoding_version(&self) -> &[u8]

View file

@ -18,6 +18,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir;
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
ExternBodyNestedBodies};
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex,
CRATE_DEF_INDEX, LOCAL_CRATE};
@ -27,7 +28,6 @@ use rustc::mir;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::codec::TyDecoder;
use rustc::util::nodemap::DefIdSet;
use rustc::mir::Mir;
use std::cell::Ref;
@ -1006,10 +1006,10 @@ impl<'a, 'tcx> CrateMetadata {
arg_names.decode(self).collect()
}
pub fn get_exported_symbols(&self) -> DefIdSet {
self.exported_symbols
.iter()
.map(|&index| self.local_def_id(index))
pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> {
self.root
.exported_symbols
.decode(self)
.collect()
}

View file

@ -20,14 +20,16 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE
use rustc::hir::map::definitions::DefPathTable;
use rustc::ich::Fingerprint;
use rustc::middle::dependency_format::Linkage;
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel,
metadata_symbol_name};
use rustc::middle::lang_items;
use rustc::mir;
use rustc::traits::specialization_graph;
use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
use rustc::ty::codec::{self as ty_codec, TyEncoder};
use rustc::session::config::{self, CrateTypeProcMacro};
use rustc::util::nodemap::{FxHashMap, NodeSet};
use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
@ -53,7 +55,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
opaque: opaque::Encoder<'a>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &'a LinkMeta,
exported_symbols: &'a NodeSet,
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
@ -395,9 +396,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// Encode exported symbols info.
i = self.position();
let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
let exported_symbols = self.tracked(
IsolatedEncoder::encode_exported_symbols,
self.exported_symbols);
&exported_symbols);
let exported_symbols_bytes = self.position() - i;
// Encode and index the items.
@ -1388,9 +1390,25 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
// middle::reachable module but filters out items that either don't have a
// symbol associated with them (they weren't translated) or if they're an FFI
// definition (as that's not defined in this crate).
fn encode_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq<DefIndex> {
let tcx = self.tcx;
self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index))
fn encode_exported_symbols(&mut self,
exported_symbols: &[(ExportedSymbol, SymbolExportLevel)])
-> LazySeq<(ExportedSymbol, SymbolExportLevel)> {
// The metadata symbol name is special. It should not show up in
// downstream crates.
let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
self.lazy_seq(exported_symbols
.iter()
.filter(|&&(ref exported_symbol, _)| {
match *exported_symbol {
ExportedSymbol::NoDefId(symbol_name) => {
symbol_name != metadata_symbol_name
},
_ => true,
}
})
.cloned())
}
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
@ -1663,8 +1681,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> {
// generated regardless of trailing bytes that end up in it.
pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &LinkMeta,
exported_symbols: &NodeSet)
link_meta: &LinkMeta)
-> EncodedMetadata
{
let mut cursor = Cursor::new(vec![]);
@ -1678,7 +1695,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
opaque: opaque::Encoder::new(&mut cursor),
tcx,
link_meta,
exported_symbols,
lazy_state: LazyState::NoNode,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),

View file

@ -146,7 +146,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
None => self.tcx.sess.err(msg),
}
}
if lib.cfg.is_some() && !self.tcx.sess.features.borrow().link_cfg {
if lib.cfg.is_some() && !self.tcx.features().link_cfg {
feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
"link_cfg",
span.unwrap(),
@ -154,7 +154,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
"is feature gated");
}
if lib.kind == cstore::NativeStaticNobundle &&
!self.tcx.sess.features.borrow().static_nobundle {
!self.tcx.features().static_nobundle {
feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
"static_nobundle",
span.unwrap(),

View file

@ -16,6 +16,7 @@ use rustc::hir::def::{self, CtorKind};
use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
use rustc::ich::StableHashingContext;
use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc::middle::lang_items;
use rustc::mir;
use rustc::session::CrateDisambiguator;
@ -202,7 +203,8 @@ pub struct CrateRoot {
pub codemap: LazySeq<syntax_pos::FileMap>,
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
pub impls: LazySeq<TraitImpls>,
pub exported_symbols: LazySeq<DefIndex>,
pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>,
pub index: LazySeq<index::Index>,
}

View file

@ -16,7 +16,7 @@ use rustc::ty::{self, RegionKind};
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::sync::Lrc;
use super::{MirBorrowckCtxt, Context};
use super::{Context, MirBorrowckCtxt};
use super::{InitializationRequiringAction, PrefixSet};
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
use dataflow::move_paths::MovePathIndex;
@ -96,7 +96,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
} else {
true
}
},
}
_ => true,
};
@ -106,9 +106,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
None => "value".to_owned(),
};
err.note(&format!("move occurs because {} has type `{}`, \
which does not implement the `Copy` trait",
note_msg, ty));
err.note(&format!(
"move occurs because {} has type `{}`, \
which does not implement the `Copy` trait",
note_msg, ty
));
}
}
@ -154,7 +156,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span,
&self.describe_place(place).unwrap_or("_".to_owned()),
self.retrieve_borrow_span(borrow),
&self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()),
&self.describe_place(&borrow.borrowed_place)
.unwrap_or("_".to_owned()),
Origin::Mir,
);
@ -175,8 +178,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
use rustc::hir::ExprClosure;
use rustc::mir::AggregateKind;
let local = match self.mir[location.block].statements.get(location.statement_index) {
Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local,
let local = match self.mir[location.block]
.statements
.get(location.statement_index)
{
Some(&Statement {
kind: StatementKind::Assign(Place::Local(local), _),
..
}) => local,
_ => return None,
};
@ -202,8 +211,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
.with_freevars(node_id, |freevars| {
for (v, place) in freevars.iter().zip(places) {
match *place {
Operand::Copy(Place::Local(l)) |
Operand::Move(Place::Local(l)) if local == l =>
Operand::Copy(Place::Local(l))
| Operand::Move(Place::Local(l)) if local == l =>
{
debug!(
"find_closure_span: found captured local {:?}",
@ -232,7 +241,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
context: Context,
(place, span): (&Place<'tcx>, Span),
gen_borrow_kind: BorrowKind,
issued_borrow: &BorrowData,
issued_borrow: &BorrowData<'tcx>,
end_issued_loan_span: Option<Span>,
) {
let issued_span = self.retrieve_borrow_span(issued_borrow);
@ -255,8 +264,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
"immutable",
"mutable",
) {
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) |
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
.cannot_reborrow_already_borrowed(
span,
&desc_place,
@ -355,11 +364,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
context: Context,
borrow: &BorrowData<'tcx>,
drop_span: Span,
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>,
) {
let end_span = borrows.opt_region_end_span(&borrow.region);
let scope_tree = borrows.0.scope_tree();
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap();
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
.last()
.unwrap();
let borrow_span = self.mir.source_info(borrow.location).span;
let proper_span = match *root_place {
@ -367,13 +378,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_ => drop_span,
};
if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) {
debug!("suppressing access_place error when borrow doesn't live long enough for {:?}",
borrow_span);
if self.access_place_error_reported
.contains(&(root_place.clone(), borrow_span))
{
debug!(
"suppressing access_place error when borrow doesn't live long enough for {:?}",
borrow_span
);
return;
}
self.access_place_error_reported.insert((root_place.clone(), borrow_span));
self.access_place_error_reported
.insert((root_place.clone(), borrow_span));
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
(RegionKind::ReScope(_), Some(name)) => {
@ -385,9 +401,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span,
borrow_span,
proper_span,
end_span
end_span,
);
},
}
(RegionKind::ReScope(_), None) => {
self.report_scoped_temporary_value_does_not_live_long_enough(
context,
@ -396,14 +412,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span,
borrow_span,
proper_span,
end_span
end_span,
);
},
(RegionKind::ReEarlyBound(_), Some(name)) |
(RegionKind::ReFree(_), Some(name)) |
(RegionKind::ReStatic, Some(name)) |
(RegionKind::ReEmpty, Some(name)) |
(RegionKind::ReVar(_), Some(name)) => {
}
(RegionKind::ReEarlyBound(_), Some(name))
| (RegionKind::ReFree(_), Some(name))
| (RegionKind::ReStatic, Some(name))
| (RegionKind::ReEmpty, Some(name))
| (RegionKind::ReVar(_), Some(name)) => {
self.report_unscoped_local_value_does_not_live_long_enough(
context,
name,
@ -414,12 +430,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
proper_span,
end_span,
);
},
(RegionKind::ReEarlyBound(_), None) |
(RegionKind::ReFree(_), None) |
(RegionKind::ReStatic, None) |
(RegionKind::ReEmpty, None) |
(RegionKind::ReVar(_), None) => {
}
(RegionKind::ReEarlyBound(_), None)
| (RegionKind::ReFree(_), None)
| (RegionKind::ReStatic, None)
| (RegionKind::ReEmpty, None)
| (RegionKind::ReVar(_), None) => {
self.report_unscoped_temporary_value_does_not_live_long_enough(
context,
&scope_tree,
@ -429,13 +445,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
proper_span,
end_span,
);
},
(RegionKind::ReLateBound(_, _), _) |
(RegionKind::ReSkolemized(_, _), _) |
(RegionKind::ReClosureBound(_), _) |
(RegionKind::ReErased, _) => {
}
(RegionKind::ReLateBound(_, _), _)
| (RegionKind::ReSkolemized(_, _), _)
| (RegionKind::ReClosureBound(_), _)
| (RegionKind::ReErased, _) => {
span_bug!(drop_span, "region does not make sense in this context");
},
}
}
}
@ -450,11 +466,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_proper_span: Span,
end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
&format!("`{}`", name),
Origin::Mir);
let mut err = self.tcx.path_does_not_live_long_enough(
borrow_span,
&format!("`{}`", name),
Origin::Mir,
);
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
err.span_label(
drop_span,
format!("`{}` dropped here while still borrowed", name),
);
if let Some(end) = end_span {
err.span_label(end, "borrowed value needs to live until here");
}
@ -472,11 +493,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
proper_span: Span,
end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
"borrowed value",
Origin::Mir);
let mut err =
self.tcx
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
err.span_label(proper_span, "temporary value does not live long enough");
err.span_label(drop_span, "temporary value dropped here while still borrowed");
err.span_label(
drop_span,
"temporary value dropped here while still borrowed",
);
err.note("consider using a `let` binding to increase its lifetime");
if let Some(end) = end_span {
err.span_label(end, "temporary value needs to live until here");
@ -496,14 +520,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
_proper_span: Span,
_end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
&format!("`{}`", name),
Origin::Mir);
debug!(
"report_unscoped_local_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
)",
context, name, scope_tree, borrow, drop_span, borrow_span
);
let mut err = self.tcx.path_does_not_live_long_enough(
borrow_span,
&format!("`{}`", name),
Origin::Mir,
);
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, "borrowed value only lives until here");
self.tcx.note_and_explain_region(scope_tree, &mut err,
"borrowed value must be valid for ",
borrow.region, "...");
if !self.tcx.nll() {
self.tcx.note_and_explain_region(
scope_tree,
&mut err,
"borrowed value must be valid for ",
borrow.region,
"...",
);
}
self.explain_why_borrow_contains_point(context, borrow, &mut err);
err.emit();
}
@ -516,16 +557,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
drop_span: Span,
_borrow_span: Span,
proper_span: Span,
_end_span: Option<Span>
_end_span: Option<Span>,
) {
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
"borrowed value",
Origin::Mir);
debug!(
"report_unscoped_temporary_value_does_not_live_long_enough(\
{:?}, {:?}, {:?}, {:?}, {:?}\
)",
context, scope_tree, borrow, drop_span, proper_span
);
let mut err =
self.tcx
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
err.span_label(proper_span, "temporary value does not live long enough");
err.span_label(drop_span, "temporary value only lives until here");
self.tcx.note_and_explain_region(scope_tree, &mut err,
"borrowed value must be valid for ",
borrow.region, "...");
if !self.tcx.nll() {
self.tcx.note_and_explain_region(
scope_tree,
&mut err,
"borrowed value must be valid for ",
borrow.region,
"...",
);
}
self.explain_why_borrow_contains_point(context, borrow, &mut err);
err.emit();
}
@ -534,7 +590,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
&mut self,
context: Context,
(place, span): (&Place<'tcx>, Span),
loan: &BorrowData,
loan: &BorrowData<'tcx>,
) {
let mut err = self.tcx.cannot_assign_to_borrowed(
span,
@ -706,9 +762,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
ProjectionElem::Field(_, field_type) => {
self.describe_field_from_ty(&field_type, field)
}
ProjectionElem::Index(..) |
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Subslice { .. } => {
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
format!("{}", self.describe_field(&proj.base, field))
}
},
@ -765,13 +821,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Place::Local(local) => {
let local = &self.mir.local_decls[*local];
Some(local.ty)
},
}
Place::Static(ref st) => Some(st.ty),
Place::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Field(_, ty) => Some(ty),
_ => None,
}
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(_, ty) => Some(ty),
_ => None,
},
}
}

View file

@ -72,7 +72,7 @@ fn mir_borrowck<'a, 'tcx>(
let input_mir = tcx.mir_validated(def_id);
debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.use_mir() {
if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir() {
return None;
}
@ -101,7 +101,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
// contain non-lexical lifetimes. It will have a lifetime tied
// to the inference context.
let mut mir: Mir<'tcx> = input_mir.clone();
let free_regions = if !tcx.sess.nll() {
let free_regions = if !tcx.nll() {
None
} else {
let mir = &mut mir;
@ -204,7 +204,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
);
(Some(Rc::new(regioncx)), opt_closure_req)
} else {
assert!(!tcx.sess.nll());
assert!(!tcx.nll());
(None, None)
};
let flow_inits = flow_inits; // remove mut
@ -719,7 +719,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
/// allowed to be split into separate Reservation and
/// Activation phases.
fn allow_two_phase_borrow(&self, kind: BorrowKind) -> bool {
self.tcx.sess.two_phase_borrows() &&
self.tcx.two_phase_borrows() &&
(kind.allows_two_phase_borrow() ||
self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref)
}
@ -1253,7 +1253,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
span: Span,
flow_state: &Flows<'cx, 'gcx, 'tcx>,
) {
if !self.tcx.sess.two_phase_borrows() {
if !self.tcx.two_phase_borrows() {
return;
}

View file

@ -21,7 +21,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
pub(in borrow_check) fn explain_why_borrow_contains_point(
&self,
context: Context,
borrow: &BorrowData<'_>,
borrow: &BorrowData<'tcx>,
err: &mut DiagnosticBuilder<'_>,
) {
if let Some(regioncx) = &self.nonlexical_regioncx {
@ -70,9 +70,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
}
_ => {
cause.label_diagnostic(mir, err);
Cause::UniversalRegion(region_vid) => {
if let Some(region) = regioncx.to_error_region(region_vid) {
self.tcx.note_and_explain_free_region(
err,
"borrowed value must be valid for ",
region,
"...",
);
}
}
_ => {}
}
}
}

View file

@ -26,7 +26,6 @@ use rustc::ty::{self, RegionVid, Ty, TypeFoldable};
use rustc::util::common::ErrorReported;
use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_errors::DiagnosticBuilder;
use std::fmt;
use std::rc::Rc;
use syntax::ast;
@ -435,7 +434,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut());
self.check_universal_regions(infcx, mir_def_id, outlives_requirements.as_mut());
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
@ -574,10 +573,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// an error that multiple bounds are required.
tcx.sess.span_err(
type_test.span,
&format!(
"`{}` does not live long enough",
type_test.generic_kind,
),
&format!("`{}` does not live long enough", type_test.generic_kind,),
);
}
}
@ -589,13 +585,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// existentially bound, then we check its inferred value and try
/// to find a good name from that. Returns `None` if we can't find
/// one (e.g., this is just some random part of the CFG).
fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
if self.universal_regions.is_universal_region(r) {
return self.definitions[r].external_name;
} else {
let inferred_values = self.inferred_values
.as_ref()
.expect("region values not yet inferred");
.as_ref()
.expect("region values not yet inferred");
let upper_bound = self.universal_upper_bound(r);
if inferred_values.contains(r, upper_bound) {
self.to_error_region(upper_bound)
@ -807,9 +803,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool {
debug!(
"eval_region_test(point={:?}, lower_bound={:?}, test={:?})",
point,
lower_bound,
test
point, lower_bound, test
);
match test {
@ -841,9 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool {
debug!(
"eval_outlives({:?}: {:?} @ {:?})",
sup_region,
sub_region,
point
sup_region, sub_region, point
);
// Roughly speaking, do a DFS of all region elements reachable
@ -897,7 +889,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_universal_regions<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
) {
@ -913,7 +904,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
for (fr, _) in universal_definitions {
self.check_universal_region(
infcx,
mir,
mir_def_id,
fr,
&mut propagated_outlives_requirements,
@ -932,7 +922,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_universal_region<'gcx>(
&self,
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
longer_fr: RegionVid,
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
@ -951,8 +940,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
debug!(
"check_universal_region: fr={:?} does not outlive shorter_fr={:?}",
longer_fr,
shorter_fr,
longer_fr, shorter_fr,
);
let blame_span = self.blame_span(longer_fr, shorter_fr);
@ -990,7 +978,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Note: in this case, we use the unapproximated regions
// to report the error. This gives better error messages
// in some cases.
self.report_error(infcx, mir, mir_def_id, longer_fr, shorter_fr, blame_span);
self.report_error(infcx, mir_def_id, longer_fr, shorter_fr, blame_span);
}
}
@ -1005,7 +993,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn report_error(
&self,
infcx: &InferCtxt<'_, '_, 'tcx>,
mir: &Mir<'tcx>,
mir_def_id: DefId,
fr: RegionVid,
outlived_fr: RegionVid,
@ -1039,12 +1026,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
&format!("{} does not outlive {}", fr_string, outlived_fr_string,),
);
// Find out why `fr` had to outlive `outlived_fr`...
let inferred_values = self.inferred_values.as_ref().unwrap();
if let Some(cause) = inferred_values.cause(fr, outlived_fr) {
cause.label_diagnostic(mir, &mut diag);
}
diag.emit();
}
@ -1134,10 +1115,7 @@ impl fmt::Debug for Constraint {
write!(
formatter,
"({:?}: {:?} @ {:?}) due to {:?}",
self.sup,
self.sub,
self.point,
self.span
self.sup, self.sub, self.point, self.span
)
}
}
@ -1187,9 +1165,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
debug!(
"apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
location,
closure_def_id,
closure_substs
location, closure_def_id, closure_substs
);
// Get Tu.
@ -1217,9 +1193,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
"apply_requirements: region={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
region,
outlived_region,
outlives_requirement,
region, outlived_region, outlives_requirement,
);
infcx.sub_regions(origin, outlived_region, region);
}
@ -1230,9 +1204,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
"apply_requirements: ty={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
ty,
outlived_region,
outlives_requirement,
ty, outlived_region, outlives_requirement,
);
infcx.register_region_obligation(
body_id,
@ -1285,77 +1257,14 @@ impl CauseExt for Rc<Cause> {
}
impl Cause {
pub(crate) fn label_diagnostic(&self, mir: &Mir<'_>, diag: &mut DiagnosticBuilder<'_>) {
// The cause information is pretty messy. Only dump it as an
// internal debugging aid if -Znll-dump-cause is given.
let nll_dump_cause = ty::tls::with(|tcx| tcx.sess.nll_dump_cause());
if !nll_dump_cause {
return;
}
let mut string = String::new();
self.push_diagnostic_string(mir, &mut string);
diag.note(&string);
}
fn push_diagnostic_string(&self, mir: &Mir<'_>, string: &mut String) {
match self {
Cause::LiveVar(local, location) => {
string.push_str(&format!("because `{:?}` is live at {:?}", local, location));
}
Cause::DropVar(local, location) => {
string.push_str(&format!(
"because `{:?}` is dropped at {:?}",
local,
location
));
}
Cause::LiveOther(location) => {
string.push_str(&format!(
"because of a general liveness constraint at {:?}",
location
));
}
Cause::UniversalRegion(region_vid) => {
string.push_str(&format!(
"because `{:?}` is universally quantified",
region_vid
));
}
Cause::Outlives {
original_cause,
constraint_location,
constraint_span: _,
} => {
string.push_str(&format!(
"because of an outlives relation created at `{:?}`\n",
constraint_location
));
original_cause.push_diagnostic_string(mir, string);
}
}
}
pub(crate) fn root_cause(&self) -> &Cause {
match self {
Cause::LiveVar(..) |
Cause::DropVar(..) |
Cause::LiveOther(..) |
Cause::UniversalRegion(..) => {
self
}
Cause::LiveVar(..)
| Cause::DropVar(..)
| Cause::LiveOther(..)
| Cause::UniversalRegion(..) => self,
Cause::Outlives {
original_cause,
..
} => {
original_cause.root_cause()
}
Cause::Outlives { original_cause, .. } => original_cause.root_cause(),
}
}
}

View file

@ -1587,7 +1587,7 @@ impl MirPass for TypeckMir {
// When NLL is enabled, the borrow checker runs the typeck
// itself, so we don't need this MIR pass anymore.
if tcx.sess.nll() {
if tcx.nll() {
return;
}

View file

@ -50,7 +50,7 @@ impl<'tcx> CFG<'tcx> {
block: BasicBlock,
source_info: SourceInfo,
region_scope: region::Scope) {
if tcx.sess.emit_end_regions() {
if tcx.emit_end_regions() {
if let region::ScopeData::CallSite(_) = region_scope.data() {
// The CallSite scope (aka the root scope) is sort of weird, in that it is
// supposed to "separate" the "interior" and "exterior" of a closure. Being

View file

@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
i == variant_index || {
self.hir.tcx().sess.features.borrow().never_type &&
self.hir.tcx().features().never_type &&
self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
}
});

View file

@ -736,7 +736,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
}
Some(_) => true,
None => {
if tcx.is_exported_symbol(def_id) ||
if tcx.is_reachable_non_generic(def_id) ||
tcx.is_foreign_item(def_id)
{
// We can link to the item in question, no instance needed
@ -984,7 +984,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
}
MonoItemCollectionMode::Lazy => {
self.entry_fn == Some(def_id) ||
self.tcx.is_exported_symbol(def_id) ||
self.tcx.is_reachable_non_generic(def_id) ||
attr::contains_name(&self.tcx.get_attrs(def_id),
"rustc_std_internal_symbol")
}

View file

@ -363,7 +363,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
can_be_internalized = false;
Visibility::Hidden
} else if def_id.is_local() {
if tcx.is_exported_symbol(def_id) {
if tcx.is_reachable_non_generic(def_id) {
can_be_internalized = false;
default_visibility(def_id)
} else {
@ -385,7 +385,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
(Linkage::External, visibility)
}
MonoItem::Static(def_id) => {
let visibility = if tcx.is_exported_symbol(def_id) {
let visibility = if tcx.is_reachable_non_generic(def_id) {
can_be_internalized = false;
default_visibility(def_id)
} else {
@ -395,7 +395,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
MonoItem::GlobalAsm(node_id) => {
let def_id = tcx.hir.local_def_id(node_id);
let visibility = if tcx.is_exported_symbol(def_id) {
let visibility = if tcx.is_reachable_non_generic(def_id) {
can_be_internalized = false;
default_visibility(def_id)
} else {

View file

@ -42,7 +42,7 @@ impl MirPass for CleanEndRegions {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
_source: MirSource,
mir: &mut Mir<'tcx>) {
if !tcx.sess.emit_end_regions() { return; }
if !tcx.emit_end_regions() { return; }
let mut gather = GatherBorrowedRegions {
seen_regions: FxHashSet()

View file

@ -77,19 +77,12 @@ impl Lower128Bit {
};
let bin_statement = block.statements.pop().unwrap();
let (source_info, place, lhs, mut rhs) = match bin_statement {
Statement {
source_info,
kind: StatementKind::Assign(
place,
Rvalue::BinaryOp(_, lhs, rhs))
} => (source_info, place, lhs, rhs),
Statement {
source_info,
kind: StatementKind::Assign(
place,
Rvalue::CheckedBinaryOp(_, lhs, rhs))
} => (source_info, place, lhs, rhs),
let source_info = bin_statement.source_info;
let (place, lhs, mut rhs) = match bin_statement.kind {
StatementKind::Assign(place, Rvalue::BinaryOp(_, lhs, rhs))
| StatementKind::Assign(place, Rvalue::CheckedBinaryOp(_, lhs, rhs)) => {
(place, lhs, rhs)
}
_ => bug!("Statement doesn't match pattern any more?"),
};

View file

@ -936,7 +936,7 @@ This does not pose a problem by itself because they can't be accessed directly."
if self.mode != Mode::Fn &&
// feature-gate is not enabled,
!self.tcx.sess.features.borrow()
!self.tcx.features()
.declared_lib_features
.iter()
.any(|&(ref sym, _)| sym == feature_name) &&

View file

@ -514,7 +514,7 @@ impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
o: Origin)
-> DiagnosticBuilder<'a>
{
if !o.should_emit_errors(self.sess.borrowck_mode()) {
if !o.should_emit_errors(self.borrowck_mode()) {
self.sess.diagnostic().cancel(&mut diag);
}
diag

View file

@ -52,7 +52,7 @@ pub fn load_plugins(sess: &Session,
// do not report any error now. since crate attributes are
// not touched by expansion, every use of plugin without
// the feature enabled will result in an error later...
if sess.features.borrow().plugin {
if sess.features_untracked().plugin {
for attr in &krate.attrs {
if !attr.check_name("plugin") {
continue;

View file

@ -590,7 +590,7 @@ impl<'a> Resolver<'a> {
};
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features,
&self.session.features_untracked(),
&macro_def));
self.macro_map.insert(def_id, ext.clone());
ext

View file

@ -1524,7 +1524,7 @@ impl<'a> Resolver<'a> {
invocations.insert(Mark::root(),
arenas.alloc_invocation_data(InvocationData::root(graph_root)));
let features = session.features.borrow();
let features = session.features_untracked();
let mut macro_defs = FxHashMap();
macro_defs.insert(Mark::root(), root_def_id);
@ -2998,7 +2998,7 @@ impl<'a> Resolver<'a> {
let prim = self.primitive_type_table.primitive_types[&path[0].node.name];
match prim {
TyUint(UintTy::U128) | TyInt(IntTy::I128) => {
if !self.session.features.borrow().i128_type {
if !self.session.features_untracked().i128_type {
emit_feature_err(&self.session.parse_sess,
"i128_type", span, GateIssue::Language,
"128-bit type is unstable");
@ -3089,7 +3089,7 @@ impl<'a> Resolver<'a> {
let prev_name = path[0].node.name;
if prev_name == keywords::Extern.name() ||
prev_name == keywords::CrateRoot.name() &&
self.session.features.borrow().extern_absolute_paths {
self.session.features_untracked().extern_absolute_paths {
// `::extern_crate::a::b`
let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
let crate_root =

View file

@ -744,7 +744,7 @@ impl<'a> Resolver<'a> {
let def_id = self.definitions.local_def_id(item.id);
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features,
&self.session.features_untracked(),
item));
self.macro_map.insert(def_id, ext);
@ -838,7 +838,7 @@ impl<'a> Resolver<'a> {
}
fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) {
if !self.session.features.borrow().custom_derive {
if !self.session.features_untracked().custom_derive {
let sess = &self.session.parse_sess;
let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE;
emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain);

View file

@ -609,7 +609,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() ||
module_path[0].node.name == keywords::Extern.name()) {
let is_extern = module_path[0].node.name == keywords::Extern.name() ||
self.session.features.borrow().extern_absolute_paths;
self.session.features_untracked().extern_absolute_paths;
match directive.subclass {
GlobImport { .. } if is_extern => {
return Some((directive.span,

View file

@ -768,9 +768,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
let mut symbols = Vec::new();
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
if level.is_below_threshold(export_threshold) {
symbols.push(name.clone());
symbols.push(symbol.symbol_name(tcx).to_string());
}
}
@ -782,9 +782,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
// ... we add its symbol list to our export list.
for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() {
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
if level.is_below_threshold(export_threshold) {
symbols.push(name.clone());
symbols.push(symbol.symbol_name(tcx).to_string());
}
}
}

View file

@ -113,7 +113,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
Lto::No => panic!("didn't request LTO but we're doing LTO"),
};
let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| {
let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
if level.is_below_threshold(export_threshold) {
let mut bytes = Vec::with_capacity(name.len() + 1);
bytes.extend(name.bytes());

View file

@ -11,33 +11,27 @@
use rustc_data_structures::sync::Lrc;
use std::sync::Arc;
use base;
use monomorphize::Instance;
use rustc::hir;
use rustc::hir::def_id::CrateNum;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::exported_symbols::SymbolExportLevel;
use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name};
use rustc::session::config;
use rustc::ty::TyCtxt;
use rustc::ty::{TyCtxt, SymbolName};
use rustc::ty::maps::Providers;
use rustc::util::nodemap::FxHashMap;
use rustc::util::nodemap::{FxHashMap, DefIdSet};
use rustc_allocator::ALLOCATOR_METHODS;
use syntax::attr;
pub type ExportedSymbols = FxHashMap<
CrateNum,
Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
Arc<Vec<(String, SymbolExportLevel)>>,
>;
pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
crates_export_threshold(&tcx.sess.crate_types.borrow())
}
pub fn metadata_symbol_name(tcx: TyCtxt) -> String {
format!("rust_metadata_{}_{}",
tcx.crate_name(LOCAL_CRATE),
tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex())
}
fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
match crate_type {
config::CrateTypeExecutable |
@ -60,140 +54,203 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType])
}
}
pub fn provide(providers: &mut Providers) {
providers.exported_symbol_ids = |tcx, cnum| {
let export_threshold = threshold(tcx);
Lrc::new(tcx.exported_symbols(cnum)
.iter()
.filter_map(|&(_, id, level)| {
id.and_then(|id| {
if level.is_below_threshold(export_threshold) {
Some(id)
fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum)
-> Lrc<DefIdSet>
{
assert_eq!(cnum, LOCAL_CRATE);
if !tcx.sess.opts.output_types.should_trans() {
return Lrc::new(DefIdSet())
}
let export_threshold = threshold(tcx);
// We already collect all potentially reachable non-generic items for
// `exported_symbols`. Now we just filter them down to what is actually
// exported for the given crate we are compiling.
let reachable_non_generics = tcx
.exported_symbols(LOCAL_CRATE)
.iter()
.filter_map(|&(exported_symbol, level)| {
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
if level.is_below_threshold(export_threshold) {
return Some(def_id)
}
}
None
})
.collect();
Lrc::new(reachable_non_generics)
}
fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> bool {
tcx.reachable_non_generics(def_id.krate).contains(&def_id)
}
fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum)
-> Arc<Vec<(ExportedSymbol,
SymbolExportLevel)>>
{
assert_eq!(cnum, LOCAL_CRATE);
if !tcx.sess.opts.output_types.should_trans() {
return Arc::new(vec![])
}
// Check to see if this crate is a "special runtime crate". These
// crates, implementation details of the standard library, typically
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
// ABI between them. We don't want their symbols to have a `C`
// export level, however, as they're just implementation details.
// Down below we'll hardwire all of the symbols to the `Rust` export
// level instead.
let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) ||
tcx.is_compiler_builtins(LOCAL_CRATE);
let reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0
.iter()
.filter_map(|&node_id| {
// We want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// categories:
//
// 1. Those that are included statically via a static library
// 2. Those included otherwise (e.g. dynamically or via a framework)
//
// Although our LLVM module is not literally emitting code for the
// statically included symbols, it's an export of our library which
// needs to be passed on to the linker and encoded in the metadata.
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
match tcx.hir.get(node_id) {
hir::map::NodeForeignItem(..) => {
let def_id = tcx.hir.local_def_id(node_id);
if tcx.is_statically_included_foreign_item(def_id) {
Some(def_id)
} else {
None
}
})
})
.collect())
};
}
providers.is_exported_symbol = |tcx, id| {
tcx.exported_symbol_ids(id.krate).contains(&id)
};
// Only consider nodes that actually have exported symbols.
hir::map::NodeItem(&hir::Item {
node: hir::ItemStatic(..),
..
}) |
hir::map::NodeItem(&hir::Item {
node: hir::ItemFn(..), ..
}) |
hir::map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..),
..
}) => {
let def_id = tcx.hir.local_def_id(node_id);
let generics = tcx.generics_of(def_id);
if (generics.parent_types == 0 && generics.types.is_empty()) &&
// Functions marked with #[inline] are only ever translated
// with "internal" linkage and are never exported.
!Instance::mono(tcx, def_id).def.requires_local(tcx) {
Some(def_id)
} else {
None
}
}
providers.exported_symbols = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
let local_exported_symbols = base::find_exported_symbols(tcx);
let mut local_crate: Vec<_> = local_exported_symbols
.iter()
.map(|&node_id| {
tcx.hir.local_def_id(node_id)
})
.map(|def_id| {
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
let export_level = export_level(tcx, def_id);
debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
(str::to_owned(&name), Some(def_id), export_level)
})
.collect();
if let Some(_) = *tcx.sess.entry_fn.borrow() {
local_crate.push(("main".to_string(),
None,
SymbolExportLevel::C));
}
if tcx.sess.allocator_kind.get().is_some() {
for method in ALLOCATOR_METHODS {
local_crate.push((format!("__rust_{}", method.name),
None,
SymbolExportLevel::Rust));
_ => None
}
})
.collect();
let mut symbols: Vec<_> = reachable_non_generics
.iter()
.map(|&def_id| {
let export_level = if special_runtime_crate {
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
// We can probably do better here by just ensuring that
// it has hidden visibility rather than public
// visibility, as this is primarily here to ensure it's
// not stripped during LTO.
//
// In general though we won't link right if these
// symbols are stripped, and LTO currently strips them.
if &*name == "rust_eh_personality" ||
&*name == "rust_eh_register_frames" ||
&*name == "rust_eh_unregister_frames" {
SymbolExportLevel::C
} else {
SymbolExportLevel::Rust
}
} else {
tcx.symbol_export_level(def_id)
};
debug!("EXPORTED SYMBOL (local): {} ({:?})",
tcx.symbol_name(Instance::mono(tcx, def_id)),
export_level);
(ExportedSymbol::NonGeneric(def_id), export_level)
})
.collect();
if let Some(id) = tcx.sess.derive_registrar_fn.get() {
let def_id = tcx.hir.local_def_id(id);
symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C));
}
if let Some(id) = tcx.sess.plugin_registrar_fn.get() {
let def_id = tcx.hir.local_def_id(id);
symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C));
}
if let Some(_) = *tcx.sess.entry_fn.borrow() {
let symbol_name = "main".to_string();
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
symbols.push((exported_symbol, SymbolExportLevel::C));
}
if tcx.sess.allocator_kind.get().is_some() {
for method in ALLOCATOR_METHODS {
let symbol_name = format!("__rust_{}", method.name);
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
symbols.push((exported_symbol, SymbolExportLevel::Rust));
}
}
if let Some(id) = tcx.sess.derive_registrar_fn.get() {
let def_id = tcx.hir.local_def_id(id);
let disambiguator = tcx.sess.local_crate_disambiguator();
let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator);
local_crate.push((registrar, Some(def_id), SymbolExportLevel::C));
}
if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
let symbol_name = metadata_symbol_name(tcx);
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
local_crate.push((metadata_symbol_name(tcx),
None,
SymbolExportLevel::Rust));
}
symbols.push((exported_symbol, SymbolExportLevel::Rust));
}
// Sort so we get a stable incr. comp. hash.
local_crate.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
name1.cmp(name2)
});
// Sort so we get a stable incr. comp. hash.
symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
symbol1.compare_stable(tcx, symbol2)
});
Arc::new(local_crate)
};
Arc::new(symbols)
}
providers.symbol_export_level = export_level;
pub fn provide(providers: &mut Providers) {
providers.reachable_non_generics = reachable_non_generics_provider;
providers.is_reachable_non_generic = is_reachable_non_generic_provider;
providers.exported_symbols = exported_symbols_provider_local;
providers.symbol_export_level = symbol_export_level_provider;
}
pub fn provide_extern(providers: &mut Providers) {
providers.exported_symbols = |tcx, cnum| {
// If this crate is a plugin and/or a custom derive crate, then
// we're not even going to link those in so we skip those crates.
if tcx.plugin_registrar_fn(cnum).is_some() ||
tcx.derive_registrar_fn(cnum).is_some() {
return Arc::new(Vec::new())
}
// Check to see if this crate is a "special runtime crate". These
// crates, implementation details of the standard library, typically
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
// ABI between them. We don't want their symbols to have a `C`
// export level, however, as they're just implementation details.
// Down below we'll hardwire all of the symbols to the `Rust` export
// level instead.
let special_runtime_crate =
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
let mut crate_exports: Vec<_> = tcx
.exported_symbol_ids(cnum)
.iter()
.map(|&def_id| {
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
let export_level = if special_runtime_crate {
// We can probably do better here by just ensuring that
// it has hidden visibility rather than public
// visibility, as this is primarily here to ensure it's
// not stripped during LTO.
//
// In general though we won't link right if these
// symbols are stripped, and LTO currently strips them.
if &*name == "rust_eh_personality" ||
&*name == "rust_eh_register_frames" ||
&*name == "rust_eh_unregister_frames" {
SymbolExportLevel::C
} else {
SymbolExportLevel::Rust
}
} else {
export_level(tcx, def_id)
};
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
(str::to_owned(&name), Some(def_id), export_level)
})
.collect();
// Sort so we get a stable incr. comp. hash.
crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
name1.cmp(name2)
});
Arc::new(crate_exports)
};
providers.symbol_export_level = export_level;
providers.is_reachable_non_generic = is_reachable_non_generic_provider;
providers.symbol_export_level = symbol_export_level_provider;
}
fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
fn symbol_export_level_provider(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
// We export anything that's not mangled at the "C" layer as it probably has
// to do with ABI concerns. We do not, however, apply such treatment to
// special symbols in the standard library for various plumbing between

View file

@ -1332,20 +1332,31 @@ fn start_executing_work(tcx: TyCtxt,
let coordinator_send = tcx.tx_to_llvm_workers.clone();
let sess = tcx.sess;
let exported_symbols = match sess.lto() {
Lto::No => None,
Lto::ThinLocal => {
let mut exported_symbols = FxHashMap();
exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
Some(Arc::new(exported_symbols))
}
Lto::Yes | Lto::Fat | Lto::Thin => {
let mut exported_symbols = FxHashMap();
exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
for &cnum in tcx.crates().iter() {
exported_symbols.insert(cnum, tcx.exported_symbols(cnum));
// Compute the set of symbols we need to retain when doing LTO (if we need to)
let exported_symbols = {
let mut exported_symbols = FxHashMap();
let copy_symbols = |cnum| {
let symbols = tcx.exported_symbols(cnum)
.iter()
.map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl))
.collect();
Arc::new(symbols)
};
match sess.lto() {
Lto::No => None,
Lto::ThinLocal => {
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
Some(Arc::new(exported_symbols))
}
Lto::Yes | Lto::Fat | Lto::Thin => {
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
for &cnum in tcx.crates().iter() {
exported_symbols.insert(cnum, copy_symbols(cnum));
}
Some(Arc::new(exported_symbols))
}
Some(Arc::new(exported_symbols))
}
};

View file

@ -30,7 +30,6 @@ use super::ModuleKind;
use abi;
use back::link;
use back::symbol_export;
use back::write::{self, OngoingCrateTranslation, create_target_machine};
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
use llvm;
@ -45,6 +44,7 @@ use rustc::ty::maps::Providers;
use rustc::dep_graph::{DepNode, DepConstructor};
use rustc::ty::subst::Kind;
use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
use rustc::middle::exported_symbols;
use rustc::util::common::{time, print_time_passes_entry};
use rustc::session::config::{self, NoDebugInfo};
use rustc::session::Session;
@ -70,7 +70,7 @@ use time_graph;
use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
use type_::Type;
use type_of::LayoutLlvmExt;
use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet, DefIdSet};
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
use CrateInfo;
use std::any::Any;
@ -89,7 +89,7 @@ use syntax::ast;
use mir::operand::OperandValue;
pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr};
pub use rustc_trans_utils::check_for_rustc_errors_attr;
pub use rustc_mir::monomorphize::item::linkage_by_name;
pub struct StatRecorder<'a, 'tcx: 'a> {
@ -606,8 +606,7 @@ fn contains_null(s: &str) -> bool {
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
llmod_id: &str,
link_meta: &LinkMeta,
exported_symbols: &NodeSet)
link_meta: &LinkMeta)
-> (ContextRef, ModuleRef, EncodedMetadata) {
use std::io::Write;
use flate2::Compression;
@ -643,7 +642,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
EncodedMetadata::new());
}
let metadata = tcx.encode_metadata(link_meta, exported_symbols);
let metadata = tcx.encode_metadata(link_meta);
if kind == MetadataKind::Uncompressed {
return (metadata_llcx, metadata_llmod, metadata);
}
@ -655,7 +654,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
let name = symbol_export::metadata_symbol_name(tcx);
let name = exported_symbols::metadata_symbol_name(tcx);
let buf = CString::new(name).unwrap();
let llglobal = unsafe {
llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr())
@ -718,13 +717,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let crate_hash = tcx.crate_hash(LOCAL_CRATE);
let link_meta = link::build_link_meta(crate_hash);
let exported_symbol_node_ids = find_exported_symbols(tcx);
// Translate the metadata.
let llmod_id = "metadata";
let (metadata_llcx, metadata_llmod, metadata) =
time(tcx.sess.time_passes(), "write metadata", || {
write_metadata(tcx, llmod_id, &link_meta, &exported_symbol_node_ids)
write_metadata(tcx, llmod_id, &link_meta)
});
let metadata_module = ModuleTranslation {

View file

@ -151,7 +151,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
if cx.tcx.is_translated_item(instance_def_id) {
if instance_def_id.is_local() {
if !cx.tcx.is_exported_symbol(instance_def_id) {
if !cx.tcx.is_reachable_non_generic(instance_def_id) {
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
}
} else {

View file

@ -134,7 +134,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
let g = declare::define_global(cx, &sym[..], llty).unwrap();
if !cx.tcx.is_exported_symbol(def_id) {
if !cx.tcx.is_reachable_non_generic(def_id) {
unsafe {
llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
}

View file

@ -597,6 +597,12 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option<ValueRef> {
ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128);
ifn!("llvm.bitreverse.i8", fn(t_i8) -> t_i8);
ifn!("llvm.bitreverse.i16", fn(t_i16) -> t_i16);
ifn!("llvm.bitreverse.i32", fn(t_i32) -> t_i32);
ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64);
ifn!("llvm.bitreverse.i128", fn(t_i128) -> t_i128);
ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});

View file

@ -32,7 +32,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool
// visible). It might better to use the `exported_items` set from
// `driver::CrateAnalysis` in the future, but (atm) this set is not
// available in the translation pass.
!cx.tcx.is_exported_symbol(def_id)
!cx.tcx.is_reachable_non_generic(def_id)
}
#[allow(non_snake_case)]

View file

@ -287,8 +287,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
], None)
},
"ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
"overflowing_add" | "overflowing_sub" | "overflowing_mul" |
"bitreverse" | "add_with_overflow" | "sub_with_overflow" |
"mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => {
let ty = arg_tys[0];
match int_type_width_signed(ty, cx) {
@ -315,6 +315,10 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
&[args[0].immediate()], None)
}
}
"bitreverse" => {
bx.call(cx.get_intrinsic(&format!("llvm.bitreverse.i{}", width)),
&[args[0].immediate()], None)
}
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => {
let intrinsic = format!("llvm.{}{}.with.overflow.i{}",
if signed { 's' } else { 'u' },

View file

@ -44,11 +44,7 @@ extern crate rustc_data_structures;
pub extern crate rustc as __rustc;
use rustc::ty::{TyCtxt, Instance};
use rustc::hir;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc::hir::map as hir_map;
use rustc::util::nodemap::NodeSet;
use rustc::ty::TyCtxt;
pub mod diagnostics;
pub mod link;
@ -70,53 +66,4 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
}
}
/// The context provided lists a set of reachable ids as calculated by
/// middle::reachable, but this contains far more ids and symbols than we're
/// actually exposing from the object file. This function will filter the set in
/// the context to the set of ids which correspond to symbols that are exposed
/// from the object file being generated.
///
/// This list is later used by linkers to determine the set of symbols needed to
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| {
// Next, we want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// categories:
//
// 1. Those that are included statically via a static library
// 2. Those included otherwise (e.g. dynamically or via a framework)
//
// Although our LLVM module is not literally emitting code for the
// statically included symbols, it's an export of our library which
// needs to be passed on to the linker and encoded in the metadata.
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
match tcx.hir.get(id) {
hir_map::NodeForeignItem(..) => {
let def_id = tcx.hir.local_def_id(id);
tcx.is_statically_included_foreign_item(def_id)
}
// Only consider nodes that actually have exported symbols.
hir_map::NodeItem(&hir::Item {
node: hir::ItemStatic(..), .. }) |
hir_map::NodeItem(&hir::Item {
node: hir::ItemFn(..), .. }) |
hir_map::NodeImplItem(&hir::ImplItem {
node: hir::ImplItemKind::Method(..), .. }) => {
let def_id = tcx.hir.local_def_id(id);
let generics = tcx.generics_of(def_id);
(generics.parent_types == 0 && generics.types.is_empty()) &&
// Functions marked with #[inline] are only ever translated
// with "internal" linkage and are never exported.
!Instance::mono(tcx, def_id).def.requires_local(tcx)
}
_ => false
}
}).collect()
}
__build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS }

View file

@ -28,7 +28,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
// if the `rustc_attrs` feature is not enabled, then the
// attributes we are interested in cannot be present anyway, so
// skip the walk.
if !tcx.sess.features.borrow().rustc_attrs {
if !tcx.features().rustc_attrs {
return;
}

View file

@ -247,8 +247,7 @@ impl TransCrate for MetadataOnlyTransCrate {
tcx.sess.abort_if_errors();
let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
let exported_symbols = ::find_exported_symbols(tcx);
let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
let metadata = tcx.encode_metadata(&link_meta);
box OngoingCrateTranslation {
metadata: metadata,

View file

@ -415,7 +415,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let trait_def = self.tcx().trait_def(trait_def_id);
if !self.tcx().sess.features.borrow().unboxed_closures &&
if !self.tcx().features().unboxed_closures &&
trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar {
// For now, require that parenthetical notation be used only with `Fn()` etc.
let msg = if trait_def.paren_sugar {

View file

@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
};
if pat_adjustments.len() > 0 {
if tcx.sess.features.borrow().match_default_bindings {
if tcx.features().match_default_bindings {
debug!("default binding mode is now {:?}", def_bm);
self.inh.tables.borrow_mut()
.pat_adjustments_mut()

View file

@ -586,7 +586,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
}
}
if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion {
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
"unsized_tuple_coercion",
self.cause.span,

View file

@ -275,7 +275,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
"volatile_store" =>
(1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()),
"ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" =>
"ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" |
"bswap" | "bitreverse" =>
(1, vec![param(0)], param(0)),
"add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" =>

View file

@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// possible that there will be multiple applicable methods.
if !is_suggestion.0 {
if reached_raw_pointer
&& !self.tcx.sess.features.borrow().arbitrary_self_types {
&& !self.tcx.features().arbitrary_self_types {
// this case used to be allowed by the compiler,
// so we do a future-compat lint here for the 2015 epoch
// (see https://github.com/rust-lang/rust/issues/46906)

Some files were not shown because too many files have changed in this diff Show more