mirror of https://github.com/rust-lang/rust.git
Auto merge of #49406 - kennytm:rollup, r=kennytm
Rollup of 11 pull requests - Successful merges: #48639, #49223, #49333, #49369, #49381, #49395, #49399, #49401, #49417, #49202, #49426 - Failed merges:
This commit is contained in:
commit
59ec9bfc66
|
@ -594,7 +594,7 @@ If you're looking for somewhere to start, check out the [E-easy][eeasy] tag.
|
|||
[inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated
|
||||
[eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy
|
||||
[lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
|
||||
[rfcbot]: https://github.com/dikaiosune/rust-dashboard/blob/master/RFCBOT.md
|
||||
[rfcbot]: https://github.com/anp/rfcbot-rs/
|
||||
|
||||
## Out-of-tree Contributions
|
||||
[out-of-tree-contributions]: #out-of-tree-contributions
|
||||
|
|
14
RELEASES.md
14
RELEASES.md
|
@ -98,6 +98,20 @@ Compatibility Notes
|
|||
[`ptr::NonNull`]: https://doc.rust-lang.org/std/ptr/struct.NonNull.html
|
||||
|
||||
|
||||
Version 1.24.1 (2018-03-01)
|
||||
==========================
|
||||
|
||||
- [Do not abort when unwinding through FFI][48251]
|
||||
- [Emit UTF-16 files for linker arguments on Windows][48318]
|
||||
- [Make the error index generator work again][48308]
|
||||
- [Cargo will warn on Windows 7 if an update is needed][cargo/5069].
|
||||
|
||||
[48251]: https://github.com/rust-lang/rust/issues/48251
|
||||
[48308]: https://github.com/rust-lang/rust/issues/48308
|
||||
[48318]: https://github.com/rust-lang/rust/issues/48318
|
||||
[cargo/5069]: https://github.com/rust-lang/cargo/pull/5069
|
||||
|
||||
|
||||
Version 1.24.0 (2018-02-15)
|
||||
==========================
|
||||
|
||||
|
|
|
@ -202,7 +202,7 @@ dependencies = [
|
|||
"shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -558,7 +558,7 @@ dependencies = [
|
|||
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1543,7 +1543,7 @@ dependencies = [
|
|||
"rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1721,7 +1721,7 @@ dependencies = [
|
|||
"rustc_data_structures 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
"termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -2326,7 +2326,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2765,7 +2765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
|
||||
"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
|
||||
"checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1"
|
||||
"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#![cfg_attr(stage0, feature(i128_type))]
|
||||
#![feature(rand)]
|
||||
#![feature(repr_simd)]
|
||||
#![feature(slice_sort_by_cached_key)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate rand;
|
||||
|
|
|
@ -284,6 +284,17 @@ macro_rules! sort_expensive {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! sort_lexicographic {
|
||||
($f:ident, $name:ident, $gen:expr, $len:expr) => {
|
||||
#[bench]
|
||||
fn $name(b: &mut Bencher) {
|
||||
let v = $gen($len);
|
||||
b.iter(|| v.clone().$f(|x| x.to_string()));
|
||||
b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort!(sort, sort_small_ascending, gen_ascending, 10);
|
||||
sort!(sort, sort_small_descending, gen_descending, 10);
|
||||
sort!(sort, sort_small_random, gen_random, 10);
|
||||
|
@ -312,6 +323,10 @@ sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000);
|
|||
sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000);
|
||||
sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000);
|
||||
|
||||
sort_lexicographic!(sort_by_key, sort_by_key_lexicographic, gen_random, 10000);
|
||||
sort_lexicographic!(sort_unstable_by_key, sort_unstable_by_key_lexicographic, gen_random, 10000);
|
||||
sort_lexicographic!(sort_by_cached_key, sort_by_cached_key_lexicographic, gen_random, 10000);
|
||||
|
||||
macro_rules! reverse {
|
||||
($name:ident, $ty:ty, $f:expr) => {
|
||||
#[bench]
|
||||
|
|
|
@ -326,7 +326,7 @@
|
|||
//! sign := '+' | '-'
|
||||
//! width := count
|
||||
//! precision := count | '*'
|
||||
//! type := identifier | ''
|
||||
//! type := identifier | '?' | ''
|
||||
//! count := parameter | integer
|
||||
//! parameter := argument '$'
|
||||
//! ```
|
||||
|
@ -516,17 +516,17 @@ pub use core::fmt::rt;
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{Formatter, Result, Write};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{Octal, Binary};
|
||||
pub use core::fmt::{Binary, Octal};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{Display, Debug};
|
||||
pub use core::fmt::{Debug, Display};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{LowerHex, UpperHex, Pointer};
|
||||
pub use core::fmt::{LowerHex, Pointer, UpperHex};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{LowerExp, UpperExp};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::Error;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{ArgumentV1, Arguments, write};
|
||||
pub use core::fmt::{write, ArgumentV1, Arguments};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
|
||||
|
||||
|
@ -563,7 +563,8 @@ use string;
|
|||
pub fn format(args: Arguments) -> string::String {
|
||||
let capacity = args.estimated_capacity();
|
||||
let mut output = string::String::with_capacity(capacity);
|
||||
output.write_fmt(args)
|
||||
.expect("a formatting trait implementation returned an error");
|
||||
output
|
||||
.write_fmt(args)
|
||||
.expect("a formatting trait implementation returned an error");
|
||||
output
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ use core::mem::size_of;
|
|||
use core::mem;
|
||||
use core::ptr;
|
||||
use core::slice as core_slice;
|
||||
use core::{u8, u16, u32};
|
||||
|
||||
use borrow::{Borrow, BorrowMut, ToOwned};
|
||||
use boxed::Box;
|
||||
|
@ -1302,7 +1303,8 @@ impl<T> [T] {
|
|||
|
||||
/// Sorts the slice with a key extraction function.
|
||||
///
|
||||
/// This sort is stable (i.e. does not reorder equal elements) and `O(n log n)` worst-case.
|
||||
/// This sort is stable (i.e. does not reorder equal elements) and `O(m n log(m n))`
|
||||
/// worst-case, where the key function is `O(m)`.
|
||||
///
|
||||
/// When applicable, unstable sorting is preferred because it is generally faster than stable
|
||||
/// sorting and it doesn't allocate auxiliary memory.
|
||||
|
@ -1328,12 +1330,82 @@ impl<T> [T] {
|
|||
/// ```
|
||||
#[stable(feature = "slice_sort_by_key", since = "1.7.0")]
|
||||
#[inline]
|
||||
pub fn sort_by_key<B, F>(&mut self, mut f: F)
|
||||
where F: FnMut(&T) -> B, B: Ord
|
||||
pub fn sort_by_key<K, F>(&mut self, mut f: F)
|
||||
where F: FnMut(&T) -> K, K: Ord
|
||||
{
|
||||
merge_sort(self, |a, b| f(a).lt(&f(b)));
|
||||
}
|
||||
|
||||
/// Sorts the slice with a key extraction function.
|
||||
///
|
||||
/// During sorting, the key function is called only once per element.
|
||||
///
|
||||
/// This sort is stable (i.e. does not reorder equal elements) and `O(m n + n log n)`
|
||||
/// worst-case, where the key function is `O(m)`.
|
||||
///
|
||||
/// For simple key functions (e.g. functions that are property accesses or
|
||||
/// basic operations), [`sort_by_key`](#method.sort_by_key) is likely to be
|
||||
/// faster.
|
||||
///
|
||||
/// # Current implementation
|
||||
///
|
||||
/// The current algorithm is based on [pattern-defeating quicksort][pdqsort] by Orson Peters,
|
||||
/// which combines the fast average case of randomized quicksort with the fast worst case of
|
||||
/// heapsort, while achieving linear time on slices with certain patterns. It uses some
|
||||
/// randomization to avoid degenerate cases, but with a fixed seed to always provide
|
||||
/// deterministic behavior.
|
||||
///
|
||||
/// In the worst case, the algorithm allocates temporary storage in a `Vec<(K, usize)>` the
|
||||
/// length of the slice.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_sort_by_cached_key)]
|
||||
/// let mut v = [-5i32, 4, 32, -3, 2];
|
||||
///
|
||||
/// v.sort_by_cached_key(|k| k.to_string());
|
||||
/// assert!(v == [-3, -5, 2, 32, 4]);
|
||||
/// ```
|
||||
///
|
||||
/// [pdqsort]: https://github.com/orlp/pdqsort
|
||||
#[unstable(feature = "slice_sort_by_cached_key", issue = "34447")]
|
||||
#[inline]
|
||||
pub fn sort_by_cached_key<K, F>(&mut self, f: F)
|
||||
where F: FnMut(&T) -> K, K: Ord
|
||||
{
|
||||
// Helper macro for indexing our vector by the smallest possible type, to reduce allocation.
|
||||
macro_rules! sort_by_key {
|
||||
($t:ty, $slice:ident, $f:ident) => ({
|
||||
let mut indices: Vec<_> =
|
||||
$slice.iter().map($f).enumerate().map(|(i, k)| (k, i as $t)).collect();
|
||||
// The elements of `indices` are unique, as they are indexed, so any sort will be
|
||||
// stable with respect to the original slice. We use `sort_unstable` here because
|
||||
// it requires less memory allocation.
|
||||
indices.sort_unstable();
|
||||
for i in 0..$slice.len() {
|
||||
let mut index = indices[i].1;
|
||||
while (index as usize) < i {
|
||||
index = indices[index as usize].1;
|
||||
}
|
||||
indices[i].1 = index;
|
||||
$slice.swap(i, index as usize);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let sz_u8 = mem::size_of::<(K, u8)>();
|
||||
let sz_u16 = mem::size_of::<(K, u16)>();
|
||||
let sz_u32 = mem::size_of::<(K, u32)>();
|
||||
let sz_usize = mem::size_of::<(K, usize)>();
|
||||
|
||||
let len = self.len();
|
||||
if sz_u8 < sz_u16 && len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) }
|
||||
if sz_u16 < sz_u32 && len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) }
|
||||
if sz_u32 < sz_usize && len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) }
|
||||
sort_by_key!(usize, self, f)
|
||||
}
|
||||
|
||||
/// Sorts the slice, but may not preserve the order of equal elements.
|
||||
///
|
||||
/// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
|
||||
|
@ -1410,7 +1482,7 @@ impl<T> [T] {
|
|||
/// elements.
|
||||
///
|
||||
/// This sort is unstable (i.e. may reorder equal elements), in-place (i.e. does not allocate),
|
||||
/// and `O(n log n)` worst-case.
|
||||
/// and `O(m n log(m n))` worst-case, where the key function is `O(m)`.
|
||||
///
|
||||
/// # Current implementation
|
||||
///
|
||||
|
@ -1420,9 +1492,6 @@ impl<T> [T] {
|
|||
/// randomization to avoid degenerate cases, but with a fixed seed to always provide
|
||||
/// deterministic behavior.
|
||||
///
|
||||
/// It is typically faster than stable sorting, except in a few special cases, e.g. when the
|
||||
/// slice consists of several concatenated sorted sequences.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -1435,9 +1504,8 @@ impl<T> [T] {
|
|||
/// [pdqsort]: https://github.com/orlp/pdqsort
|
||||
#[stable(feature = "sort_unstable", since = "1.20.0")]
|
||||
#[inline]
|
||||
pub fn sort_unstable_by_key<B, F>(&mut self, f: F)
|
||||
where F: FnMut(&T) -> B,
|
||||
B: Ord
|
||||
pub fn sort_unstable_by_key<K, F>(&mut self, f: F)
|
||||
where F: FnMut(&T) -> K, K: Ord
|
||||
{
|
||||
core_slice::SliceExt::sort_unstable_by_key(self, f);
|
||||
}
|
||||
|
|
|
@ -2122,6 +2122,48 @@ impl str {
|
|||
unsafe { String::from_utf8_unchecked(buf) }
|
||||
}
|
||||
|
||||
/// Returns true if this `str` is entirely whitespace, and false otherwise.
|
||||
///
|
||||
/// 'Whitespace' is defined according to the terms of the Unicode Derived Core
|
||||
/// Property `White_Space`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// assert!(" \t ".is_whitespace());
|
||||
///
|
||||
/// // a non-breaking space
|
||||
/// assert!("\u{A0}".is_whitespace());
|
||||
///
|
||||
/// assert!(!" 越".is_whitespace());
|
||||
/// ```
|
||||
#[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
|
||||
#[inline]
|
||||
pub fn is_whitespace(&self) -> bool {
|
||||
UnicodeStr::is_whitespace(self)
|
||||
}
|
||||
|
||||
/// Returns true if this `str` is entirely alphanumeric, and false otherwise.
|
||||
///
|
||||
/// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories
|
||||
/// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// assert!("٣7৬Kو藏".is_alphanumeric());
|
||||
/// assert!(!"¾①".is_alphanumeric());
|
||||
/// ```
|
||||
#[stable(feature = "unicode_methods_on_intrinsics", since = "1.27.0")]
|
||||
#[inline]
|
||||
pub fn is_alphanumeric(&self) -> bool {
|
||||
UnicodeStr::is_alphanumeric(self)
|
||||
}
|
||||
|
||||
/// Checks if all characters in this string are within the ASCII range.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#![feature(pattern)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(rand)]
|
||||
#![feature(slice_sort_by_cached_key)]
|
||||
#![feature(splice)]
|
||||
#![feature(str_escape)]
|
||||
#![feature(string_retain)]
|
||||
|
|
|
@ -425,6 +425,14 @@ fn test_sort() {
|
|||
v.sort_by(|a, b| b.cmp(a));
|
||||
assert!(v.windows(2).all(|w| w[0] >= w[1]));
|
||||
|
||||
// Sort in lexicographic order.
|
||||
let mut v1 = orig.clone();
|
||||
let mut v2 = orig.clone();
|
||||
v1.sort_by_key(|x| x.to_string());
|
||||
v2.sort_by_cached_key(|x| x.to_string());
|
||||
assert!(v1.windows(2).all(|w| w[0].to_string() <= w[1].to_string()));
|
||||
assert!(v1 == v2);
|
||||
|
||||
// Sort with many pre-sorted runs.
|
||||
let mut v = orig.clone();
|
||||
v.sort();
|
||||
|
@ -477,7 +485,7 @@ fn test_sort_stability() {
|
|||
// the second item represents which occurrence of that
|
||||
// number this element is, i.e. the second elements
|
||||
// will occur in sorted order.
|
||||
let mut v: Vec<_> = (0..len)
|
||||
let mut orig: Vec<_> = (0..len)
|
||||
.map(|_| {
|
||||
let n = thread_rng().gen::<usize>() % 10;
|
||||
counts[n] += 1;
|
||||
|
@ -485,16 +493,21 @@ fn test_sort_stability() {
|
|||
})
|
||||
.collect();
|
||||
|
||||
// only sort on the first element, so an unstable sort
|
||||
let mut v = orig.clone();
|
||||
// Only sort on the first element, so an unstable sort
|
||||
// may mix up the counts.
|
||||
v.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
|
||||
|
||||
// this comparison includes the count (the second item
|
||||
// This comparison includes the count (the second item
|
||||
// of the tuple), so elements with equal first items
|
||||
// will need to be ordered with increasing
|
||||
// counts... i.e. exactly asserting that this sort is
|
||||
// stable.
|
||||
assert!(v.windows(2).all(|w| w[0] <= w[1]));
|
||||
|
||||
let mut v = orig.clone();
|
||||
v.sort_by_cached_key(|&(x, _)| x);
|
||||
assert!(v.windows(2).all(|w| w[0] <= w[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 263a703b10351d8930e48045b4fd09768991b867
|
||||
Subproject commit 2a2f6d96c8dc578d2474742f14c9bab0b36b0408
|
|
@ -13,7 +13,7 @@ pub use self::AnnNode::*;
|
|||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{CodeMap, Spanned};
|
||||
use syntax::parse::ParseSess;
|
||||
use syntax::parse::{token, ParseSess};
|
||||
use syntax::parse::lexer::comments;
|
||||
use syntax::print::pp::{self, Breaks};
|
||||
use syntax::print::pp::Breaks::{Consistent, Inconsistent};
|
||||
|
@ -1561,7 +1561,11 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
|
||||
self.s.word(&name.as_str())?;
|
||||
if token::is_raw_guess(ast::Ident::with_empty_ctxt(name)) {
|
||||
self.s.word(&format!("r#{}", name))?;
|
||||
} else {
|
||||
self.s.word(&name.as_str())?;
|
||||
}
|
||||
self.ann.post(self, NodeName(&name))
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,14 @@ use rustc::traits::{Obligation, SelectionContext};
|
|||
use util::nodemap::FxHashSet;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use errors::DiagnosticBuilder;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::print;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::ty::TyAdt;
|
||||
|
||||
use std::cell;
|
||||
use std::cmp::Ordering;
|
||||
|
@ -179,9 +181,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let actual = self.resolve_type_vars_if_possible(&rcvr_ty);
|
||||
let ty_string = self.ty_to_string(actual);
|
||||
let is_method = mode == Mode::MethodCall;
|
||||
let mut suggestion = None;
|
||||
let type_str = if is_method {
|
||||
"method"
|
||||
} else if actual.is_enum() {
|
||||
if let TyAdt(ref adt_def, _) = actual.sty {
|
||||
let names = adt_def.variants.iter().map(|s| &s.name);
|
||||
suggestion = find_best_match_for_name(names,
|
||||
&item_name.as_str(),
|
||||
None);
|
||||
}
|
||||
"variant"
|
||||
} else {
|
||||
match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
|
||||
|
@ -256,7 +265,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
err.emit();
|
||||
return;
|
||||
} else {
|
||||
struct_span_err!(
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0599,
|
||||
|
@ -264,7 +273,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
type_str,
|
||||
item_name,
|
||||
ty_string
|
||||
)
|
||||
);
|
||||
if let Some(suggestion) = suggestion {
|
||||
err.note(&format!("did you mean `{}::{}`?", type_str, suggestion));
|
||||
}
|
||||
err
|
||||
}
|
||||
} else {
|
||||
tcx.sess.diagnostic().struct_dummy()
|
||||
|
|
|
@ -1022,11 +1022,12 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
|
|||
.flat_map(|imp| cx.tcx.associated_items(*imp))
|
||||
.find(|item| item.name == item_name);
|
||||
if let Some(item) = item {
|
||||
if item.kind == ty::AssociatedKind::Method && is_val {
|
||||
Ok((ty.def, Some(format!("method.{}", item_name))))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
let out = match item.kind {
|
||||
ty::AssociatedKind::Method if is_val => "method",
|
||||
ty::AssociatedKind::Const if is_val => "associatedconstant",
|
||||
_ => return Err(())
|
||||
};
|
||||
Ok((ty.def, Some(format!("{}.{}", out, item_name))))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
|
@ -1139,9 +1140,6 @@ impl Clean<Attributes> for [ast::Attribute] {
|
|||
&link[..]
|
||||
}.trim();
|
||||
|
||||
// avoid resolving things (i.e. regular links) which aren't like paths
|
||||
// FIXME(Manishearth) given that most links have slashes in them might be worth
|
||||
// doing a check for slashes first
|
||||
if path_str.contains(|ch: char| !(ch.is_alphanumeric() ||
|
||||
ch == ':' || ch == '_')) {
|
||||
continue;
|
||||
|
|
|
@ -406,8 +406,6 @@ pub fn make_test(s: &str,
|
|||
|
||||
// FIXME(aburka): use a real parser to deal with multiline attributes
|
||||
fn partition_source(s: &str) -> (String, String) {
|
||||
use std_unicode::str::UnicodeStr;
|
||||
|
||||
let mut after_header = false;
|
||||
let mut before = String::new();
|
||||
let mut after = String::new();
|
||||
|
|
|
@ -40,7 +40,6 @@ pub mod attr;
|
|||
|
||||
pub mod common;
|
||||
pub mod classify;
|
||||
pub mod obsolete;
|
||||
|
||||
/// Info about a parsing session.
|
||||
pub struct ParseSess {
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of
|
||||
//! these syntaxes is tested by compile-test/obsolete-syntax.rs.
|
||||
//!
|
||||
//! Obsolete syntax that becomes too hard to parse can be removed.
|
||||
|
||||
use syntax_pos::Span;
|
||||
use parse::parser;
|
||||
|
||||
/// The specific types of unsupported syntax
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ObsoleteSyntax {
|
||||
// Nothing here at the moment
|
||||
}
|
||||
|
||||
pub trait ParserObsoleteMethods {
|
||||
/// Reports an obsolete syntax non-fatal error.
|
||||
fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax);
|
||||
fn report(&mut self,
|
||||
sp: Span,
|
||||
kind: ObsoleteSyntax,
|
||||
kind_str: &str,
|
||||
desc: &str,
|
||||
error: bool);
|
||||
}
|
||||
|
||||
impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
|
||||
/// Reports an obsolete syntax non-fatal error.
|
||||
#[allow(unused_variables)]
|
||||
#[allow(unreachable_code)]
|
||||
fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
|
||||
let (kind_str, desc, error) = match kind {
|
||||
// Nothing here at the moment
|
||||
};
|
||||
|
||||
self.report(sp, kind, kind_str, desc, error);
|
||||
}
|
||||
|
||||
fn report(&mut self,
|
||||
sp: Span,
|
||||
kind: ObsoleteSyntax,
|
||||
kind_str: &str,
|
||||
desc: &str,
|
||||
error: bool) {
|
||||
let mut err = if error {
|
||||
self.diagnostic().struct_span_err(sp, &format!("obsolete syntax: {}", kind_str))
|
||||
} else {
|
||||
self.diagnostic().struct_span_warn(sp, &format!("obsolete syntax: {}", kind_str))
|
||||
};
|
||||
|
||||
if !self.obsolete_set.contains(&kind) &&
|
||||
(error || self.sess.span_diagnostic.flags.can_emit_warnings) {
|
||||
err.note(desc);
|
||||
self.obsolete_set.insert(kind);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
|
@ -48,7 +48,6 @@ use parse::{self, classify, token};
|
|||
use parse::common::SeqSep;
|
||||
use parse::lexer::TokenAndSpan;
|
||||
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
|
||||
use parse::obsolete::ObsoleteSyntax;
|
||||
use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership};
|
||||
use util::parser::{AssocOp, Fixity};
|
||||
use print::pprust;
|
||||
|
@ -59,7 +58,6 @@ use symbol::{Symbol, keywords};
|
|||
use util::ThinVec;
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::HashSet;
|
||||
use std::mem;
|
||||
use std::path::{self, Path, PathBuf};
|
||||
use std::slice;
|
||||
|
@ -229,9 +227,6 @@ pub struct Parser<'a> {
|
|||
/// the previous token kind
|
||||
prev_token_kind: PrevTokenKind,
|
||||
pub restrictions: Restrictions,
|
||||
/// The set of seen errors about obsolete syntax. Used to suppress
|
||||
/// extra detail when the same error is seen twice
|
||||
pub obsolete_set: HashSet<ObsoleteSyntax>,
|
||||
/// Used to determine the path to externally loaded source files
|
||||
pub directory: Directory,
|
||||
/// Whether to parse sub-modules in other files.
|
||||
|
@ -555,7 +550,6 @@ impl<'a> Parser<'a> {
|
|||
meta_var_span: None,
|
||||
prev_token_kind: PrevTokenKind::Other,
|
||||
restrictions: Restrictions::empty(),
|
||||
obsolete_set: HashSet::new(),
|
||||
recurse_into_file_modules,
|
||||
directory: Directory {
|
||||
path: PathBuf::new(),
|
||||
|
|
|
@ -142,6 +142,13 @@ pub fn is_path_segment_keyword(id: ast::Ident) -> bool {
|
|||
id.name == keywords::DollarCrate.name()
|
||||
}
|
||||
|
||||
// We see this identifier in a normal identifier position, like variable name or a type.
|
||||
// How was it written originally? Did it use the raw form? Let's try to guess.
|
||||
pub fn is_raw_guess(ident: ast::Ident) -> bool {
|
||||
ident.name != keywords::Invalid.name() &&
|
||||
is_reserved_ident(ident) && !is_path_segment_keyword(ident)
|
||||
}
|
||||
|
||||
// Returns true for reserved identifiers used internally for elided lifetimes,
|
||||
// unnamed method parameters, crate root module, error recovery etc.
|
||||
pub fn is_special_ident(id: ast::Ident) -> bool {
|
||||
|
@ -236,7 +243,7 @@ impl Token {
|
|||
|
||||
/// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
|
||||
pub fn from_ast_ident(ident: ast::Ident) -> Token {
|
||||
Ident(ident, is_reserved_ident(ident) && !is_path_segment_keyword(ident))
|
||||
Ident(ident, is_raw_guess(ident))
|
||||
}
|
||||
|
||||
/// Returns `true` if the token starts with '>'.
|
||||
|
|
|
@ -2373,7 +2373,11 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
|
||||
self.s.word(&ident.name.as_str())?;
|
||||
if token::is_raw_guess(ident) {
|
||||
self.s.word(&format!("r#{}", ident))?;
|
||||
} else {
|
||||
self.s.word(&ident.name.as_str())?;
|
||||
}
|
||||
self.ann.post(self, NodeIdent(&ident))
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-pretty
|
||||
|
||||
#![feature(raw_identifiers)]
|
||||
|
||||
use std::mem;
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-pretty
|
||||
|
||||
#![feature(raw_identifiers)]
|
||||
|
||||
fn r#fn(r#match: u32) -> u32 {
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-pretty
|
||||
|
||||
#![feature(raw_identifiers)]
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-pretty
|
||||
|
||||
#![feature(decl_macro)]
|
||||
#![feature(raw_identifiers)]
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has foo/index.html '//a[@href="../foo/foo/constant.FIRSTCONST.html"]' 'foo::FIRSTCONST'
|
||||
// @has foo/index.html '//a[@href="../foo/struct.Bar.html#associatedconstant.CONST"]' 'Bar::CONST'
|
||||
|
||||
//! We have here [`foo::FIRSTCONST`] and [`Bar::CONST`].
|
||||
|
||||
pub mod foo {
|
||||
pub const FIRSTCONST: u32 = 42;
|
||||
}
|
||||
|
||||
pub struct Bar;
|
||||
|
||||
impl Bar {
|
||||
pub const CONST: u32 = 42;
|
||||
}
|
|
@ -5,6 +5,8 @@ LL | pub enum SomeEnum {
|
|||
| ----------------- variant `A` not found here
|
||||
LL | B = SomeEnum::A,
|
||||
| ^^^^^^^^^^^ variant not found in `SomeEnum`
|
||||
|
|
||||
= note: did you mean `variant::B`?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ LL | enum Foo {
|
|||
...
|
||||
LL | Foo::Baz(..) => (),
|
||||
| ^^^^^^^^^^^^ variant not found in `Foo`
|
||||
|
|
||||
= note: did you mean `variant::Bar`?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
Loading…
Reference in New Issue