Auto merge of #52937 - pietroalbini:rollup, r=pietroalbini

Rollup of 30 pull requests

Successful merges:

 - #52340 (Document From trait implementations for OsStr, OsString, CString, and CStr)
 - #52628 (Cleanup some rustdoc code)
 - #52732 (Remove unstable and deprecated APIs)
 - #52745 (Update clippy to latest master)
 - #52771 (Clarify thread::park semantics)
 - #52778 (Improve readability of serialize.rs)
 - #52810 ([NLL] Don't make "fake" match variables mutable)
 - #52821 (pretty print for std::collections::vecdeque)
 - #52822 (Fix From<LocalWaker>)
 - #52824 (Fix -Wpessimizing-move warnings in rustllvm/PassWrapper)
 - #52825 (Make sure #47772 does not regress)
 - #52831 (remove references to AUTHORS.txt file)
 - #52842 (update comment)
 - #52846 (Add timeout to use of `curl` in bootstrap.py.)
 - #52851 (Make the tool_lints actually usable)
 - #52853 (Improve bootstrap help on stages)
 - #52859 (Use Vec::extend in SmallVec::extend when applicable)
 - #52861 (Add targets for HermitCore (https://hermitcore.org) to the Rust compiler and port libstd to it.)
 - #52867 (releases.md: fix 2 typos)
 - #52870 (Implement Unpin for FutureObj and LocalFutureObj)
 - #52876 (run-pass/const-endianness: negate before to_le())
 - #52878 (Fix wrong issue number in the test name)
 - #52883 (Include lifetime in mutability suggestion in NLL messages)
 - #52888 (Use suggestions for shell format arguments)
 - #52904 (NLL: sort diagnostics by span)
 - #52905 (Fix a typo in unsize.rs)
 - #52907 (NLL: On "cannot move out of type" error, print original before rewrite)
 - #52914 (Only run the sparc-abi test on sparc)
 - #52918 (Backport 1.27.2 release notes)
 - #52929 (Update compatibility note for 1.28.0 to be correct)

Failed merges:

r? @ghost
This commit is contained in:
bors 2018-08-01 08:41:36 +00:00
commit 8c069ceba8
120 changed files with 2125 additions and 1749 deletions

View File

@ -10,8 +10,8 @@ Copyrights in the Rust project are retained by their contributors. No
copyright assignment is required to contribute to the Rust project.
Some files include explicit copyright notices and/or license notices.
For full authorship information, see AUTHORS.txt and the version control
history.
For full authorship information, see the version control history or
https://thanks.rust-lang.org
Except as otherwise noted (below and/or in individual files), Rust is
licensed under the Apache License, Version 2.0 <LICENSE-APACHE> or

View File

@ -94,9 +94,9 @@ Misc
Compatibility Notes
-------------------
- [Rust will no longer consider trait objects with duplicated constraints to
have implementations.][51276] For example the below code will now fail
to compile.
- [Rust will consider trait objects with duplicated constraints to be the same
type as without the duplicated constraint.][51276] For example the below code will
now fail to compile.
```rust
trait Trait {}
@ -160,6 +160,17 @@ Compatibility Notes
[`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2
[`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2
Version 1.27.2 (2018-07-20)
===========================
Compatibility Notes
-------------------
- The borrow checker was fixed to avoid potential unsoundness when using
match ergonomics: [#52213][52213].
[52213]: https://github.com/rust-lang/rust/issues/52213
Version 1.27.1 (2018-07-10)
===========================
@ -190,7 +201,7 @@ Version 1.27.0 (2018-06-21)
Language
--------
- [Removed 'proc' from the reserved keywords list.][49699] This allows `proc` to
be used as an identifer.
be used as an identifier.
- [The dyn syntax is now available.][49968] This syntax is equivalent to the
bare `Trait` syntax, and should make it clearer when being used in tandem with
`impl Trait`. Since it is equivalent to the following syntax:
@ -4795,7 +4806,7 @@ Language
--------
* Patterns with `ref mut` now correctly invoke [`DerefMut`] when
matching against dereferencable values.
matching against dereferenceable values.
Libraries
---------

View File

@ -2612,18 +2612,9 @@ dependencies = [
"rustc_lsan 0.0.0",
"rustc_msan 0.0.0",
"rustc_tsan 0.0.0",
"std_unicode 0.0.0",
"unwind 0.0.0",
]
[[package]]
name = "std_unicode"
version = "0.0.0"
dependencies = [
"compiler_builtins 0.0.0",
"core 0.0.0",
]
[[package]]
name = "string_cache"
version = "0.7.3"

View File

@ -88,7 +88,10 @@ def _download(path, url, probably_big, verbose, exception):
option = "-#"
else:
option = "-s"
run(["curl", option, "--retry", "3", "-Sf", "-o", path, url],
run(["curl", option,
"-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
"--connect-timeout", "30", # timeout if cannot connect within 30 seconds
"--retry", "3", "-Sf", "-o", path, url],
verbose=verbose,
exception=exception)

View File

@ -157,7 +157,6 @@ pub fn std_cargo(builder: &Builder,
cargo.arg("--features").arg("c mem")
.args(&["-p", "alloc"])
.args(&["-p", "compiler_builtins"])
.args(&["-p", "std_unicode"])
.arg("--manifest-path")
.arg(builder.src.join("src/rustc/compiler_builtins_shim/Cargo.toml"));
} else {

View File

@ -856,7 +856,6 @@ impl Step for Src {
"src/librustc_msan",
"src/librustc_tsan",
"src/libstd",
"src/libstd_unicode",
"src/libunwind",
"src/rustc/compiler_builtins_shim",
"src/rustc/libc_shim",

View File

@ -489,7 +489,7 @@ impl Step for Std {
// Keep a whitelist so we do not build internal stdlib crates, these will be
// build by the rustc step later if enabled.
cargo.arg("--no-deps");
for krate in &["alloc", "core", "std", "std_unicode"] {
for krate in &["alloc", "core", "std"] {
cargo.arg("-p").arg(krate);
// Create all crate output directories first to make sure rustdoc uses
// relative links.

View File

@ -121,7 +121,10 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
opts.optmulti("", "exclude", "build paths to exclude", "PATH");
opts.optopt("", "on-fail", "command to run on failure", "CMD");
opts.optflag("", "dry-run", "dry run; don't build anything");
opts.optopt("", "stage", "stage to build", "N");
opts.optopt("", "stage",
"stage to build (indicates compiler to use/test, e.g. stage 0 uses the \
bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)",
"N");
opts.optmulti("", "keep-stage", "stage(s) to keep without recompiling", "N");
opts.optopt("", "src", "path to the root of the rust checkout", "DIR");
opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS");
@ -258,7 +261,7 @@ Arguments:
./x.py build --stage 1 src/libtest
This will first build everything once (like --stage 0 without further
This will first build everything once (like `--stage 0` without further
arguments would), and then use the compiler built in stage 0 to build
src/libtest and its dependencies.
Once this is done, build/$ARCH/stage1 contains a usable compiler.",
@ -290,10 +293,14 @@ Arguments:
./x.py test src/test/run-pass
./x.py test src/libstd --test-args hash_map
./x.py test src/libstd --stage 0
./x.py test src/libstd --stage 0 --no-doc
./x.py test src/test/ui --bless
./x.py test src/test/ui --compare-mode nll
Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`;
just like `build src/libstd --stage N` it tests the compiler produced by the previous
stage.
If no arguments are passed then the complete artifacts for that stage are
compiled and tested.

View File

@ -119,7 +119,7 @@ See <\fBhttps://github.com/rust\-lang/rust/issues\fR>
for issues.
.SH "AUTHOR"
See \fIAUTHORS.txt\fR in the Rust source distribution.
See the version control history or <\fBhttps://thanks.rust\-lang.org\fR>
.SH "COPYRIGHT"
This work is dual\[hy]licensed under Apache\ 2.0 and MIT terms.

View File

@ -47,6 +47,7 @@ TYPE_KIND_PTR = 15
TYPE_KIND_FIXED_SIZE_VEC = 16
TYPE_KIND_REGULAR_UNION = 17
TYPE_KIND_OS_STRING = 18
TYPE_KIND_STD_VECDEQUE = 19
ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
@ -62,6 +63,14 @@ STD_VEC_FIELD_NAME_BUF = "buf"
STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF,
STD_VEC_FIELD_NAME_LENGTH]
# std::collections::VecDeque<> related constants
STD_VECDEQUE_FIELD_NAME_TAIL = "tail"
STD_VECDEQUE_FIELD_NAME_HEAD = "head"
STD_VECDEQUE_FIELD_NAME_BUF = "buf"
STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL,
STD_VECDEQUE_FIELD_NAME_HEAD,
STD_VECDEQUE_FIELD_NAME_BUF]
# std::String related constants
STD_STRING_FIELD_NAMES = ["vec"]
@ -161,6 +170,11 @@ class Type(object):
self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
return TYPE_KIND_STD_VEC
# STD COLLECTION VECDEQUE
if (unqualified_type_name.startswith("VecDeque<") and
self.__conforms_to_field_layout(STD_VECDEQUE_FIELD_NAMES)):
return TYPE_KIND_STD_VECDEQUE
# STD STRING
if (unqualified_type_name.startswith("String") and
self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
@ -325,6 +339,25 @@ def extract_length_ptr_and_cap_from_std_vec(vec_val):
assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
return (length, data_ptr, capacity)
def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val):
assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VECDEQUE
tail_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_TAIL)
head_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_HEAD)
buf_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_BUF)
tail = vec_val.get_child_at_index(tail_field_index).as_integer()
head = vec_val.get_child_at_index(head_field_index).as_integer()
buf = vec_val.get_child_at_index(buf_field_index)
vec_ptr_val = buf.get_child_at_index(0)
capacity = buf.get_child_at_index(1).as_integer()
unique_ptr_val = vec_ptr_val.get_child_at_index(0)
data_ptr = unique_ptr_val.get_child_at_index(0)
assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
return (tail, head, data_ptr, capacity)
def extract_length_and_ptr_from_slice(slice_val):
assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)

View File

@ -124,6 +124,9 @@ def rust_pretty_printer_lookup_function(gdb_val):
if type_kind == rustpp.TYPE_KIND_STD_VEC:
return RustStdVecPrinter(val)
if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE:
return RustStdVecDequePrinter(val)
if type_kind == rustpp.TYPE_KIND_STD_STRING:
return RustStdStringPrinter(val)
@ -274,6 +277,28 @@ class RustStdVecPrinter(object):
yield (str(index), (gdb_ptr + index).dereference())
class RustStdVecDequePrinter(object):
def __init__(self, val):
self.__val = val
@staticmethod
def display_hint():
return "array"
def to_string(self):
(tail, head, data_ptr, cap) = \
rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
return (self.__val.type.get_unqualified_type_name() +
("(len: %i, cap: %i)" % (head - tail, cap)))
def children(self):
(tail, head, data_ptr, cap) = \
rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
gdb_ptr = data_ptr.get_wrapped_value()
for index in xrange(tail, head):
yield (str(index), (gdb_ptr + index).dereference())
class RustStdStringPrinter(object):
def __init__(self, val):
self.__val = val

View File

@ -174,7 +174,10 @@ mod platform {
}
}
#[cfg(any(target_os = "android", target_os = "redox", target_os = "solaris"))]
#[cfg(any(target_os = "android",
target_os = "hermit",
target_os = "redox",
target_os = "solaris"))]
#[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
// On android we currently target API level 9 which unfortunately
@ -197,7 +200,10 @@ mod platform {
libc::memalign(layout.align(), layout.size()) as *mut u8
}
#[cfg(not(any(target_os = "android", target_os = "redox", target_os = "solaris")))]
#[cfg(not(any(target_os = "android",
target_os = "hermit",
target_os = "redox",
target_os = "solaris")))]
#[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
let mut out = ptr::null_mut();

View File

@ -11,135 +11,8 @@
//! UTF-8 and UTF-16 decoding iterators
use fmt;
use iter::FusedIterator;
use super::from_u32_unchecked;
/// An iterator over an iterator of bytes of the characters the bytes represent
/// as UTF-8
#[unstable(feature = "decode_utf8", issue = "33906")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[derive(Clone, Debug)]
#[allow(deprecated)]
pub struct DecodeUtf8<I: Iterator<Item = u8>>(::iter::Peekable<I>);
/// Decodes an `Iterator` of bytes as UTF-8.
#[unstable(feature = "decode_utf8", issue = "33906")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[allow(deprecated)]
#[inline]
pub fn decode_utf8<I: IntoIterator<Item = u8>>(i: I) -> DecodeUtf8<I::IntoIter> {
DecodeUtf8(i.into_iter().peekable())
}
/// `<DecodeUtf8 as Iterator>::next` returns this for an invalid input sequence.
#[unstable(feature = "decode_utf8", issue = "33906")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[derive(PartialEq, Eq, Debug)]
#[allow(deprecated)]
pub struct InvalidSequence(());
#[unstable(feature = "decode_utf8", issue = "33906")]
#[allow(deprecated)]
impl<I: Iterator<Item = u8>> Iterator for DecodeUtf8<I> {
type Item = Result<char, InvalidSequence>;
#[inline]
fn next(&mut self) -> Option<Result<char, InvalidSequence>> {
self.0.next().map(|first_byte| {
// Emit InvalidSequence according to
// Unicode §5.22 Best Practice for U+FFFD Substitution
// http://www.unicode.org/versions/Unicode9.0.0/ch05.pdf#G40630
// Roughly: consume at least one byte,
// then validate one byte at a time and stop before the first unexpected byte
// (which might be the valid start of the next byte sequence).
let mut code_point;
macro_rules! first_byte {
($mask: expr) => {
code_point = u32::from(first_byte & $mask)
}
}
macro_rules! continuation_byte {
() => { continuation_byte!(0x80..=0xBF) };
($range: pat) => {
match self.0.peek() {
Some(&byte @ $range) => {
code_point = (code_point << 6) | u32::from(byte & 0b0011_1111);
self.0.next();
}
_ => return Err(InvalidSequence(()))
}
}
}
match first_byte {
0x00..=0x7F => {
first_byte!(0b1111_1111);
}
0xC2..=0xDF => {
first_byte!(0b0001_1111);
continuation_byte!();
}
0xE0 => {
first_byte!(0b0000_1111);
continuation_byte!(0xA0..=0xBF); // 0x80..=0x9F here are overlong
continuation_byte!();
}
0xE1..=0xEC | 0xEE..=0xEF => {
first_byte!(0b0000_1111);
continuation_byte!();
continuation_byte!();
}
0xED => {
first_byte!(0b0000_1111);
continuation_byte!(0x80..=0x9F); // 0xA0..0xBF here are surrogates
continuation_byte!();
}
0xF0 => {
first_byte!(0b0000_0111);
continuation_byte!(0x90..=0xBF); // 0x80..0x8F here are overlong
continuation_byte!();
continuation_byte!();
}
0xF1..=0xF3 => {
first_byte!(0b0000_0111);
continuation_byte!();
continuation_byte!();
continuation_byte!();
}
0xF4 => {
first_byte!(0b0000_0111);
continuation_byte!(0x80..=0x8F); // 0x90..0xBF here are beyond char::MAX
continuation_byte!();
continuation_byte!();
}
_ => return Err(InvalidSequence(())) // Illegal first byte, overlong, or beyond MAX
}
unsafe {
Ok(from_u32_unchecked(code_point))
}
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, upper) = self.0.size_hint();
// A code point is at most 4 bytes long.
let min_code_points = lower / 4;
(min_code_points, upper)
}
}
#[unstable(feature = "decode_utf8", issue = "33906")]
#[allow(deprecated)]
impl<I: FusedIterator<Item = u8>> FusedIterator for DecodeUtf8<I> {}
/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
#[stable(feature = "decode_utf16", since = "1.9.0")]
#[derive(Clone, Debug)]

View File

@ -50,11 +50,6 @@ pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
pub use unicode::tables::UNICODE_VERSION;
#[unstable(feature = "unicode_version", issue = "49726")]
pub use unicode::version::UnicodeVersion;
#[unstable(feature = "decode_utf8", issue = "33906")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[allow(deprecated)]
pub use self::decode::{decode_utf8, DecodeUtf8, InvalidSequence};
use fmt::{self, Write};
use iter::FusedIterator;

View File

@ -36,6 +36,8 @@ pub struct LocalFutureObj<'a, T> {
_marker: PhantomData<&'a ()>,
}
impl<'a, T> Unpin for LocalFutureObj<'a, T> {}
impl<'a, T> LocalFutureObj<'a, T> {
/// Create a `LocalFutureObj` from a custom trait object representation.
#[inline]
@ -104,6 +106,7 @@ impl<'a, T> Drop for LocalFutureObj<'a, T> {
/// information #44874)
pub struct FutureObj<'a, T>(LocalFutureObj<'a, T>);
impl<'a, T> Unpin for FutureObj<'a, T> {}
unsafe impl<'a, T> Send for FutureObj<'a, T> {}
impl<'a, T> FutureObj<'a, T> {

View File

@ -13,7 +13,7 @@ use marker::Unsize;
/// Trait that indicates that this is a pointer or a wrapper for one,
/// where unsizing can be performed on the pointee.
///
/// See the [DST coercion RfC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce]
/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce]
/// for more details.
///
/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize<U>`

View File

@ -680,46 +680,6 @@ impl<T: ?Sized> *const T {
}
}
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// If the address different between the two pointers ia not a multiple of
/// `mem::size_of::<T>()` then the result of the division is rounded towards
/// zero.
///
/// This function returns `None` if `T` is a zero-sized type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(offset_to)]
/// #![allow(deprecated)]
///
/// fn main() {
/// let a = [0; 5];
/// let ptr1: *const i32 = &a[1];
/// let ptr2: *const i32 = &a[3];
/// assert_eq!(ptr1.offset_to(ptr2), Some(2));
/// assert_eq!(ptr2.offset_to(ptr1), Some(-2));
/// assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
/// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
/// }
/// ```
#[unstable(feature = "offset_to", issue = "41079")]
#[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \
opposite argument order. If you're writing unsafe code, consider `offset_from`.")]
#[inline]
pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
let size = mem::size_of::<T>();
if size == 0 {
None
} else {
Some(other.wrapping_offset_from(self))
}
}
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
@ -1464,46 +1424,6 @@ impl<T: ?Sized> *mut T {
}
}
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// If the address different between the two pointers ia not a multiple of
/// `mem::size_of::<T>()` then the result of the division is rounded towards
/// zero.
///
/// This function returns `None` if `T` is a zero-sized type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(offset_to)]
/// #![allow(deprecated)]
///
/// fn main() {
/// let mut a = [0; 5];
/// let ptr1: *mut i32 = &mut a[1];
/// let ptr2: *mut i32 = &mut a[3];
/// assert_eq!(ptr1.offset_to(ptr2), Some(2));
/// assert_eq!(ptr2.offset_to(ptr1), Some(-2));
/// assert_eq!(unsafe { ptr1.offset(2) }, ptr2);
/// assert_eq!(unsafe { ptr2.offset(-2) }, ptr1);
/// }
/// ```
#[unstable(feature = "offset_to", issue = "41079")]
#[rustc_deprecated(since = "1.27.0", reason = "Replaced by `wrapping_offset_from`, with the \
opposite argument order. If you're writing unsafe code, consider `offset_from`.")]
#[inline]
pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
let size = mem::size_of::<T>();
if size == 0 {
None
} else {
Some(other.wrapping_offset_from(self))
}
}
/// Calculates the distance between two pointers. The returned value is in
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///

View File

@ -42,7 +42,7 @@ impl Waker {
/// `Arc` type and the safe `Wake` trait.
#[inline]
pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
Waker { inner: inner }
Waker { inner }
}
/// Wake up the task associated with this `Waker`.
@ -120,7 +120,7 @@ impl LocalWaker {
/// on the current thread.
#[inline]
pub unsafe fn new(inner: NonNull<dyn UnsafeWake>) -> Self {
LocalWaker { inner: inner }
LocalWaker { inner }
}
/// Wake up the task associated with this `LocalWaker`.
@ -159,7 +159,9 @@ impl LocalWaker {
impl From<LocalWaker> for Waker {
#[inline]
fn from(local_waker: LocalWaker) -> Self {
Waker { inner: local_waker.inner }
let inner = local_waker.inner;
mem::forget(local_waker);
Waker { inner }
}
}

View File

@ -363,54 +363,3 @@ fn eu_iterator_specializations() {
check('\u{12340}');
check('\u{10FFFF}');
}
#[test]
#[allow(deprecated)]
fn test_decode_utf8() {
macro_rules! assert_decode_utf8 {
($input_bytes: expr, $expected_str: expr) => {
let input_bytes: &[u8] = &$input_bytes;
let s = char::decode_utf8(input_bytes.iter().cloned())
.map(|r_b| r_b.unwrap_or('\u{FFFD}'))
.collect::<String>();
assert_eq!(s, $expected_str,
"input bytes: {:?}, expected str: {:?}, result: {:?}",
input_bytes, $expected_str, s);
assert_eq!(String::from_utf8_lossy(&$input_bytes), $expected_str);
}
}
assert_decode_utf8!([], "");
assert_decode_utf8!([0x41], "A");
assert_decode_utf8!([0xC1, 0x81], "<EFBFBD><EFBFBD>");
assert_decode_utf8!([0xE2, 0x99, 0xA5], "");
assert_decode_utf8!([0xE2, 0x99, 0xA5, 0x41], "♥A");
assert_decode_utf8!([0xE2, 0x99], "<EFBFBD>");
assert_decode_utf8!([0xE2, 0x99, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xC0], "<EFBFBD>");
assert_decode_utf8!([0xC0, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0x80], "<EFBFBD>");
assert_decode_utf8!([0x80, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xFE], "<EFBFBD>");
assert_decode_utf8!([0xFE, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xFF], "<EFBFBD>");
assert_decode_utf8!([0xFF, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xC0, 0x80], "<EFBFBD><EFBFBD>");
// Surrogates
assert_decode_utf8!([0xED, 0x9F, 0xBF], "\u{D7FF}");
assert_decode_utf8!([0xED, 0xA0, 0x80], "<EFBFBD><EFBFBD><EFBFBD>");
assert_decode_utf8!([0xED, 0xBF, 0x80], "<EFBFBD><EFBFBD><EFBFBD>");
assert_decode_utf8!([0xEE, 0x80, 0x80], "\u{E000}");
// char::MAX
assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0xBF], "\u{10FFFF}");
assert_decode_utf8!([0xF4, 0x8F, 0xBF, 0x41], "<EFBFBD>A");
assert_decode_utf8!([0xF4, 0x90, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
// 5 and 6 bytes sequence
// Part of the original design of UTF-8,
// but invalid now that UTF-8 is artificially restricted to match the range of UTF-16.
assert_decode_utf8!([0xF8, 0x80, 0x80, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
assert_decode_utf8!([0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}

View File

@ -42,7 +42,7 @@ use util::nodemap::FxHashMap;
use std::default::Default as StdDefault;
use syntax::ast;
use syntax::edition;
use syntax_pos::{MultiSpan, Span};
use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString};
use errors::DiagnosticBuilder;
use hir;
use hir::def_id::LOCAL_CRATE;
@ -133,6 +133,12 @@ pub enum CheckLintNameResult<'a> {
/// The lint is either renamed or removed. This is the warning
/// message, and an optional new name (`None` if removed).
Warning(String, Option<String>),
/// The lint is from a tool. If the Option is None, then either
/// the lint does not exist in the tool or the code was not
/// compiled with the tool and therefore the lint was never
/// added to the `LintStore`. Otherwise the `LintId` will be
/// returned as if it where a rustc lint.
Tool(Option<&'a [LintId]>),
}
impl LintStore {
@ -288,7 +294,7 @@ impl LintStore {
sess: &Session,
lint_name: &str,
level: Level) {
let db = match self.check_lint_name(lint_name) {
let db = match self.check_lint_name(lint_name, None) {
CheckLintNameResult::Ok(_) => None,
CheckLintNameResult::Warning(ref msg, _) => {
Some(sess.struct_warn(msg))
@ -296,6 +302,7 @@ impl LintStore {
CheckLintNameResult::NoLint => {
Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
}
CheckLintNameResult::Tool(_) => unreachable!(),
};
if let Some(mut db) = db {
@ -319,26 +326,41 @@ impl LintStore {
/// it emits non-fatal warnings and there are *two* lint passes that
/// inspect attributes, this is only run from the late pass to avoid
/// printing duplicate warnings.
pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult {
match self.by_name.get(lint_name) {
Some(&Renamed(ref new_name, _)) => {
CheckLintNameResult::Warning(
format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
Some(new_name.to_owned())
)
},
Some(&Removed(ref reason)) => {
CheckLintNameResult::Warning(
format!("lint `{}` has been removed: `{}`", lint_name, reason),
None
)
},
None => {
match self.lint_groups.get(lint_name) {
None => CheckLintNameResult::NoLint,
Some(ids) => CheckLintNameResult::Ok(&ids.0),
}
pub fn check_lint_name(
&self,
lint_name: &str,
tool_name: Option<LocalInternedString>,
) -> CheckLintNameResult {
let complete_name = if let Some(tool_name) = tool_name {
format!("{}::{}", tool_name, lint_name)
} else {
lint_name.to_string()
};
if let Some(_) = tool_name {
match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) {
None => return CheckLintNameResult::Tool(None),
Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)),
},
Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))),
// If the lint was registered as removed or renamed by the lint tool, we don't need
// to treat tool_lints and rustc lints different and can use the code below.
_ => {}
}
}
match self.by_name.get(&complete_name) {
Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
Some(new_name.to_owned()),
),
Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
format!("lint `{}` has been removed: `{}`", lint_name, reason),
None,
),
None => match self.lint_groups.get(&*complete_name) {
None => CheckLintNameResult::NoLint,
Some(ids) => CheckLintNameResult::Ok(&ids.0),
},
Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
}
}

View File

@ -227,8 +227,10 @@ impl<'a> LintLevelsBuilder<'a> {
continue
}
};
if let Some(lint_tool) = word.is_scoped() {
if !self.sess.features_untracked().tool_lints {
let tool_name = if let Some(lint_tool) = word.is_scoped() {
let gate_feature = !self.sess.features_untracked().tool_lints;
let known_tool = attr::is_known_lint_tool(lint_tool);
if gate_feature {
feature_gate::emit_feature_err(&sess.parse_sess,
"tool_lints",
word.span,
@ -236,8 +238,7 @@ impl<'a> LintLevelsBuilder<'a> {
&format!("scoped lint `{}` is experimental",
word.ident));
}
if !attr::is_known_lint_tool(lint_tool) {
if !known_tool {
span_err!(
sess,
lint_tool.span,
@ -247,10 +248,16 @@ impl<'a> LintLevelsBuilder<'a> {
);
}
continue
}
if gate_feature || !known_tool {
continue
}
Some(lint_tool.as_str())
} else {
None
};
let name = word.name();
match store.check_lint_name(&name.as_str()) {
match store.check_lint_name(&name.as_str(), tool_name) {
CheckLintNameResult::Ok(ids) => {
let src = LintSource::Node(name, li.span);
for id in ids {
@ -258,6 +265,20 @@ impl<'a> LintLevelsBuilder<'a> {
}
}
CheckLintNameResult::Tool(result) => {
if let Some(ids) = result {
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
let src = LintSource::Node(Symbol::intern(complete_name), li.span);
for id in ids {
specs.insert(*id, (level, src));
}
}
// If Tool(None) is returned, then either the lint does not exist in the
// tool or the code was not compiled with the tool and therefore the lint
// was never added to the `LintStore`. To detect this is the responsibility
// of the lint tool.
}
_ if !self.warn_about_weird_lints => {}
CheckLintNameResult::Warning(msg, renamed) => {
@ -298,7 +319,7 @@ impl<'a> LintLevelsBuilder<'a> {
if name.as_str().chars().any(|c| c.is_uppercase()) {
let name_lower = name.as_str().to_lowercase().to_string();
if let CheckLintNameResult::NoLint =
store.check_lint_name(&name_lower) {
store.check_lint_name(&name_lower, tool_name) {
db.emit();
} else {
db.span_suggestion_with_applicability(

View File

@ -139,6 +139,26 @@ macro_rules! declare_lint {
);
}
#[macro_export]
macro_rules! declare_tool_lint {
($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
);
($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
report_in_external_macro: $rep: expr) => (
declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
);
($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: &concat!(stringify!($tool), "::", stringify!($NAME)),
default_level: $crate::lint::$Level,
desc: $desc,
edition_lint_opts: None,
report_in_external_macro: $external,
};
);
}
/// Declare a static `LintArray` and return it as an expression.
#[macro_export]
macro_rules! lint_array {

View File

@ -169,10 +169,18 @@ impl<A: Array> FromIterator<A::Element> for SmallVec<A> {
impl<A: Array> Extend<A::Element> for SmallVec<A> {
fn extend<I: IntoIterator<Item=A::Element>>(&mut self, iter: I) {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);
for el in iter {
self.push(el);
if self.is_array() {
let iter = iter.into_iter();
self.reserve(iter.size_hint().0);
for el in iter {
self.push(el);
}
} else {
match self.0 {
AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
_ => unreachable!()
}
}
}
}
@ -213,3 +221,119 @@ impl<A> Decodable for SmallVec<A>
})
}
}
#[cfg(test)]
mod tests {
extern crate test;
use self::test::Bencher;
use super::*;
#[bench]
fn fill_small_vec_1_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(10);
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_1_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_8_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(10);
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_8_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_32_10_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(10);
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_32_10_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
sv.extend(0..10);
})
}
#[bench]
fn fill_small_vec_1_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::with_capacity(50);
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_1_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 1]> = SmallVec::new();
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_8_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::with_capacity(50);
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_8_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 8]> = SmallVec::new();
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_32_50_with_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::with_capacity(50);
sv.extend(0..50);
})
}
#[bench]
fn fill_small_vec_32_50_wo_cap(b: &mut Bencher) {
b.iter(|| {
let mut sv: SmallVec<[usize; 32]> = SmallVec::new();
sv.extend(0..50);
})
}
}

View File

@ -331,6 +331,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
}
if mbcx.errors_buffer.len() > 0 {
mbcx.errors_buffer.sort_by_key(|diag| diag.span.primary_span());
if tcx.migrate_borrowck() {
match tcx.borrowck(def_id).signalled_any_error {
SignalledError::NoErrorsSeen => {

View File

@ -341,7 +341,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
// another match arm
binds_to.sort();
binds_to.dedup();
for local in binds_to {
let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
for (j, local) in binds_to.into_iter().enumerate() {
let bind_to = &self.mir.local_decls[local];
let binding_span = bind_to.source_info.span;
@ -350,13 +351,15 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
Mutability::Not => "ref",
Mutability::Mut => "ref mut",
};
if j == 0 {
err.span_label(binding_span, format!("data moved here"));
} else {
err.span_label(binding_span, format!("... and here"));
}
match bind_to.name {
Some(name) => {
err.span_suggestion(
binding_span,
"to prevent move, use ref or ref mut",
format!("{} {:?}", ref_kind, name),
);
multipart_suggestion.push((binding_span,
format!("{} {}", ref_kind, name)));
}
None => {
err.span_label(
@ -366,6 +369,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
}
}
}
err.multipart_suggestion("to prevent move, use ref or ref mut",
multipart_suggestion);
}
// Nothing to suggest.
GroupedMoveError::OtherIllegalMove { .. } => (),

View File

@ -307,7 +307,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
let local_decl = &self.mir.local_decls[*local];
let suggestion = match local_decl.is_user_variable.as_ref().unwrap() {
ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf) => {
Some(suggest_ampmut_self(local_decl))
Some(suggest_ampmut_self(self.tcx, local_decl))
}
ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
@ -418,8 +418,22 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
}
}
fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(local_decl: &mir::LocalDecl<'tcx>) -> (Span, String) {
(local_decl.source_info.span, "&mut self".to_string())
fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
tcx: TyCtxt<'cx, 'gcx, 'tcx>,
local_decl: &mir::LocalDecl<'tcx>,
) -> (Span, String) {
let sp = local_decl.source_info.span;
(sp, match tcx.sess.codemap().span_to_snippet(sp) {
Ok(snippet) => {
let lt_pos = snippet.find('\'');
if let Some(lt_pos) = lt_pos {
format!("&{}mut self", &snippet[lt_pos..snippet.len() - 4])
} else {
"&mut self".to_string()
}
}
_ => "&mut self".to_string()
})
}
// When we want to suggest a user change a local variable to be a `&mut`, there
@ -447,9 +461,15 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
let locations = mir.find_assignments(local);
if locations.len() > 0 {
let assignment_rhs_span = mir.source_info(locations[0]).span;
let snippet = tcx.sess.codemap().span_to_snippet(assignment_rhs_span);
if let Ok(src) = snippet {
if src.starts_with('&') {
if let Ok(src) = tcx.sess.codemap().span_to_snippet(assignment_rhs_span) {
if let (true, Some(ws_pos)) = (
src.starts_with("&'"),
src.find(|c: char| -> bool { c.is_whitespace() }),
) {
let lt_name = &src[1..ws_pos];
let ty = &src[ws_pos..];
return (assignment_rhs_span, format!("&{} mut {}", lt_name, ty));
} else if src.starts_with('&') {
let borrowed_expr = src[1..].to_string();
return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
}
@ -466,13 +486,25 @@ fn suggest_ampmut<'cx, 'gcx, 'tcx>(
None => local_decl.source_info.span,
};
if let Ok(src) = tcx.sess.codemap().span_to_snippet(highlight_span) {
if let (true, Some(ws_pos)) = (
src.starts_with("&'"),
src.find(|c: char| -> bool { c.is_whitespace() }),
) {
let lt_name = &src[1..ws_pos];
let ty = &src[ws_pos..];
return (highlight_span, format!("&{} mut{}", lt_name, ty));
}
}
let ty_mut = local_decl.ty.builtin_deref(true).unwrap();
assert_eq!(ty_mut.mutbl, hir::MutImmutable);
if local_decl.ty.is_region_ptr() {
(highlight_span, format!("&mut {}", ty_mut.ty))
} else {
(highlight_span, format!("*mut {}", ty_mut.ty))
}
(highlight_span,
if local_decl.ty.is_region_ptr() {
format!("&mut {}", ty_mut.ty)
} else {
format!("*mut {}", ty_mut.ty)
})
}
fn is_closure_or_generator(ty: ty::Ty) -> bool {

View File

@ -1213,11 +1213,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() {
let mut vals_for_guard = Vec::with_capacity(num_patterns);
for _ in 0..num_patterns {
let val_for_guard_idx = self.local_decls.push(local.clone());
let val_for_guard_idx = self.local_decls.push(LocalDecl {
// This variable isn't mutated but has a name, so has to be
// immutable to avoid the unused mut lint.
mutability: Mutability::Not,
..local.clone()
});
vals_for_guard.push(val_for_guard_idx);
}
let ref_for_guard = self.local_decls.push(LocalDecl::<'tcx> {
mutability,
// See previous comment.
mutability: Mutability::Not,
ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
name: Some(name),
source_info,

View File

@ -0,0 +1,32 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use spec::{LinkerFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::hermit_base::opts();
base.max_atomic_width = Some(128);
base.abi_blacklist = super::arm_base::abi_blacklist();
base.linker = Some("aarch64-hermit-gcc".to_string());
Ok(Target {
llvm_target: "aarch64-unknown-hermit".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
target_os: "hermit".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}

View File

@ -0,0 +1,37 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
use std::default::Default;
pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
args.insert(LinkerFlavor::Gcc, vec![
"-Wl,-Bstatic".to_string(),
"-Wl,--no-dynamic-linker".to_string(),
"-Wl,--gc-sections".to_string(),
"-Wl,--as-needed".to_string(),
]);
TargetOptions {
exe_allocation_crate: None,
executables: true,
has_elf_tls: true,
linker_is_gnu: true,
no_default_libraries: false,
panic_strategy: PanicStrategy::Abort,
position_independent_executables: false,
pre_link_args: args,
relocation_model: "static".to_string(),
target_family: Some("unix".to_string()),
tls_model: "local-exec".to_string(),
.. Default::default()
}
}

View File

@ -62,6 +62,7 @@ mod cloudabi_base;
mod dragonfly_base;
mod freebsd_base;
mod haiku_base;
mod hermit_base;
mod linux_base;
mod linux_musl_base;
mod openbsd_base;
@ -373,6 +374,9 @@ supported_targets! {
("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf),
("i686-unknown-cloudabi", i686_unknown_cloudabi),
("x86_64-unknown-cloudabi", x86_64_unknown_cloudabi),
("aarch64-unknown-hermit", aarch64_unknown_hermit),
("x86_64-unknown-hermit", x86_64_unknown_hermit),
}
/// Everything `rustc` knows about how to compile for a specific target.

View File

@ -0,0 +1,33 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use spec::{LinkerFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::hermit_base::opts();
base.cpu = "x86-64".to_string();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.linker = Some("x86_64-hermit-gcc".to_string());
base.max_atomic_width = Some(64);
Ok(Target {
llvm_target: "x86_64-unknown-hermit".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(),
arch: "x86_64".to_string(),
target_os: "hermit".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}

View File

@ -12,7 +12,9 @@ use std::fs;
use std::path::Path;
use std::str;
use errors;
use html::markdown::Markdown;
use syntax::feature_gate::UnstableFeatures;
use html::markdown::{IdMap, ErrorCodes, Markdown};
use std::cell::RefCell;
#[derive(Clone)]
pub struct ExternalHtml {
@ -29,8 +31,10 @@ pub struct ExternalHtml {
impl ExternalHtml {
pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler)
md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler,
id_map: &mut IdMap)
-> Option<ExternalHtml> {
let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
load_external_files(in_header, diag)
.and_then(|ih|
load_external_files(before_content, diag)
@ -38,7 +42,8 @@ impl ExternalHtml {
)
.and_then(|(ih, bc)|
load_external_files(md_before_content, diag)
.map(|m_bc| (ih, format!("{}{}", bc, Markdown(&m_bc, &[]))))
.map(|m_bc| (ih,
format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes))))
)
.and_then(|(ih, bc)|
load_external_files(after_content, diag)
@ -46,7 +51,8 @@ impl ExternalHtml {
)
.and_then(|(ih, bc, ac)|
load_external_files(md_after_content, diag)
.map(|m_ac| (ih, bc, format!("{}{}", ac, Markdown(&m_ac, &[]))))
.map(|m_ac| (ih, bc,
format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes))))
)
.map(|(ih, bc, ac)|
ExternalHtml {

View File

@ -13,12 +13,7 @@
//! This module uses libsyntax's lexer to provide token-based highlighting for
//! the HTML documentation generated by rustdoc.
//!
//! If you just want to syntax highlighting for a Rust program, then you can use
//! the `render_inner_with_highlighting` or `render_with_highlighting`
//! functions. For more advanced use cases (if you want to supply your own css
//! classes or control how the HTML is generated, or even generate something
//! other then HTML), then you should implement the `Writer` trait and use a
//! `Classifier`.
//! Use the `render_with_highlighting` to highlight some rust code.
use html::escape::Escape;
@ -33,7 +28,7 @@ use syntax::parse;
use syntax_pos::{Span, FileName};
/// Highlights `src`, returning the HTML output.
pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>,
pub fn render_with_highlighting(src: &str, class: Option<&str>,
extension: Option<&str>,
tooltip: Option<(&str, &str)>) -> String {
debug!("highlighting: ================\n{}\n==============", src);
@ -46,7 +41,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>
class='tooltiptext'>{}</span></div></div>",
class, tooltip).unwrap();
}
write_header(class, id, &mut out).unwrap();
write_header(class, &mut out).unwrap();
let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), sess.codemap());
if let Err(_) = classifier.write_source(&mut out) {
@ -63,7 +58,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>
/// Processes a program (nested in the internal `lexer`), classifying strings of
/// text by highlighting category (`Class`). Calls out to a `Writer` to write
/// each span of text in sequence.
pub struct Classifier<'a> {
struct Classifier<'a> {
lexer: lexer::StringReader<'a>,
codemap: &'a CodeMap,
@ -75,7 +70,7 @@ pub struct Classifier<'a> {
/// How a span of text is classified. Mostly corresponds to token kinds.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Class {
enum Class {
None,
Comment,
DocComment,
@ -103,7 +98,7 @@ pub enum Class {
/// The classifier will call into the `Writer` implementation as it finds spans
/// of text to highlight. Exactly how that text should be highlighted is up to
/// the implementation.
pub trait Writer {
trait Writer {
/// Called when we start processing a span of text that should be highlighted.
/// The `Class` argument specifies how it should be highlighted.
fn enter_span(&mut self, _: Class) -> io::Result<()>;
@ -111,11 +106,9 @@ pub trait Writer {
/// Called at the end of a span of highlighted text.
fn exit_span(&mut self) -> io::Result<()>;
/// Called for a span of text, usually, but not always, a single token. If
/// the string of text (`T`) does correspond to a token, then the token will
/// also be passed. If the text should be highlighted differently from the
/// surrounding text, then the `Class` argument will be a value other than
/// `None`.
/// Called for a span of text. If the text should be highlighted differently from the
/// surrounding text, then the `Class` argument will be a value other than `None`.
///
/// The following sequences of callbacks are equivalent:
/// ```plain
/// enter_span(Foo), string("text", None), exit_span()
@ -125,8 +118,7 @@ pub trait Writer {
/// more flexible.
fn string<T: Display>(&mut self,
text: T,
klass: Class,
tok: Option<&TokenAndSpan>)
klass: Class)
-> io::Result<()>;
}
@ -135,8 +127,7 @@ pub trait Writer {
impl<U: Write> Writer for U {
fn string<T: Display>(&mut self,
text: T,
klass: Class,
_tas: Option<&TokenAndSpan>)
klass: Class)
-> io::Result<()> {
match klass {
Class::None => write!(self, "{}", text),
@ -154,7 +145,7 @@ impl<U: Write> Writer for U {
}
impl<'a> Classifier<'a> {
pub fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> {
fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> {
Classifier {
lexer,
codemap,
@ -186,7 +177,7 @@ impl<'a> Classifier<'a> {
/// is used. All source code emission is done as slices from the source map,
/// not from the tokens themselves, in order to stay true to the original
/// source.
pub fn write_source<W: Writer>(&mut self,
fn write_source<W: Writer>(&mut self,
out: &mut W)
-> io::Result<()> {
loop {
@ -208,7 +199,7 @@ impl<'a> Classifier<'a> {
-> io::Result<()> {
let klass = match tas.tok {
token::Shebang(s) => {
out.string(Escape(&s.as_str()), Class::None, Some(&tas))?;
out.string(Escape(&s.as_str()), Class::None)?;
return Ok(());
},
@ -272,8 +263,8 @@ impl<'a> Classifier<'a> {
self.in_attribute = true;
out.enter_span(Class::Attribute)?;
}
out.string("#", Class::None, None)?;
out.string("!", Class::None, None)?;
out.string("#", Class::None)?;
out.string("!", Class::None)?;
return Ok(());
}
@ -282,13 +273,13 @@ impl<'a> Classifier<'a> {
self.in_attribute = true;
out.enter_span(Class::Attribute)?;
}
out.string("#", Class::None, None)?;
out.string("#", Class::None)?;
return Ok(());
}
token::CloseDelim(token::Bracket) => {
if self.in_attribute {
self.in_attribute = false;
out.string("]", Class::None, None)?;
out.string("]", Class::None)?;
out.exit_span()?;
return Ok(());
} else {
@ -344,7 +335,7 @@ impl<'a> Classifier<'a> {
// Anything that didn't return above is the simple case where we the
// class just spans a single token, so we can use the `string` method.
out.string(Escape(&self.snip(tas.sp)), klass, Some(&tas))
out.string(Escape(&self.snip(tas.sp)), klass)
}
// Helper function to get a snippet from the codemap.
@ -355,7 +346,7 @@ impl<'a> Classifier<'a> {
impl Class {
/// Returns the css class expected by rustdoc for each `Class`.
pub fn rustdoc_class(self) -> &'static str {
fn rustdoc_class(self) -> &'static str {
match self {
Class::None => "",
Class::Comment => "comment",
@ -379,15 +370,8 @@ impl Class {
}
}
fn write_header(class: Option<&str>,
id: Option<&str>,
out: &mut dyn Write)
-> io::Result<()> {
write!(out, "<pre ")?;
if let Some(id) = id {
write!(out, "id='{}' ", id)?;
}
write!(out, "class=\"rust {}\">\n", class.unwrap_or(""))
fn write_header(class: Option<&str>, out: &mut dyn Write) -> io::Result<()> {
write!(out, "<pre class=\"rust {}\">\n", class.unwrap_or(""))
}
fn write_footer(out: &mut dyn Write) -> io::Result<()> {

View File

@ -18,16 +18,17 @@
//! ```
//! #![feature(rustc_private)]
//!
//! use rustdoc::html::markdown::Markdown;
//! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes};
//! use std::cell::RefCell;
//!
//! let s = "My *markdown* _text_";
//! let html = format!("{}", Markdown(s, &[]));
//! let mut id_map = IdMap::new();
//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes));
//! // ... something using html
//! ```
#![allow(non_camel_case_types)]
use rustc::session;
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::default::Default;
@ -35,10 +36,7 @@ use std::fmt::{self, Write};
use std::borrow::Cow;
use std::ops::Range;
use std::str;
use syntax::feature_gate::UnstableFeatures;
use syntax::codemap::Span;
use html::render::derive_id;
use html::toc::TocBuilder;
use html::highlight;
use test;
@ -50,15 +48,38 @@ use pulldown_cmark::{Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};
/// formatted, this struct will emit the HTML corresponding to the rendered
/// version of the contained markdown string.
/// The second parameter is a list of link replacements
pub struct Markdown<'a>(pub &'a str, pub &'a [(String, String)]);
pub struct Markdown<'a>(
pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes);
/// A unit struct like `Markdown`, that renders the markdown with a
/// table of contents.
pub struct MarkdownWithToc<'a>(pub &'a str);
pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
/// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
pub struct MarkdownHtml<'a>(pub &'a str);
pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
/// A unit struct like `Markdown`, that renders only the first paragraph.
pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum ErrorCodes {
Yes,
No,
}
impl ErrorCodes {
pub fn from(b: bool) -> Self {
match b {
true => ErrorCodes::Yes,
false => ErrorCodes::No,
}
}
pub fn as_bool(self) -> bool {
match self {
ErrorCodes::Yes => true,
ErrorCodes::No => false,
}
}
}
/// Controls whether a line will be hidden or shown in HTML output.
///
/// All lines are used in documentation tests.
@ -129,12 +150,14 @@ thread_local!(pub static PLAYGROUND: RefCell<Option<(Option<String>, String)>> =
/// Adds syntax highlighting and playground Run buttons to rust code blocks.
struct CodeBlocks<'a, I: Iterator<Item = Event<'a>>> {
inner: I,
check_error_codes: ErrorCodes,
}
impl<'a, I: Iterator<Item = Event<'a>>> CodeBlocks<'a, I> {
fn new(iter: I) -> Self {
fn new(iter: I, error_codes: ErrorCodes) -> Self {
CodeBlocks {
inner: iter,
check_error_codes: error_codes,
}
}
}
@ -147,7 +170,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
let compile_fail;
let ignore;
if let Some(Event::Start(Tag::CodeBlock(lang))) = event {
let parse_result = LangString::parse(&lang);
let parse_result = LangString::parse(&lang, self.check_error_codes);
if !parse_result.rust {
return Some(Event::Start(Tag::CodeBlock(lang)));
}
@ -224,7 +247,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
if ignore { " ignore" }
else if compile_fail { " compile_fail" }
else { "" })),
None,
playground_button.as_ref().map(String::as_str),
tooltip));
Some(Event::Html(s.into()))
@ -266,23 +288,25 @@ impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, 'b, I>
}
/// Make headings links with anchor ids and build up TOC.
struct HeadingLinks<'a, 'b, I: Iterator<Item = Event<'a>>> {
struct HeadingLinks<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> {
inner: I,
toc: Option<&'b mut TocBuilder>,
buf: VecDeque<Event<'a>>,
id_map: &'ids mut IdMap,
}
impl<'a, 'b, I: Iterator<Item = Event<'a>>> HeadingLinks<'a, 'b, I> {
fn new(iter: I, toc: Option<&'b mut TocBuilder>) -> Self {
impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> HeadingLinks<'a, 'b, 'ids, I> {
fn new(iter: I, toc: Option<&'b mut TocBuilder>, ids: &'ids mut IdMap) -> Self {
HeadingLinks {
inner: iter,
toc,
buf: VecDeque::new(),
id_map: ids,
}
}
}
impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, I> {
impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, 'ids, I> {
type Item = Event<'a>;
fn next(&mut self) -> Option<Self::Item> {
@ -301,7 +325,7 @@ impl<'a, 'b, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, I>
}
self.buf.push_back(event);
}
let id = derive_id(id);
let id = self.id_map.derive(id);
if let Some(ref mut builder) = self.toc {
let mut html_header = String::new();
@ -467,10 +491,17 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Footnotes<'a, I> {
}
}
pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span,
sess: Option<&session::Session>) {
tests.set_position(position);
pub struct TestableCodeError(());
impl fmt::Display for TestableCodeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "invalid start of a new code block")
}
}
pub fn find_testable_code(
doc: &str, tests: &mut test::Collector, error_codes: ErrorCodes,
) -> Result<(), TestableCodeError> {
let mut parser = Parser::new(doc);
let mut prev_offset = 0;
let mut nb_lines = 0;
@ -481,7 +512,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
let block_info = if s.is_empty() {
LangString::all_false()
} else {
LangString::parse(&*s)
LangString::parse(&*s, error_codes)
};
if !block_info.rust {
continue
@ -510,18 +541,10 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
let text = lines.collect::<Vec<Cow<str>>>().join("\n");
nb_lines += doc[prev_offset..offset].lines().count();
let line = tests.get_line() + (nb_lines - 1);
let filename = tests.get_filename();
tests.add_test(text.to_owned(),
block_info.should_panic, block_info.no_run,
block_info.ignore, block_info.test_harness,
block_info.compile_fail, block_info.error_codes,
line, filename, block_info.allow_fail);
tests.add_test(text, block_info, line);
prev_offset = offset;
} else {
if let Some(ref sess) = sess {
sess.span_warn(position, "invalid start of a new code block");
}
break;
return Err(TestableCodeError(()));
}
}
Event::Start(Tag::Header(level)) => {
@ -539,19 +562,20 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
_ => {}
}
}
Ok(())
}
#[derive(Eq, PartialEq, Clone, Debug)]
struct LangString {
pub struct LangString {
original: String,
should_panic: bool,
no_run: bool,
ignore: bool,
rust: bool,
test_harness: bool,
compile_fail: bool,
error_codes: Vec<String>,
allow_fail: bool,
pub should_panic: bool,
pub no_run: bool,
pub ignore: bool,
pub rust: bool,
pub test_harness: bool,
pub compile_fail: bool,
pub error_codes: Vec<String>,
pub allow_fail: bool,
}
impl LangString {
@ -569,14 +593,11 @@ impl LangString {
}
}
fn parse(string: &str) -> LangString {
fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString {
let allow_error_code_check = allow_error_code_check.as_bool();
let mut seen_rust_tags = false;
let mut seen_other_tags = false;
let mut data = LangString::all_false();
let mut allow_error_code_check = false;
if UnstableFeatures::from_environment().is_nightly_build() {
allow_error_code_check = true;
}
data.original = string.to_owned();
let tokens = string.split(|c: char|
@ -623,7 +644,8 @@ impl LangString {
impl<'a> fmt::Display for Markdown<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let Markdown(md, links) = *self;
let Markdown(md, links, ref ids, codes) = *self;
let mut ids = ids.borrow_mut();
// This is actually common enough to special-case
if md.is_empty() { return Ok(()) }
@ -643,12 +665,11 @@ impl<'a> fmt::Display for Markdown<'a> {
let mut s = String::with_capacity(md.len() * 3 / 2);
html::push_html(&mut s,
Footnotes::new(
CodeBlocks::new(
LinkReplacer::new(
HeadingLinks::new(p, None),
links))));
let p = HeadingLinks::new(p, None, &mut ids);
let p = LinkReplacer::new(p, links);
let p = CodeBlocks::new(p, codes);
let p = Footnotes::new(p);
html::push_html(&mut s, p);
fmt.write_str(&s)
}
@ -656,7 +677,8 @@ impl<'a> fmt::Display for Markdown<'a> {
impl<'a> fmt::Display for MarkdownWithToc<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let MarkdownWithToc(md) = *self;
let MarkdownWithToc(md, ref ids, codes) = *self;
let mut ids = ids.borrow_mut();
let mut opts = Options::empty();
opts.insert(OPTION_ENABLE_TABLES);
@ -668,8 +690,12 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
let mut toc = TocBuilder::new();
html::push_html(&mut s,
Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, Some(&mut toc)))));
{
let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
let p = CodeBlocks::new(p, codes);
let p = Footnotes::new(p);
html::push_html(&mut s, p);
}
write!(fmt, "<nav id=\"TOC\">{}</nav>", toc.into_toc())?;
@ -679,7 +705,8 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> {
impl<'a> fmt::Display for MarkdownHtml<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let MarkdownHtml(md) = *self;
let MarkdownHtml(md, ref ids, codes) = *self;
let mut ids = ids.borrow_mut();
// This is actually common enough to special-case
if md.is_empty() { return Ok(()) }
@ -697,8 +724,10 @@ impl<'a> fmt::Display for MarkdownHtml<'a> {
let mut s = String::with_capacity(md.len() * 3 / 2);
html::push_html(&mut s,
Footnotes::new(CodeBlocks::new(HeadingLinks::new(p, None))));
let p = HeadingLinks::new(p, None, &mut ids);
let p = CodeBlocks::new(p, codes);
let p = Footnotes::new(p);
html::push_html(&mut s, p);
fmt.write_str(&s)
}
@ -812,7 +841,10 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
let p = Parser::new_with_broken_link_callback(md, opts,
Some(&push));
let iter = Footnotes::new(HeadingLinks::new(p, None));
// There's no need to thread an IdMap through to here because
// the IDs generated aren't going to be emitted anywhere.
let mut ids = IdMap::new();
let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
for ev in iter {
if let Event::Start(Tag::Link(dest, _)) = ev {
@ -831,18 +863,74 @@ pub fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
links
}
#[derive(Default)]
pub struct IdMap {
map: HashMap<String, usize>,
}
impl IdMap {
pub fn new() -> Self {
IdMap::default()
}
pub fn populate<I: IntoIterator<Item=String>>(&mut self, ids: I) {
for id in ids {
let _ = self.derive(id);
}
}
pub fn reset(&mut self) {
self.map = HashMap::new();
}
pub fn derive(&mut self, candidate: String) -> String {
let id = match self.map.get_mut(&candidate) {
None => candidate,
Some(a) => {
let id = format!("{}-{}", candidate, *a);
*a += 1;
id
}
};
self.map.insert(id.clone(), 1);
id
}
}
#[cfg(test)]
#[test]
fn test_unique_id() {
let input = ["foo", "examples", "examples", "method.into_iter","examples",
"method.into_iter", "foo", "main", "search", "methods",
"examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"];
let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2",
"method.into_iter-1", "foo-1", "main", "search", "methods",
"examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"];
let map = RefCell::new(IdMap::new());
let test = || {
let mut map = map.borrow_mut();
let actual: Vec<String> = input.iter().map(|s| map.derive(s.to_string())).collect();
assert_eq!(&actual[..], expected);
};
test();
map.borrow_mut().reset();
test();
}
#[cfg(test)]
mod tests {
use super::{LangString, Markdown, MarkdownHtml};
use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
use super::plain_summary_line;
use html::render::reset_ids;
use std::cell::RefCell;
#[test]
fn test_lang_string_parse() {
fn t(s: &str,
should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool,
compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) {
assert_eq!(LangString::parse(s), LangString {
assert_eq!(LangString::parse(s, ErrorCodes::Yes), LangString {
should_panic,
no_run,
ignore,
@ -878,19 +966,12 @@ mod tests {
t("text,no_run", false, true, false, false, false, false, false, v());
}
#[test]
fn issue_17736() {
let markdown = "# title";
Markdown(markdown, &[]).to_string();
reset_ids(true);
}
#[test]
fn test_header() {
fn t(input: &str, expect: &str) {
let output = Markdown(input, &[]).to_string();
let mut map = IdMap::new();
let output = Markdown(input, &[], RefCell::new(&mut map), ErrorCodes::Yes).to_string();
assert_eq!(output, expect, "original: {}", input);
reset_ids(true);
}
t("# Foo bar", "<h1 id=\"foo-bar\" class=\"section-header\">\
@ -909,28 +990,24 @@ mod tests {
#[test]
fn test_header_ids_multiple_blocks() {
fn t(input: &str, expect: &str) {
let output = Markdown(input, &[]).to_string();
let mut map = IdMap::new();
fn t(map: &mut IdMap, input: &str, expect: &str) {
let output = Markdown(input, &[], RefCell::new(map), ErrorCodes::Yes).to_string();
assert_eq!(output, expect, "original: {}", input);
}
let test = || {
t("# Example", "<h1 id=\"example\" class=\"section-header\">\
<a href=\"#example\">Example</a></h1>");
t("# Panics", "<h1 id=\"panics\" class=\"section-header\">\
<a href=\"#panics\">Panics</a></h1>");
t("# Example", "<h1 id=\"example-1\" class=\"section-header\">\
<a href=\"#example-1\">Example</a></h1>");
t("# Main", "<h1 id=\"main-1\" class=\"section-header\">\
<a href=\"#main-1\">Main</a></h1>");
t("# Example", "<h1 id=\"example-2\" class=\"section-header\">\
<a href=\"#example-2\">Example</a></h1>");
t("# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\
<a href=\"#panics-1\">Panics</a></h1>");
};
test();
reset_ids(true);
test();
t(&mut map, "# Example", "<h1 id=\"example\" class=\"section-header\">\
<a href=\"#example\">Example</a></h1>");
t(&mut map, "# Panics", "<h1 id=\"panics\" class=\"section-header\">\
<a href=\"#panics\">Panics</a></h1>");
t(&mut map, "# Example", "<h1 id=\"example-1\" class=\"section-header\">\
<a href=\"#example-1\">Example</a></h1>");
t(&mut map, "# Main", "<h1 id=\"main\" class=\"section-header\">\
<a href=\"#main\">Main</a></h1>");
t(&mut map, "# Example", "<h1 id=\"example-2\" class=\"section-header\">\
<a href=\"#example-2\">Example</a></h1>");
t(&mut map, "# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\
<a href=\"#panics-1\">Panics</a></h1>");
}
#[test]
@ -951,7 +1028,8 @@ mod tests {
#[test]
fn test_markdown_html_escape() {
fn t(input: &str, expect: &str) {
let output = MarkdownHtml(input).to_string();
let mut idmap = IdMap::new();
let output = MarkdownHtml(input, RefCell::new(&mut idmap), ErrorCodes::Yes).to_string();
assert_eq!(output, expect, "original: {}", input);
}

View File

@ -50,12 +50,14 @@ use std::mem;
use std::path::{PathBuf, Path, Component};
use std::str;
use std::sync::Arc;
use std::rc::Rc;
use externalfiles::ExternalHtml;
use serialize::json::{ToJson, Json, as_json};
use syntax::ast;
use syntax::codemap::FileName;
use syntax::feature_gate::UnstableFeatures;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
use rustc::middle::privacy::AccessLevels;
use rustc::middle::stability;
@ -72,7 +74,7 @@ use html::format::{GenericBounds, WhereClause, href, AbiSpace};
use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
use html::format::fmt_impl_for_trait_page;
use html::item_type::ItemType;
use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine};
use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap};
use html::{highlight, layout};
use minifier;
@ -88,7 +90,7 @@ pub type NameDoc = (String, Option<String>);
/// easily cloned because it is cloned per work-job (about once per item in the
/// rustdoc tree).
#[derive(Clone)]
pub struct Context {
struct Context {
/// Current hierarchy of components leading down to what's currently being
/// rendered
pub current: Vec<String>,
@ -99,10 +101,13 @@ pub struct Context {
/// real location of an item. This is used to allow external links to
/// publicly reused items to redirect to the right location.
pub render_redirect_pages: bool,
pub codes: ErrorCodes,
/// The map used to ensure all generated 'id=' attributes are unique.
id_map: Rc<RefCell<IdMap>>,
pub shared: Arc<SharedContext>,
}
pub struct SharedContext {
struct SharedContext {
/// The path to the crate root source minus the file name.
/// Used for simplifying paths to the highlighted source code files.
pub src_root: PathBuf,
@ -450,9 +455,8 @@ impl ToJson for IndexItemFunctionType {
thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> = RefCell::new(Vec::new()));
thread_local!(pub static USED_ID_MAP: RefCell<FxHashMap<String, usize>> = RefCell::new(init_ids()));
fn init_ids() -> FxHashMap<String, usize> {
pub fn initial_ids() -> Vec<String> {
[
"main",
"search",
@ -470,36 +474,7 @@ fn init_ids() -> FxHashMap<String, usize> {
"methods",
"deref-methods",
"implementations",
].into_iter().map(|id| (String::from(*id), 1)).collect()
}
/// This method resets the local table of used ID attributes. This is typically
/// used at the beginning of rendering an entire HTML page to reset from the
/// previous state (if any).
pub fn reset_ids(embedded: bool) {
USED_ID_MAP.with(|s| {
*s.borrow_mut() = if embedded {
init_ids()
} else {
FxHashMap()
};
});
}
pub fn derive_id(candidate: String) -> String {
USED_ID_MAP.with(|map| {
let id = match map.borrow_mut().get_mut(&candidate) {
None => candidate,
Some(a) => {
let id = format!("{}-{}", candidate, *a);
*a += 1;
id
}
};
map.borrow_mut().insert(id.clone(), 1);
id
})
].into_iter().map(|id| (String::from(*id))).collect()
}
/// Generates the documentation for `crate` into the directory `dst`
@ -513,7 +488,8 @@ pub fn run(mut krate: clean::Crate,
renderinfo: RenderInfo,
sort_modules_alphabetically: bool,
themes: Vec<PathBuf>,
enable_minification: bool) -> Result<(), Error> {
enable_minification: bool,
id_map: IdMap) -> Result<(), Error> {
let src_root = match krate.src {
FileName::Real(ref p) => match p.parent() {
Some(p) => p.to_path_buf(),
@ -581,6 +557,8 @@ pub fn run(mut krate: clean::Crate,
current: Vec::new(),
dst,
render_redirect_pages: false,
codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
id_map: Rc::new(RefCell::new(id_map)),
shared: Arc::new(scx),
};
@ -1708,6 +1686,11 @@ impl<'a> fmt::Display for Settings<'a> {
}
impl Context {
fn derive_id(&self, id: String) -> String {
let mut map = self.id_map.borrow_mut();
map.derive(id)
}
/// String representation of how to get back to the root path of the 'doc/'
/// folder in terms of a relative URL.
fn root_path(&self) -> String {
@ -1862,7 +1845,10 @@ impl Context {
resource_suffix: &self.shared.resource_suffix,
};
reset_ids(true);
{
self.id_map.borrow_mut().reset();
self.id_map.borrow_mut().populate(initial_ids());
}
if !self.render_redirect_pages {
layout::render(writer, &self.shared.layout, &page,
@ -2219,14 +2205,17 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
/// Render md_text as markdown.
fn render_markdown(w: &mut fmt::Formatter,
cx: &Context,
md_text: &str,
links: Vec<(String, String)>,
prefix: &str,)
prefix: &str)
-> fmt::Result {
write!(w, "<div class='docblock'>{}{}</div>", prefix, Markdown(md_text, &links))
let mut ids = cx.id_map.borrow_mut();
write!(w, "<div class='docblock'>{}{}</div>",
prefix, Markdown(md_text, &links, RefCell::new(&mut ids), cx.codes))
}
fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink,
fn document_short(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, link: AssocItemLink,
prefix: &str) -> fmt::Result {
if let Some(s) = item.doc_value() {
let markdown = if s.contains('\n') {
@ -2235,7 +2224,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
} else {
plain_summary_line(Some(s)).to_string()
};
render_markdown(w, &markdown, item.links(), prefix)?;
render_markdown(w, cx, &markdown, item.links(), prefix)?;
} else if !prefix.is_empty() {
write!(w, "<div class='docblock'>{}</div>", prefix)?;
}
@ -2250,7 +2239,6 @@ fn render_assoc_const_value(item: &clean::Item) -> String {
None,
None,
None,
None,
)
}
_ => String::new(),
@ -2261,7 +2249,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
cx: &Context, prefix: &str) -> fmt::Result {
if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
debug!("Doc block: =====\n{}\n=====", s);
render_markdown(w, &*s, item.links(), prefix)?;
render_markdown(w, cx, &*s, item.links(), prefix)?;
} else if !prefix.is_empty() {
write!(w, "<div class='docblock'>{}</div>", prefix)?;
}
@ -2427,7 +2415,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
let (short, name) = item_ty_to_strs(&myty.unwrap());
write!(w, "<h2 id='{id}' class='section-header'>\
<a href=\"#{id}\">{name}</a></h2>\n<table>",
id = derive_id(short.to_owned()), name = name)?;
id = cx.derive_id(short.to_owned()), name = name)?;
}
match myitem.inner {
@ -2508,6 +2496,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<String> {
let mut stability = vec![];
let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
if let Some(stab) = item.stability.as_ref() {
let deprecated_reason = if show_reason && !stab.deprecated_reason.is_empty() {
@ -2521,14 +2510,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
} else {
String::new()
};
let mut ids = cx.id_map.borrow_mut();
let html = MarkdownHtml(&deprecated_reason, RefCell::new(&mut ids), error_codes);
let text = if stability::deprecation_in_effect(&stab.deprecated_since) {
format!("Deprecated{}{}",
since,
MarkdownHtml(&deprecated_reason))
format!("Deprecated{}{}", since, html)
} else {
format!("Deprecating in {}{}",
Escape(&stab.deprecated_since),
MarkdownHtml(&deprecated_reason))
format!("Deprecating in {}{}", Escape(&stab.deprecated_since), html)
};
stability.push(format!("<div class='stab deprecated'>{}</div>", text))
};
@ -2555,11 +2542,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
</div>",
unstable_extra));
} else {
let mut ids = cx.id_map.borrow_mut();
let text = format!("<summary><span class=microscope>🔬</span> \
This is a nightly-only experimental API. {}\
</summary>{}",
unstable_extra,
MarkdownHtml(&stab.unstable_reason));
MarkdownHtml(
&stab.unstable_reason,
RefCell::new(&mut ids),
error_codes));
stability.push(format!("<div class='stab unstable'><details>{}</details></div>",
text));
}
@ -2579,14 +2570,15 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
String::new()
};
let mut ids = cx.id_map.borrow_mut();
let text = if stability::deprecation_in_effect(&depr.since) {
format!("Deprecated{}{}",
since,
MarkdownHtml(&note))
MarkdownHtml(&note, RefCell::new(&mut ids), error_codes))
} else {
format!("Deprecating in {}{}",
Escape(&depr.since),
MarkdownHtml(&note))
MarkdownHtml(&note, RefCell::new(&mut ids), error_codes))
};
stability.push(format!("<div class='stab deprecated'>{}</div>", text))
}
@ -2827,8 +2819,8 @@ fn item_trait(
-> fmt::Result {
let name = m.name.as_ref().unwrap();
let item_type = m.type_();
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
let id = cx.derive_id(format!("{}.{}", item_type, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "{extra}<h3 id='{id}' class='method'>\
<span id='{ns_id}' class='invisible'><code>",
extra = render_spotlight_traits(m)?,
@ -3183,10 +3175,10 @@ fn item_struct(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
document_non_exhaustive_header(it))?;
document_non_exhaustive(w, it)?;
for (field, ty) in fields {
let id = derive_id(format!("{}.{}",
let id = cx.derive_id(format!("{}.{}",
ItemType::StructField,
field.name.as_ref().unwrap()));
let ns_id = derive_id(format!("{}.{}",
let ns_id = cx.derive_id(format!("{}.{}",
field.name.as_ref().unwrap(),
ItemType::StructField.name_space()));
write!(w, "<span id=\"{id}\" class=\"{item_type} small-section-header\">
@ -3317,10 +3309,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
document_non_exhaustive_header(it))?;
document_non_exhaustive(w, it)?;
for variant in &e.variants {
let id = derive_id(format!("{}.{}",
let id = cx.derive_id(format!("{}.{}",
ItemType::Variant,
variant.name.as_ref().unwrap()));
let ns_id = derive_id(format!("{}.{}",
let ns_id = cx.derive_id(format!("{}.{}",
variant.name.as_ref().unwrap(),
ItemType::Variant.name_space()));
write!(w, "<span id=\"{id}\" class=\"variant small-section-header\">\
@ -3348,7 +3340,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
if let clean::VariantItem(Variant {
kind: VariantKind::Struct(ref s)
}) = variant.inner {
let variant_id = derive_id(format!("{}.{}.fields",
let variant_id = cx.derive_id(format!("{}.{}.fields",
ItemType::Variant,
variant.name.as_ref().unwrap()));
write!(w, "<span class='docblock autohide sub-variant' id='{id}'>",
@ -3358,10 +3350,10 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
for field in &s.fields {
use clean::StructFieldItem;
if let StructFieldItem(ref ty) = field.inner {
let id = derive_id(format!("variant.{}.field.{}",
let id = cx.derive_id(format!("variant.{}.field.{}",
variant.name.as_ref().unwrap(),
field.name.as_ref().unwrap()));
let ns_id = derive_id(format!("{}.{}.{}.{}",
let ns_id = cx.derive_id(format!("{}.{}.{}.{}",
variant.name.as_ref().unwrap(),
ItemType::Variant.name_space(),
field.name.as_ref().unwrap(),
@ -3790,7 +3782,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
render_mode: RenderMode, outer_version: Option<&str>,
show_def_docs: bool) -> fmt::Result {
if render_mode == RenderMode::Normal {
let id = derive_id(match i.inner_impl().trait_ {
let id = cx.derive_id(match i.inner_impl().trait_ {
Some(ref t) => format!("impl-{}", small_url_encode(&format!("{:#}", t))),
None => "impl".to_string(),
});
@ -3810,8 +3802,9 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
}
write!(w, "</span></td></tr></tbody></table></h3>")?;
if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
let mut ids = cx.id_map.borrow_mut();
write!(w, "<div class='docblock'>{}</div>",
Markdown(&*dox, &i.impl_item.links()))?;
Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?;
}
}
@ -3832,8 +3825,8 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
clean::TyMethodItem(clean::TyMethod{ ref decl, .. }) => {
// Only render when the method is not static or we allow static methods
if render_method_item {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
let id = cx.derive_id(format!("{}.{}", item_type, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "{}", spotlight_decl(decl)?)?;
write!(w, "<span id='{}' class='invisible'>", ns_id)?;
@ -3854,24 +3847,24 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
}
}
clean::TypedefItem(ref tydef, _) => {
let id = derive_id(format!("{}.{}", ItemType::AssociatedType, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
let id = cx.derive_id(format!("{}.{}", ItemType::AssociatedType, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
}
clean::AssociatedConstItem(ref ty, ref default) => {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
let id = cx.derive_id(format!("{}.{}", item_type, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
write!(w, "</code></span></h4>\n")?;
}
clean::AssociatedTypeItem(ref bounds, ref default) => {
let id = derive_id(format!("{}.{}", item_type, name));
let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
let id = cx.derive_id(format!("{}.{}", item_type, name));
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
write!(w, "<h4 id='{}' class=\"{}\">", id, item_type)?;
write!(w, "<span id='{}' class='invisible'><code>", ns_id)?;
assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
@ -3897,7 +3890,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
} else if show_def_docs {
// In case the item isn't documented,
// provide short documentation from the trait.
document_short(w, it, link, &prefix)?;
document_short(w, cx, it, link, &prefix)?;
}
}
} else {
@ -3909,7 +3902,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
} else {
document_stability(w, cx, item)?;
if show_def_docs {
document_short(w, item, link, &prefix)?;
document_short(w, cx, item, link, &prefix)?;
}
}
}
@ -4557,7 +4550,7 @@ impl<'a> fmt::Display for Source<'a> {
}
write!(fmt, "</pre>")?;
write!(fmt, "{}",
highlight::render_with_highlighting(s, None, None, None, None))?;
highlight::render_with_highlighting(s, None, None, None))?;
Ok(())
}
}
@ -4568,7 +4561,6 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
w.write_str(&highlight::render_with_highlighting(&t.source,
Some("macro"),
None,
None,
None))
})?;
document(w, cx, it)
@ -4715,25 +4707,6 @@ pub fn cache() -> Arc<Cache> {
CACHE_KEY.with(|c| c.borrow().clone())
}
#[cfg(test)]
#[test]
fn test_unique_id() {
let input = ["foo", "examples", "examples", "method.into_iter","examples",
"method.into_iter", "foo", "main", "search", "methods",
"examples", "method.into_iter", "assoc_type.Item", "assoc_type.Item"];
let expected = ["foo", "examples", "examples-1", "method.into_iter", "examples-2",
"method.into_iter-1", "foo-1", "main-1", "search-1", "methods-1",
"examples-3", "method.into_iter-2", "assoc_type.Item", "assoc_type.Item-1"];
let test = || {
let actual: Vec<String> = input.iter().map(|s| derive_id(s.to_string())).collect();
assert_eq!(&actual[..], expected);
};
test();
reset_ids(true);
test();
}
#[cfg(test)]
#[test]
fn test_name_key() {

View File

@ -500,12 +500,14 @@ fn main_args(args: &[String]) -> isize {
}
}
let mut id_map = html::markdown::IdMap::new();
id_map.populate(html::render::initial_ids());
let external_html = match ExternalHtml::load(
&matches.opt_strs("html-in-header"),
&matches.opt_strs("html-before-content"),
&matches.opt_strs("html-after-content"),
&matches.opt_strs("markdown-before-content"),
&matches.opt_strs("markdown-after-content"), &diag) {
&matches.opt_strs("markdown-after-content"), &diag, &mut id_map) {
Some(eh) => eh,
None => return 3,
};
@ -562,7 +564,7 @@ fn main_args(args: &[String]) -> isize {
renderinfo,
sort_modules_alphabetically,
themes,
enable_minification)
enable_minification, id_map)
.expect("failed to generate documentation");
0
}

View File

@ -12,6 +12,7 @@ use std::default::Default;
use std::fs::File;
use std::io::prelude::*;
use std::path::{PathBuf, Path};
use std::cell::RefCell;
use errors;
use getopts;
@ -19,14 +20,14 @@ use testing;
use rustc::session::search_paths::SearchPaths;
use rustc::session::config::{Externs, CodegenOptions};
use syntax::codemap::DUMMY_SP;
use syntax::feature_gate::UnstableFeatures;
use syntax::edition::Edition;
use externalfiles::{ExternalHtml, LoadStringError, load_string};
use html::render::reset_ids;
use html::escape::Escape;
use html::markdown;
use html::markdown::{Markdown, MarkdownWithToc, find_testable_code};
use html::markdown::{ErrorCodes, IdMap, Markdown, MarkdownWithToc, find_testable_code};
use test::{TestOptions, Collector};
/// Separate any lines at the start of the file that begin with `# ` or `%`.
@ -86,12 +87,12 @@ pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches,
}
let title = metadata[0];
reset_ids(false);
let mut ids = IdMap::new();
let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
let text = if include_toc {
MarkdownWithToc(text).to_string()
MarkdownWithToc(text, RefCell::new(&mut ids), error_codes).to_string()
} else {
Markdown(text, &[]).to_string()
Markdown(text, &[], RefCell::new(&mut ids), error_codes).to_string()
};
let err = write!(
@ -156,7 +157,12 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
true, opts, maybe_sysroot, None,
Some(PathBuf::from(input)),
linker, edition);
find_testable_code(&input_str, &mut collector, DUMMY_SP, None);
collector.set_position(DUMMY_SP);
let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
let res = find_testable_code(&input_str, &mut collector, codes);
if let Err(err) = res {
diag.span_warn(DUMMY_SP, &err.to_string());
}
test_args.insert(0, "rustdoctest".to_string());
testing::test_main(&test_args, collector.tests,
testing::Options::new().display_output(display_warnings));

View File

@ -42,7 +42,7 @@ use errors;
use errors::emitter::ColorConfig;
use clean::Attributes;
use html::markdown;
use html::markdown::{self, ErrorCodes, LangString};
#[derive(Clone, Default)]
pub struct TestOptions {
@ -145,7 +145,8 @@ pub fn run(input_path: &Path,
let mut hir_collector = HirCollector {
sess: &sess,
collector: &mut collector,
map: &map
map: &map,
codes: ErrorCodes::from(sess.opts.unstable_features.is_nightly_build()),
};
hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
intravisit::walk_crate(this, krate);
@ -533,10 +534,8 @@ impl Collector {
format!("{} - {} (line {})", filename, self.names.join("::"), line)
}
pub fn add_test(&mut self, test: String,
should_panic: bool, no_run: bool, should_ignore: bool,
as_test_harness: bool, compile_fail: bool, error_codes: Vec<String>,
line: usize, filename: FileName, allow_fail: bool) {
pub fn add_test(&mut self, test: String, config: LangString, line: usize) {
let filename = self.get_filename();
let name = self.generate_name(line, &filename);
let cfgs = self.cfgs.clone();
let libs = self.libs.clone();
@ -551,10 +550,10 @@ impl Collector {
self.tests.push(testing::TestDescAndFn {
desc: testing::TestDesc {
name: testing::DynTestName(name.clone()),
ignore: should_ignore,
ignore: config.ignore,
// compiler failures are test failures
should_panic: testing::ShouldPanic::No,
allow_fail,
allow_fail: config.allow_fail,
},
testfn: testing::DynTestFn(box move || {
let panic = io::set_panic(None);
@ -572,11 +571,11 @@ impl Collector {
libs,
cg,
externs,
should_panic,
no_run,
as_test_harness,
compile_fail,
error_codes,
config.should_panic,
config.no_run,
config.test_harness,
config.compile_fail,
config.error_codes,
&opts,
maybe_sysroot,
linker,
@ -604,7 +603,7 @@ impl Collector {
self.position = position;
}
pub fn get_filename(&self) -> FileName {
fn get_filename(&self) -> FileName {
if let Some(ref codemap) = self.codemap {
let filename = codemap.span_to_filename(self.position);
if let FileName::Real(ref filename) = filename {
@ -664,7 +663,8 @@ impl Collector {
struct HirCollector<'a, 'hir: 'a> {
sess: &'a session::Session,
collector: &'a mut Collector,
map: &'a hir::map::Map<'hir>
map: &'a hir::map::Map<'hir>,
codes: ErrorCodes,
}
impl<'a, 'hir> HirCollector<'a, 'hir> {
@ -689,10 +689,12 @@ impl<'a, 'hir> HirCollector<'a, 'hir> {
// the collapse-docs pass won't combine sugared/raw doc attributes, or included files with
// anything else, this will combine them for us
if let Some(doc) = attrs.collapsed_doc_value() {
markdown::find_testable_code(&doc,
self.collector,
attrs.span.unwrap_or(DUMMY_SP),
Some(self.sess));
self.collector.set_position(attrs.span.unwrap_or(DUMMY_SP));
let res = markdown::find_testable_code(&doc, self.collector, self.codes);
if let Err(err) = res {
self.sess.diagnostic().span_warn(attrs.span.unwrap_or(DUMMY_SP),
&err.to_string());
}
}
nested(self);

View File

@ -46,58 +46,67 @@ pub trait Encoder {
// Compound types:
fn emit_enum<F>(&mut self, _name: &str, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
fn emit_enum_variant<F>(&mut self, _v_name: &str,
v_id: usize,
_len: usize,
f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_enum_variant<F>(&mut self, _v_name: &str, v_id: usize, _len: usize, f: F)
-> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
self.emit_usize(v_id)?;
f(self)
}
fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F)
-> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
fn emit_enum_struct_variant<F>(&mut self, v_name: &str,
v_id: usize,
len: usize,
f: F) -> Result<(), Self::Error>
fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_enum_struct_variant<F>(&mut self, v_name: &str, v_id: usize, len: usize, f: F)
-> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
self.emit_enum_variant(v_name, v_id, len, f)
}
fn emit_enum_struct_variant_field<F>(&mut self,
_f_name: &str,
f_idx: usize,
f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
fn emit_enum_struct_variant_field<F>(&mut self, _f_name: &str, f_idx: usize, f: F)
-> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
self.emit_enum_variant_arg(f_idx, f)
}
fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F)
-> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_struct_field<F>(&mut self, _f_name: &str, _f_idx: usize, f: F)
-> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
-> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_tuple<F>(&mut self, _len: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
fn emit_tuple_arg<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F)
-> Result<(), Self::Error>
fn emit_tuple_arg<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
self.emit_tuple(len, f)
}
fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F)
-> Result<(), Self::Error>
fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
self.emit_tuple_arg(f_idx, f)
@ -109,13 +118,14 @@ pub trait Encoder {
{
self.emit_enum("Option", f)
}
fn emit_option_none(&mut self) -> Result<(), Self::Error> {
self.emit_enum_variant("None", 0, 0, |_| Ok(()))
}
fn emit_option_some<F>(&mut self, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
self.emit_enum_variant("Some", 1, 1, f)
}
@ -125,8 +135,12 @@ pub trait Encoder {
self.emit_usize(len)?;
f(self)
}
fn emit_seq_elt<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_map<F>(&mut self, len: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
@ -134,10 +148,18 @@ pub trait Encoder {
self.emit_usize(len)?;
f(self)
}
fn emit_map_elt_key<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
where F: FnOnce(&mut Self) -> Result<(), Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<(), Self::Error>
{
f(self)
}
}
pub trait Decoder {
@ -165,59 +187,67 @@ pub trait Decoder {
// Compound types:
fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F)
-> Result<T, Self::Error>
fn read_enum_variant<T, F>(&mut self, _names: &[&str], mut f: F) -> Result<T, Self::Error>
where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
{
let disr = self.read_usize()?;
f(self, disr)
}
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F)
-> Result<T, Self::Error>
fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, Self::Error>
where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
{
self.read_enum_variant(names, f)
}
fn read_enum_struct_variant_field<T, F>(&mut self,
_f_name: &str,
f_idx: usize,
f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
fn read_enum_struct_variant_field<T, F>(&mut self, _f_name: &str, f_idx: usize, f: F)
-> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
self.read_enum_variant_arg(f_idx, f)
}
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
fn read_struct_field<T, F>(&mut self,
_f_name: &str,
_f_idx: usize,
f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_struct_field<T, F>(&mut self, _f_name: &str, _f_idx: usize, f: F)
-> Result<T, Self::Error> where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_tuple<T, F>(&mut self, _len: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F)
-> Result<T, Self::Error>
fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
self.read_tuple(len, f)
}
fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F)
-> Result<T, Self::Error>
fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
self.read_tuple_arg(a_idx, f)
@ -244,8 +274,12 @@ pub trait Decoder {
let len = self.read_usize()?;
f(self, len)
}
fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_map<T, F>(&mut self, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
@ -253,12 +287,18 @@ pub trait Decoder {
let len = self.read_usize()?;
f(self, len)
}
fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F)
-> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error> { f(self) }
fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
where F: FnOnce(&mut Self) -> Result<T, Self::Error>
{
f(self)
}
// Failure
fn error(&mut self, err: &str) -> Self::Error;
@ -567,9 +607,7 @@ impl<T:Decodable> Decodable for Vec<T> {
}
}
impl<'a, T:Encodable> Encodable for Cow<'a, [T]>
where [T]: ToOwned<Owned = Vec<T>>
{
impl<'a, T:Encodable> Encodable for Cow<'a, [T]> where [T]: ToOwned<Owned = Vec<T>> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
@ -580,9 +618,7 @@ where [T]: ToOwned<Owned = Vec<T>>
}
}
impl<T:Decodable+ToOwned> Decodable for Cow<'static, [T]>
where [T]: ToOwned<Owned = Vec<T>>
{
impl<T:Decodable+ToOwned> Decodable for Cow<'static, [T]> where [T]: ToOwned<Owned = Vec<T>> {
fn decode<D: Decoder>(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
d.read_seq(|d, len| {
let mut v = Vec::with_capacity(len);
@ -685,8 +721,7 @@ macro_rules! tuple {
let len: usize = count_idents!($($name,)*);
d.read_tuple(len, |d| {
let mut i = 0;
let ret = ($(d.read_tuple_arg({ i+=1; i-1 },
|d| -> Result<$name,D::Error> {
let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> {
Decodable::decode(d)
})?,)*);
Ok(ret)
@ -778,13 +813,11 @@ pub trait SpecializationError {
/// `T` is the type being encoded/decoded, and
/// the arguments are the names of the trait
/// and method that should've been overridden.
fn not_found<S, T: ?Sized>(trait_name: &'static str,
method_name: &'static str) -> Self;
fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> Self;
}
impl<E> SpecializationError for E {
default fn not_found<S, T: ?Sized>(trait_name: &'static str,
method_name: &'static str) -> E {
default fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> E {
panic!("missing specialization: `<{} as {}<{}>>::{}` not overridden",
unsafe { intrinsics::type_name::<S>() },
trait_name,

View File

@ -22,7 +22,6 @@ core = { path = "../libcore" }
libc = { path = "../rustc/libc_shim" }
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
std_unicode = { path = "../libstd_unicode" }
unwind = { path = "../libunwind" }
[dev-dependencies]

View File

@ -154,180 +154,6 @@ pub trait AsciiExt {
/// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase
#[stable(feature = "ascii", since = "1.9.0")]
fn make_ascii_lowercase(&mut self);
/// Checks if the value is an ASCII alphabetic character:
/// U+0041 'A' ... U+005A 'Z' or U+0061 'a' ... U+007A 'z'.
/// For strings, true if all characters in the string are
/// ASCII alphabetic.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_alphabetic)`.
/// For `str` use `.bytes().all(u8::is_ascii_alphabetic)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_alphabetic(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII uppercase character:
/// U+0041 'A' ... U+005A 'Z'.
/// For strings, true if all characters in the string are
/// ASCII uppercase.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_uppercase)`.
/// For `str` use `.bytes().all(u8::is_ascii_uppercase)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_uppercase(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII lowercase character:
/// U+0061 'a' ... U+007A 'z'.
/// For strings, true if all characters in the string are
/// ASCII lowercase.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_lowercase)`.
/// For `str` use `.bytes().all(u8::is_ascii_lowercase)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_lowercase(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII alphanumeric character:
/// U+0041 'A' ... U+005A 'Z', U+0061 'a' ... U+007A 'z', or
/// U+0030 '0' ... U+0039 '9'.
/// For strings, true if all characters in the string are
/// ASCII alphanumeric.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_alphanumeric)`.
/// For `str` use `.bytes().all(u8::is_ascii_alphanumeric)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_alphanumeric(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII decimal digit:
/// U+0030 '0' ... U+0039 '9'.
/// For strings, true if all characters in the string are
/// ASCII digits.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_digit)`.
/// For `str` use `.bytes().all(u8::is_ascii_digit)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_digit(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII hexadecimal digit:
/// U+0030 '0' ... U+0039 '9', U+0041 'A' ... U+0046 'F', or
/// U+0061 'a' ... U+0066 'f'.
/// For strings, true if all characters in the string are
/// ASCII hex digits.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_hexdigit)`.
/// For `str` use `.bytes().all(u8::is_ascii_hexdigit)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_hexdigit(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII punctuation character:
///
/// U+0021 ... U+002F `! " # $ % & ' ( ) * + , - . /`
/// U+003A ... U+0040 `: ; < = > ? @`
/// U+005B ... U+0060 ``[ \\ ] ^ _ ` ``
/// U+007B ... U+007E `{ | } ~`
///
/// For strings, true if all characters in the string are
/// ASCII punctuation.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_punctuation)`.
/// For `str` use `.bytes().all(u8::is_ascii_punctuation)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_punctuation(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII graphic character:
/// U+0021 '!' ... U+007E '~'.
/// For strings, true if all characters in the string are
/// ASCII graphic characters.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_graphic)`.
/// For `str` use `.bytes().all(u8::is_ascii_graphic)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_graphic(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII whitespace character:
/// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
/// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
/// For strings, true if all characters in the string are
/// ASCII whitespace.
///
/// Rust uses the WhatWG Infra Standard's [definition of ASCII
/// whitespace][infra-aw]. There are several other definitions in
/// wide use. For instance, [the POSIX locale][pct] includes
/// U+000B VERTICAL TAB as well as all the above characters,
/// but—from the very same specification—[the default rule for
/// "field splitting" in the Bourne shell][bfs] considers *only*
/// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
///
/// If you are writing a program that will process an existing
/// file format, check what that format's definition of whitespace is
/// before using this function.
///
/// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
/// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
/// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_whitespace)`.
/// For `str` use `.bytes().all(u8::is_ascii_whitespace)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_whitespace(&self) -> bool { unimplemented!(); }
/// Checks if the value is an ASCII control character:
/// U+0000 NUL ... U+001F UNIT SEPARATOR, or U+007F DELETE.
/// Note that most ASCII whitespace characters are control
/// characters, but SPACE is not.
///
/// # Note
///
/// This method will be deprecated in favor of the identically-named
/// inherent methods on `u8` and `char`.
/// For `[u8]` use `.iter().all(u8::is_ascii_control)`.
/// For `str` use `.bytes().all(u8::is_ascii_control)`.
#[unstable(feature = "ascii_ctype", issue = "39658")]
#[rustc_deprecated(since = "1.26.0", reason = "use inherent methods instead")]
fn is_ascii_control(&self) -> bool { unimplemented!(); }
}
macro_rules! delegating_ascii_methods {
@ -352,47 +178,12 @@ macro_rules! delegating_ascii_methods {
}
}
macro_rules! delegating_ascii_ctype_methods {
() => {
#[inline]
fn is_ascii_alphabetic(&self) -> bool { self.is_ascii_alphabetic() }
#[inline]
fn is_ascii_uppercase(&self) -> bool { self.is_ascii_uppercase() }
#[inline]
fn is_ascii_lowercase(&self) -> bool { self.is_ascii_lowercase() }
#[inline]
fn is_ascii_alphanumeric(&self) -> bool { self.is_ascii_alphanumeric() }
#[inline]
fn is_ascii_digit(&self) -> bool { self.is_ascii_digit() }
#[inline]
fn is_ascii_hexdigit(&self) -> bool { self.is_ascii_hexdigit() }
#[inline]
fn is_ascii_punctuation(&self) -> bool { self.is_ascii_punctuation() }
#[inline]
fn is_ascii_graphic(&self) -> bool { self.is_ascii_graphic() }
#[inline]
fn is_ascii_whitespace(&self) -> bool { self.is_ascii_whitespace() }
#[inline]
fn is_ascii_control(&self) -> bool { self.is_ascii_control() }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl AsciiExt for u8 {
type Owned = u8;
delegating_ascii_methods!();
delegating_ascii_ctype_methods!();
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -401,7 +192,6 @@ impl AsciiExt for char {
type Owned = char;
delegating_ascii_methods!();
delegating_ascii_ctype_methods!();
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -410,56 +200,6 @@ impl AsciiExt for [u8] {
type Owned = Vec<u8>;
delegating_ascii_methods!();
#[inline]
fn is_ascii_alphabetic(&self) -> bool {
self.iter().all(|b| b.is_ascii_alphabetic())
}
#[inline]
fn is_ascii_uppercase(&self) -> bool {
self.iter().all(|b| b.is_ascii_uppercase())
}
#[inline]
fn is_ascii_lowercase(&self) -> bool {
self.iter().all(|b| b.is_ascii_lowercase())
}
#[inline]
fn is_ascii_alphanumeric(&self) -> bool {
self.iter().all(|b| b.is_ascii_alphanumeric())
}
#[inline]
fn is_ascii_digit(&self) -> bool {
self.iter().all(|b| b.is_ascii_digit())
}
#[inline]
fn is_ascii_hexdigit(&self) -> bool {
self.iter().all(|b| b.is_ascii_hexdigit())
}
#[inline]
fn is_ascii_punctuation(&self) -> bool {
self.iter().all(|b| b.is_ascii_punctuation())
}
#[inline]
fn is_ascii_graphic(&self) -> bool {
self.iter().all(|b| b.is_ascii_graphic())
}
#[inline]
fn is_ascii_whitespace(&self) -> bool {
self.iter().all(|b| b.is_ascii_whitespace())
}
#[inline]
fn is_ascii_control(&self) -> bool {
self.iter().all(|b| b.is_ascii_control())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -468,54 +208,4 @@ impl AsciiExt for str {
type Owned = String;
delegating_ascii_methods!();
#[inline]
fn is_ascii_alphabetic(&self) -> bool {
self.bytes().all(|b| b.is_ascii_alphabetic())
}
#[inline]
fn is_ascii_uppercase(&self) -> bool {
self.bytes().all(|b| b.is_ascii_uppercase())
}
#[inline]
fn is_ascii_lowercase(&self) -> bool {
self.bytes().all(|b| b.is_ascii_lowercase())
}
#[inline]
fn is_ascii_alphanumeric(&self) -> bool {
self.bytes().all(|b| b.is_ascii_alphanumeric())
}
#[inline]
fn is_ascii_digit(&self) -> bool {
self.bytes().all(|b| b.is_ascii_digit())
}
#[inline]
fn is_ascii_hexdigit(&self) -> bool {
self.bytes().all(|b| b.is_ascii_hexdigit())
}
#[inline]
fn is_ascii_punctuation(&self) -> bool {
self.bytes().all(|b| b.is_ascii_punctuation())
}
#[inline]
fn is_ascii_graphic(&self) -> bool {
self.bytes().all(|b| b.is_ascii_graphic())
}
#[inline]
fn is_ascii_whitespace(&self) -> bool {
self.bytes().all(|b| b.is_ascii_whitespace())
}
#[inline]
fn is_ascii_control(&self) -> bool {
self.bytes().all(|b| b.is_ascii_control())
}
}

View File

@ -642,6 +642,12 @@ impl fmt::Debug for CString {
#[stable(feature = "cstring_into", since = "1.7.0")]
impl From<CString> for Vec<u8> {
/// Converts a [`CString`] into a [`Vec`]`<u8>`.
///
/// The conversion consumes the [`CString`], and removes the terminating NUL byte.
///
/// [`Vec`]: ../vec/struct.Vec.html
/// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: CString) -> Vec<u8> {
s.into_bytes()
@ -700,6 +706,10 @@ impl<'a> From<&'a CStr> for Box<CStr> {
#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
@ -716,6 +726,10 @@ impl Clone for Box<CStr> {
#[stable(feature = "box_from_c_string", since = "1.20.0")]
impl From<CString> for Box<CStr> {
/// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Box`]: ../boxed/struct.Box.html
#[inline]
fn from(s: CString) -> Box<CStr> {
s.into_boxed_c_str()
@ -748,6 +762,10 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
/// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Arc`]: ../sync/struct.Arc.html
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
@ -766,6 +784,10 @@ impl<'a> From<&'a CStr> for Arc<CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
/// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Rc`]: ../rc/struct.Rc.html
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
@ -839,6 +861,10 @@ impl fmt::Display for NulError {
#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
/// Converts a [`NulError`] into a [`io::Error`].
///
/// [`NulError`]: ../ffi/struct.NulError.html
/// [`io::Error`]: ../io/struct.Error.html
fn from(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput,
"data provided contains a nul byte")

View File

@ -348,6 +348,12 @@ impl OsString {
#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for OsString {
/// Converts a [`String`] into a [`OsString`].
///
/// The conversion copies the data, and includes an allocation on the heap.
///
/// [`String`]: ../string/struct.String.html
/// [`OsString`]: struct.OsString.html
fn from(s: String) -> OsString {
OsString { inner: Buf::from_string(s) }
}
@ -630,6 +636,10 @@ impl<'a> From<&'a OsStr> for Box<OsStr> {
#[stable(feature = "os_string_from_box", since = "1.18.0")]
impl From<Box<OsStr>> for OsString {
/// Converts a `Box<OsStr>` into a `OsString` without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsString`]: ../ffi/struct.OsString.html
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
@ -637,6 +647,10 @@ impl From<Box<OsStr>> for OsString {
#[stable(feature = "box_from_os_string", since = "1.20.0")]
impl From<OsString> for Box<OsStr> {
/// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsString`]: ../ffi/struct.OsString.html
fn from(s: OsString) -> Box<OsStr> {
s.into_boxed_os_str()
}
@ -652,6 +666,10 @@ impl Clone for Box<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
/// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
///
/// [`Arc`]: ../sync/struct.Arc.html
/// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
@ -670,6 +688,10 @@ impl<'a> From<&'a OsStr> for Arc<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
/// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
///
/// [`Rc`]: ../rc/struct.Rc.html
/// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();

View File

@ -154,33 +154,6 @@ impl<R: Read> BufReader<R> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
/// Returns `true` if there are no bytes in the internal buffer.
///
/// # Examples
//
/// ```no_run
/// # #![feature(bufreader_is_empty)]
/// use std::io::BufReader;
/// use std::io::BufRead;
/// use std::fs::File;
///
/// fn main() -> std::io::Result<()> {
/// let f1 = File::open("log.txt")?;
/// let mut reader = BufReader::new(f1);
/// assert!(reader.is_empty());
///
/// if reader.fill_buf()?.len() > 0 {
/// assert!(!reader.is_empty());
/// }
/// Ok(())
/// }
/// ```
#[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
#[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")]
pub fn is_empty(&self) -> bool {
self.buffer().is_empty()
}
/// Returns a reference to the internally buffered data.
///
/// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
@ -1265,25 +1238,6 @@ mod tests {
assert_eq!(reader.read(&mut buf).unwrap(), 0);
}
#[test]
#[allow(deprecated)]
fn read_char_buffered() {
let buf = [195, 159];
let reader = BufReader::with_capacity(1, &buf[..]);
assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß');
}
#[test]
#[allow(deprecated)]
fn test_chars() {
let buf = [195, 159, b'a'];
let reader = BufReader::with_capacity(1, &buf[..]);
let mut it = reader.chars();
assert_eq!(it.next().unwrap().unwrap(), 'ß');
assert_eq!(it.next().unwrap().unwrap(), 'a');
assert!(it.next().is_none());
}
#[test]
#[should_panic]
fn dont_panic_in_drop_on_panicked_flush() {

View File

@ -550,26 +550,6 @@ mod tests {
assert_eq!(reader.read(&mut buf).unwrap(), 0);
}
#[test]
#[allow(deprecated)]
fn test_read_char() {
let b = &b"Vi\xE1\xBB\x87t"[..];
let mut c = Cursor::new(b).chars();
assert_eq!(c.next().unwrap().unwrap(), 'V');
assert_eq!(c.next().unwrap().unwrap(), 'i');
assert_eq!(c.next().unwrap().unwrap(), 'ệ');
assert_eq!(c.next().unwrap().unwrap(), 't');
assert!(c.next().is_none());
}
#[test]
#[allow(deprecated)]
fn test_read_bad_char() {
let b = &b"\x80"[..];
let mut c = Cursor::new(b).chars();
assert!(c.next().unwrap().is_err());
}
#[test]
fn seek_past_end() {
let buf = [0xff];

View File

@ -270,10 +270,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
use cmp;
use core::str as core_str;
use error as std_error;
use fmt;
use result;
use str;
use memchr;
use ptr;
@ -800,53 +797,6 @@ pub trait Read {
Bytes { inner: self }
}
/// Transforms this `Read` instance to an [`Iterator`] over [`char`]s.
///
/// This adaptor will attempt to interpret this reader as a UTF-8 encoded
/// sequence of characters. The returned iterator will return [`None`] once
/// EOF is reached for this reader. Otherwise each element yielded will be a
/// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error
/// occurred or where decoding failed.
///
/// Currently this adaptor will discard intermediate data read, and should
/// be avoided if this is not desired.
///
/// # Examples
///
/// [`File`]s implement `Read`:
///
/// [`File`]: ../fs/struct.File.html
/// [`Iterator`]: ../../std/iter/trait.Iterator.html
/// [`Result`]: ../../std/result/enum.Result.html
/// [`char`]: ../../std/primitive.char.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
///
/// ```no_run
/// #![feature(io)]
/// use std::io;
/// use std::io::prelude::*;
/// use std::fs::File;
///
/// fn main() -> io::Result<()> {
/// let mut f = File::open("foo.txt")?;
///
/// for c in f.chars() {
/// println!("{}", c.unwrap());
/// }
/// Ok(())
/// }
/// ```
#[unstable(feature = "io", reason = "the semantics of a partial read/write \
of where errors happen is currently \
unclear and may change",
issue = "27802")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[allow(deprecated)]
fn chars(self) -> Chars<Self> where Self: Sized {
Chars { inner: self }
}
/// Creates an adaptor which will chain this stream with another.
///
/// The returned `Read` instance will first read all bytes from this object
@ -2005,104 +1955,6 @@ impl<R: Read> Iterator for Bytes<R> {
}
}
/// An iterator over the `char`s of a reader.
///
/// This struct is generally created by calling [`chars`][chars] on a reader.
/// Please see the documentation of `chars()` for more details.
///
/// [chars]: trait.Read.html#method.chars
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[derive(Debug)]
#[allow(deprecated)]
pub struct Chars<R> {
inner: R,
}
/// An enumeration of possible errors that can be generated from the `Chars`
/// adapter.
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[rustc_deprecated(since = "1.27.0", reason = "Use str::from_utf8 instead:
https://doc.rust-lang.org/nightly/std/str/struct.Utf8Error.html#examples")]
#[derive(Debug)]
#[allow(deprecated)]
pub enum CharsError {
/// Variant representing that the underlying stream was read successfully
/// but it did not contain valid utf8 data.
NotUtf8,
/// Variant representing that an I/O error occurred.
Other(Error),
}
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[allow(deprecated)]
impl<R: Read> Iterator for Chars<R> {
type Item = result::Result<char, CharsError>;
fn next(&mut self) -> Option<result::Result<char, CharsError>> {
let first_byte = match read_one_byte(&mut self.inner)? {
Ok(b) => b,
Err(e) => return Some(Err(CharsError::Other(e))),
};
let width = core_str::utf8_char_width(first_byte);
if width == 1 { return Some(Ok(first_byte as char)) }
if width == 0 { return Some(Err(CharsError::NotUtf8)) }
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;
while start < width {
match self.inner.read(&mut buf[start..width]) {
Ok(0) => return Some(Err(CharsError::NotUtf8)),
Ok(n) => start += n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) => return Some(Err(CharsError::Other(e))),
}
}
}
Some(match str::from_utf8(&buf[..width]).ok() {
Some(s) => Ok(s.chars().next().unwrap()),
None => Err(CharsError::NotUtf8),
})
}
}
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[allow(deprecated)]
impl std_error::Error for CharsError {
fn description(&self) -> &str {
match *self {
CharsError::NotUtf8 => "invalid utf8 encoding",
CharsError::Other(ref e) => std_error::Error::description(e),
}
}
fn cause(&self) -> Option<&dyn std_error::Error> {
match *self {
CharsError::NotUtf8 => None,
CharsError::Other(ref e) => e.cause(),
}
}
}
#[unstable(feature = "io", reason = "awaiting stability of Read::chars",
issue = "27802")]
#[allow(deprecated)]
impl fmt::Display for CharsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CharsError::NotUtf8 => {
"byte stream did not contain valid utf8".fmt(f)
}
CharsError::Other(ref e) => e.fmt(f),
}
}
}
/// An iterator over the contents of an instance of `BufRead` split on a
/// particular byte.
///

389
src/libstd/os/hermit/fs.rs Normal file
View File

@ -0,0 +1,389 @@
// 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.
#![stable(feature = "metadata_ext", since = "1.1.0")]
use libc;
use fs::Metadata;
use sys_common::AsInner;
#[allow(deprecated)]
use os::hermit::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains
/// the raw information returned by the OS.
///
/// The contents of the returned [`stat`] are **not** consistent across
/// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
/// cross-Unix abstractions contained within the raw stat.
///
/// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// let stat = meta.as_raw_stat();
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext", since = "1.1.0")]
#[rustc_deprecated(since = "1.8.0",
reason = "deprecated in favor of the accessor \
methods of this trait")]
#[allow(deprecated)]
fn as_raw_stat(&self) -> &raw::stat;
/// Returns the device ID on which this file resides.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_dev());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_dev(&self) -> u64;
/// Returns the inode number.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ino());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ino(&self) -> u64;
/// Returns the file type and mode.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mode());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mode(&self) -> u32;
/// Returns the number of hard links to file.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_nlink());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_nlink(&self) -> u64;
/// Returns the user ID of the file owner.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_uid());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_uid(&self) -> u32;
/// Returns the group ID of the file owner.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_gid());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_gid(&self) -> u32;
/// Returns the device ID that this file represents. Only relevant for special file.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_rdev());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_rdev(&self) -> u64;
/// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
///
/// The size of a symbolic link is the length of the pathname it contains,
/// without a terminating null byte.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_size());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_size(&self) -> u64;
/// Returns the last access time.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_atime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime(&self) -> i64;
/// Returns the last access time, nano seconds part.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_atime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_atime_nsec(&self) -> i64;
/// Returns the last modification time.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mtime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime(&self) -> i64;
/// Returns the last modification time, nano seconds part.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_mtime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_mtime_nsec(&self) -> i64;
/// Returns the last status change time.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ctime());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime(&self) -> i64;
/// Returns the last status change time, nano seconds part.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_ctime_nsec());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_ctime_nsec(&self) -> i64;
/// Returns the "preferred" blocksize for efficient filesystem I/O.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_blksize());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blksize(&self) -> u64;
/// Returns the number of blocks allocated to the file, 512-byte units.
///
/// # Examples
///
/// ```no_run
/// use std::fs;
/// use std::io;
/// use std::os::linux::fs::MetadataExt;
///
/// fn main() -> io::Result<()> {
/// let meta = fs::metadata("some_file")?;
/// println!("{}", meta.st_blocks());
/// Ok(())
/// }
/// ```
#[stable(feature = "metadata_ext2", since = "1.8.0")]
fn st_blocks(&self) -> u64;
}
#[stable(feature = "metadata_ext", since = "1.1.0")]
impl MetadataExt for Metadata {
#[allow(deprecated)]
fn as_raw_stat(&self) -> &raw::stat {
unsafe {
&*(self.as_inner().as_inner() as *const libc::stat64
as *const raw::stat)
}
}
fn st_dev(&self) -> u64 {
self.as_inner().as_inner().st_dev as u64
}
fn st_ino(&self) -> u64 {
self.as_inner().as_inner().st_ino as u64
}
fn st_mode(&self) -> u32 {
self.as_inner().as_inner().st_mode as u32
}
fn st_nlink(&self) -> u64 {
self.as_inner().as_inner().st_nlink as u64
}
fn st_uid(&self) -> u32 {
self.as_inner().as_inner().st_uid as u32
}
fn st_gid(&self) -> u32 {
self.as_inner().as_inner().st_gid as u32
}
fn st_rdev(&self) -> u64 {
self.as_inner().as_inner().st_rdev as u64
}
fn st_size(&self) -> u64 {
self.as_inner().as_inner().st_size as u64
}
fn st_atime(&self) -> i64 {
self.as_inner().as_inner().st_atime as i64
}
fn st_atime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_atime_nsec as i64
}
fn st_mtime(&self) -> i64 {
self.as_inner().as_inner().st_mtime as i64
}
fn st_mtime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_mtime_nsec as i64
}
fn st_ctime(&self) -> i64 {
self.as_inner().as_inner().st_ctime as i64
}
fn st_ctime_nsec(&self) -> i64 {
self.as_inner().as_inner().st_ctime_nsec as i64
}
fn st_blksize(&self) -> u64 {
self.as_inner().as_inner().st_blksize as u64
}
fn st_blocks(&self) -> u64 {
self.as_inner().as_inner().st_blocks as u64
}
}

View File

@ -0,0 +1,16 @@
// 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.
//! HermitCore-specific definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
pub mod raw;
pub mod fs;

View File

@ -0,0 +1,27 @@
// 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.
//! HermitCore-specific raw type definitions
#![stable(feature = "raw_ext", since = "1.1.0")]
#![rustc_deprecated(since = "1.8.0",
reason = "these type aliases are no longer supported by \
the standard library, the `libc` crate on \
crates.io should be used instead for the correct \
definitions")]
#![allow(deprecated)]
#![allow(missing_debug_implementations)]
#[stable(feature = "pthread_t", since = "1.8.0")]
pub use libc::pthread_t;
#[doc(inline)]
#[stable(feature = "raw_ext", since = "1.1.0")]
pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};

View File

@ -47,6 +47,7 @@ cfg_if! {
#[cfg(target_os = "solaris")] pub mod solaris;
#[cfg(target_os = "emscripten")] pub mod emscripten;
#[cfg(target_os = "fuchsia")] pub mod fuchsia;
#[cfg(target_os = "hermit")] pub mod hermit;
#[cfg(any(target_os = "redox", unix))]
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -66,7 +66,8 @@ impl DoubleEndedIterator for Args {
target_os = "emscripten",
target_os = "haiku",
target_os = "l4re",
target_os = "fuchsia"))]
target_os = "fuchsia",
target_os = "hermit"))]
mod imp {
use os::unix::prelude::*;
use ptr;

View File

@ -41,13 +41,15 @@ impl Condvar {
#[cfg(any(target_os = "macos",
target_os = "ios",
target_os = "l4re",
target_os = "android"))]
target_os = "android",
target_os = "hermit"))]
pub unsafe fn init(&mut self) {}
#[cfg(not(any(target_os = "macos",
target_os = "ios",
target_os = "l4re",
target_os = "android")))]
target_os = "android",
target_os = "hermit")))]
pub unsafe fn init(&mut self) {
use mem;
let mut attr: libc::pthread_condattr_t = mem::uninitialized();
@ -83,7 +85,10 @@ impl Condvar {
// where we configure condition variable to use monotonic clock (instead of
// default system clock). This approach avoids all problems that result
// from changes made to the system time.
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
#[cfg(not(any(target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "hermit")))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
use mem;
@ -113,7 +118,7 @@ impl Condvar {
// This implementation is modeled after libcxx's condition_variable
// https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
use ptr;
use time::Instant;

View File

@ -172,3 +172,14 @@ pub mod os {
pub const EXE_SUFFIX: &'static str = "";
pub const EXE_EXTENSION: &'static str = "";
}
#[cfg(target_os = "hermit")]
pub mod os {
pub const FAMILY: &'static str = "unix";
pub const OS: &'static str = "hermit";
pub const DLL_PREFIX: &'static str = "lib";
pub const DLL_SUFFIX: &'static str = ".so";
pub const DLL_EXTENSION: &'static str = "so";
pub const EXE_SUFFIX: &'static str = "";
pub const EXE_EXTENSION: &'static str = "";
}

View File

@ -20,7 +20,7 @@
// fallback implementation to use as well.
//
// Due to rust-lang/rust#18804, make sure this is not generic!
#[cfg(any(target_os = "linux", target_os = "fuchsia"))]
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
use libc;
use mem;

View File

@ -325,12 +325,12 @@ impl DirEntry {
lstat(&self.path())
}
#[cfg(any(target_os = "solaris", target_os = "haiku"))]
#[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))]
pub fn file_type(&self) -> io::Result<FileType> {
lstat(&self.path()).map(|m| m.file_type())
}
#[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
#[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
@ -352,7 +352,8 @@ impl DirEntry {
target_os = "solaris",
target_os = "haiku",
target_os = "l4re",
target_os = "fuchsia"))]
target_os = "fuchsia",
target_os = "hermit"))]
pub fn ino(&self) -> u64 {
self.entry.d_ino as u64
}
@ -383,7 +384,8 @@ impl DirEntry {
target_os = "linux",
target_os = "emscripten",
target_os = "l4re",
target_os = "haiku"))]
target_os = "haiku",
target_os = "hermit"))]
fn name_bytes(&self) -> &[u8] {
unsafe {
CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()

View File

@ -28,6 +28,7 @@ use libc;
#[cfg(all(not(dox), target_os = "emscripten"))] pub use os::emscripten as platform;
#[cfg(all(not(dox), target_os = "fuchsia"))] pub use os::fuchsia as platform;
#[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform;
#[cfg(all(not(dox), target_os = "hermit"))] pub use os::hermit as platform;
pub use self::rand::hashmap_random_keys;
pub use libc::strlen;

View File

@ -47,6 +47,7 @@ extern {
target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_os = "hermit",
target_env = "newlib"),
link_name = "__errno")]
#[cfg_attr(target_os = "solaris", link_name = "___errno")]
@ -376,7 +377,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
}
}
#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
pub fn current_exe() -> io::Result<PathBuf> {
use io::ErrorKind;
Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))

View File

@ -138,7 +138,8 @@ impl Thread {
target_os = "solaris",
target_os = "haiku",
target_os = "l4re",
target_os = "emscripten"))]
target_os = "emscripten",
target_os = "hermit"))]
pub fn set_name(_name: &CStr) {
// Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
}

View File

@ -345,9 +345,9 @@ mod inner {
}
}
#[cfg(not(target_os = "dragonfly"))]
#[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))]
pub type clock_t = libc::c_int;
#[cfg(target_os = "dragonfly")]
#[cfg(any(target_os = "dragonfly", target_os = "hermit"))]
pub type clock_t = libc::c_ulong;
fn now(clock: clock_t) -> Timespec {

View File

@ -731,7 +731,8 @@ const NOTIFIED: usize = 2;
/// specifying a maximum time to block the thread for.
///
/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
/// if it wasn't already.
/// if it wasn't already. Because the token is initially absent, [`unpark`]
/// followed by [`park`] will result in the second call returning immediately.
///
/// In other words, each [`Thread`] acts a bit like a spinlock that can be
/// locked and unlocked using `park` and `unpark`.
@ -766,6 +767,8 @@ const NOTIFIED: usize = 2;
/// // Let some time pass for the thread to be spawned.
/// thread::sleep(Duration::from_millis(10));
///
/// // There is no race condition here, if `unpark`
/// // happens first, `park` will return immediately.
/// println!("Unpark the thread");
/// parked_thread.thread().unpark();
///

View File

@ -1,14 +0,0 @@
[package]
authors = ["The Rust Project Developers"]
name = "std_unicode"
version = "0.0.0"
[lib]
name = "std_unicode"
path = "lib.rs"
test = false
bench = false
[dependencies]
core = { path = "../libcore" }
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

View File

@ -1,36 +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.
//! # The Unicode Library
//!
//! Unicode-intensive functions for `char` and `str` types.
//!
//! This crate provides a collection of Unicode-related functionality,
//! including decompositions, conversions, etc., and provides traits
//! implementing these functions for the `char` and `str` types.
//!
//! The functionality included here is only that which is necessary to
//! provide for basic string-related manipulations. This crate does not
//! (yet) aim to provide a full set of Unicode tables.
#![unstable(feature = "unicode", issue = "27783")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/",
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
#![no_std]
#![feature(unicode_internals)]
#![feature(staged_api)]
#![rustc_deprecated(since = "1.27.0", reason = "moved into libcore")]
pub use core::unicode::*;

View File

@ -396,7 +396,7 @@ declare_features! (
// Infer outlives requirements; RFC 2093
(active, infer_outlives_requirements, "1.26.0", Some(44493), None),
// Infer outlives requirements; RFC 2093
// Infer static outlives requirements; RFC 2093
(active, infer_static_outlives_requirements, "1.26.0", Some(44493), None),
// Multiple patterns with `|` in `if let` and `while let`

View File

@ -774,31 +774,41 @@ pub mod shell {
#[derive(Clone, PartialEq, Debug)]
pub enum Substitution<'a> {
Ordinal(u8),
Name(&'a str),
Escape,
Ordinal(u8, (usize, usize)),
Name(&'a str, (usize, usize)),
Escape((usize, usize)),
}
impl<'a> Substitution<'a> {
pub fn as_str(&self) -> String {
match *self {
Substitution::Ordinal(n) => format!("${}", n),
Substitution::Name(n) => format!("${}", n),
Substitution::Escape => "$$".into(),
match self {
Substitution::Ordinal(n, _) => format!("${}", n),
Substitution::Name(n, _) => format!("${}", n),
Substitution::Escape(_) => "$$".into(),
}
}
pub fn position(&self) -> Option<(usize, usize)> {
match *self {
_ => None,
match self {
Substitution::Ordinal(_, pos) |
Substitution::Name(_, pos) |
Substitution::Escape(pos) => Some(*pos),
}
}
pub fn set_position(&mut self, start: usize, end: usize) {
match self {
Substitution::Ordinal(_, ref mut pos) |
Substitution::Name(_, ref mut pos) |
Substitution::Escape(ref mut pos) => *pos = (start, end),
}
}
pub fn translate(&self) -> Option<String> {
match *self {
Substitution::Ordinal(n) => Some(format!("{{{}}}", n)),
Substitution::Name(n) => Some(format!("{{{}}}", n)),
Substitution::Escape => None,
Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)),
Substitution::Name(n, _) => Some(format!("{{{}}}", n)),
Substitution::Escape(_) => None,
}
}
}
@ -807,20 +817,26 @@ pub mod shell {
pub fn iter_subs(s: &str) -> Substitutions {
Substitutions {
s,
pos: 0,
}
}
/// Iterator over substitutions in a string.
pub struct Substitutions<'a> {
s: &'a str,
pos: usize,
}
impl<'a> Iterator for Substitutions<'a> {
type Item = Substitution<'a>;
fn next(&mut self) -> Option<Self::Item> {
match parse_next_substitution(self.s) {
Some((sub, tail)) => {
Some((mut sub, tail)) => {
self.s = tail;
if let Some((start, end)) = sub.position() {
sub.set_position(start + self.pos, end + self.pos);
self.pos += end;
}
Some(sub)
},
None => None,
@ -837,15 +853,15 @@ pub mod shell {
let at = {
let start = s.find('$')?;
match s[start+1..].chars().next()? {
'$' => return Some((Substitution::Escape, &s[start+2..])),
'$' => return Some((Substitution::Escape((start, start+2)), &s[start+2..])),
c @ '0' ..= '9' => {
let n = (c as u8) - b'0';
return Some((Substitution::Ordinal(n), &s[start+2..]));
return Some((Substitution::Ordinal(n, (start, start+2)), &s[start+2..]));
},
_ => {/* fall-through */},
}
Cur::new_at_start(&s[start..])
Cur::new_at(&s[..], start)
};
let at = at.at_next_cp()?;
@ -855,7 +871,10 @@ pub mod shell {
None
} else {
let end = at_next_cp_while(inner, is_ident_tail);
Some((Substitution::Name(at.slice_between(end).unwrap()), end.slice_after()))
let slice = at.slice_between(end).unwrap();
let start = at.at - 1;
let end_pos = at.at + slice.len();
Some((Substitution::Name(slice, (start, end_pos)), end.slice_after()))
}
}
@ -907,24 +926,24 @@ pub mod shell {
fn test_escape() {
assert_eq!(pns("has no escapes"), None);
assert_eq!(pns("has no escapes, either $"), None);
assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape, " escape")));
assert_eq!(pns("$$ leading escape"), Some((S::Escape, " leading escape")));
assert_eq!(pns("trailing escape $$"), Some((S::Escape, "")));
assert_eq!(pns("*so* has a $$ escape"), Some((S::Escape((11, 13)), " escape")));
assert_eq!(pns("$$ leading escape"), Some((S::Escape((0, 2)), " leading escape")));
assert_eq!(pns("trailing escape $$"), Some((S::Escape((16, 18)), "")));
}
#[test]
fn test_parse() {
macro_rules! assert_pns_eq_sub {
($in_:expr, $kind:ident($arg:expr)) => {
assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into()), "!")))
($in_:expr, $kind:ident($arg:expr, $pos:expr)) => {
assert_eq!(pns(concat!($in_, "!")), Some((S::$kind($arg.into(), $pos), "!")))
};
}
assert_pns_eq_sub!("$0", Ordinal(0));
assert_pns_eq_sub!("$1", Ordinal(1));
assert_pns_eq_sub!("$9", Ordinal(9));
assert_pns_eq_sub!("$N", Name("N"));
assert_pns_eq_sub!("$NAME", Name("NAME"));
assert_pns_eq_sub!("$0", Ordinal(0, (0, 2)));
assert_pns_eq_sub!("$1", Ordinal(1, (0, 2)));
assert_pns_eq_sub!("$9", Ordinal(9, (0, 2)));
assert_pns_eq_sub!("$N", Name("N", (0, 2)));
assert_pns_eq_sub!("$NAME", Name("NAME", (0, 5)));
}
#[test]
@ -961,13 +980,6 @@ mod strcursor {
}
impl<'a> StrCursor<'a> {
pub fn new_at_start(s: &'a str) -> StrCursor<'a> {
StrCursor {
s,
at: 0,
}
}
pub fn new_at(s: &'a str, at: usize) -> StrCursor<'a> {
StrCursor {
s,

View File

@ -1075,7 +1075,7 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
auto MOrErr = getLazyBitcodeModule(Memory, Context, true, true);
if (!MOrErr)
return std::move(MOrErr);
return MOrErr;
// The rest of this closure is a workaround for
// https://bugs.llvm.org/show_bug.cgi?id=38184 where during ThinLTO imports
@ -1093,14 +1093,14 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M) {
// shouldn't be a perf hit.
if (Error Err = (*MOrErr)->materializeMetadata()) {
Expected<std::unique_ptr<Module>> Ret(std::move(Err));
return std::move(Ret);
return Ret;
}
auto *WasmCustomSections = (*MOrErr)->getNamedMetadata("wasm.custom_sections");
if (WasmCustomSections)
WasmCustomSections->eraseFromParent();
return std::move(MOrErr);
return MOrErr;
};
FunctionImporter Importer(Data->Index, Loader);
Expected<bool> Result = Importer.importFunctions(Mod, ImportList);

View File

@ -0,0 +1,42 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// no-system-llvm
// compile-flags: -O -C panic=abort
#![crate_type = "lib"]
fn search<T: Ord + Eq>(arr: &mut [T], a: &T) -> Result<usize, ()> {
match arr.iter().position(|x| x == a) {
Some(p) => {
Ok(p)
},
None => Err(()),
}
}
// CHECK-LABEL: @position_no_bounds_check
#[no_mangle]
pub fn position_no_bounds_check(y: &mut [u32], x: &u32, z: &u32) -> bool {
// This contains "call assume" so we cannot just rule out all calls
// CHECK-NOT: panic_bounds_check
if let Ok(p) = search(y, x) {
y[p] == *z
} else {
false
}
}
// just to make sure that panicking really emits "panic_bounds_check" somewhere in the IR
// CHECK-LABEL: @test_check
#[no_mangle]
pub fn test_check(y: &[i32]) -> i32 {
// CHECK: panic_bounds_check
y[12]
}

View File

@ -11,6 +11,7 @@
// Checks that we correctly codegen extern "C" functions returning structs.
// See issue #52638.
// only-sparc64
// compile-flags: -O --target=sparc64-unknown-linux-gnu --crate-type=rlib
#![feature(no_core, lang_items)]
#![no_core]

View File

@ -25,7 +25,7 @@ fn main() {
#[cfg(not(target_arch = "asmjs"))]
{
const BE_U128: u128 = 999999u128.to_be();
const LE_I128: i128 = -999999i128.to_le();
const LE_I128: i128 = (-999999i128).to_le();
assert_eq!(BE_U128, b(999999u128).to_be());
assert_eq!(LE_I128, b(-999999i128).to_le());
}

View File

@ -12,7 +12,7 @@ error[E0425]: cannot find value `no` in this scope
3 | no
| ^^ not found in this scope
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:332:13
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 26)' panicked at 'couldn't compile the test', librustdoc/test.rs:333:13
note: Run with `RUST_BACKTRACE=1` for a backtrace.
---- $DIR/failed-doctest-output.rs - SomeStruct (line 20) stdout ----
@ -21,7 +21,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 20)' panicked at 'test
thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
note: Run with `RUST_BACKTRACE=1` for a backtrace.
', librustdoc/test.rs:367:17
', librustdoc/test.rs:368:17
failures:

View File

@ -0,0 +1,48 @@
// 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.
#![feature(plugin_registrar)]
#![feature(box_syntax, rustc_private)]
#![feature(macro_vis_matcher)]
#![feature(macro_at_most_once_rep)]
extern crate syntax;
// Load rustc as a plugin to get macros
#[macro_use]
extern crate rustc;
extern crate rustc_plugin;
use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
LintArray};
use rustc_plugin::Registry;
use syntax::ast;
declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
struct Pass;
impl LintPass for Pass {
fn get_lints(&self) -> LintArray {
lint_array!(TEST_LINT)
}
}
impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.name == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
}
}
}
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_early_lint_pass(box Pass);
}

View File

@ -0,0 +1,24 @@
// 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.
// run-pass
// aux-build:lint_tool_test.rs
// ignore-stage1
#![feature(plugin)]
#![feature(tool_lints)]
#![plugin(lint_tool_test)]
#![allow(dead_code)]
fn lintme() { } //~ WARNING item is named 'lintme'
#[allow(clippy::test_lint)]
pub fn main() {
fn lintme() { }
}

View File

@ -0,0 +1,8 @@
warning: item is named 'lintme'
--> $DIR/lint_tool_test.rs:19:1
|
LL | fn lintme() { } //~ WARNING item is named 'lintme'
| ^^^^^^^^^^^^^^^
|
= note: #[warn(clippy::test_lint)] on by default

View File

@ -19,14 +19,16 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
|
LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
...
LL | f: _s,
| -- data moved here
LL | g: _t
| -- ... and here
help: to prevent move, use ref or ref mut
|
LL | f: ref _s,
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | g: ref _t
| ^^^^^^
|
error[E0507]: cannot move out of borrowed content
--> $DIR/borrowck-move-error-with-note.rs:57:11

View File

@ -3,14 +3,19 @@ error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
|
LL | match tail {
| ^^^^ cannot move out of here
LL | &[Foo { string: a },
| - data moved here
...
LL | Foo { string: b }] => {
| - ... and here
help: to prevent move, use ref or ref mut
|
LL | &[Foo { string: ref a },
| ^^^^^
help: to prevent move, use ref or ref mut
|
LL | //~^ ERROR cannot move out of type `[Foo]`
LL | //~| cannot move out
LL | //~| to prevent move
LL | Foo { string: ref b }] => {
| ^^^^^
|
error: aborting due to previous error

View File

@ -28,7 +28,10 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
LL | match vec {
| ^^^ cannot move out of here
LL | &mut [_a, //~ ERROR cannot move out
| -- help: to prevent move, use ref or ref mut: `ref _a`
| --
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref _a`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:57:13
@ -46,7 +49,10 @@ LL | match vec {
| ^^^ cannot move out of here
...
LL | _b] => {}
| -- help: to prevent move, use ref or ref mut: `ref _b`
| --
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref _b`
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:70:13
@ -62,18 +68,15 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
|
LL | match vec {
| ^^^ cannot move out of here
LL | &mut [_a, _b, _c] => {} //~ ERROR cannot move out
| -- -- -- ... and here
| | |
| | ... and here
| data moved here
help: to prevent move, use ref or ref mut
|
LL | &mut [ref _a, _b, _c] => {} //~ ERROR cannot move out
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | &mut [_a, ref _b, _c] => {} //~ ERROR cannot move out
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | &mut [_a, _b, ref _c] => {} //~ ERROR cannot move out
| ^^^^^^
LL | &mut [ref _a, ref _b, ref _c] => {} //~ ERROR cannot move out
| ^^^^^^ ^^^^^^ ^^^^^^
error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
--> $DIR/borrowck-vec-pattern-nesting.rs:82:13

View File

@ -16,6 +16,25 @@ LL | if let Some(thing) = maybe {
|
= note: move occurs because the value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:16
|
LL | if let Some(thing) = maybe {
| ^^^^^-----^
| | |
| | value moved here
| value used here after move
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value (Mir)
--> $DIR/issue-41962.rs:17:21
|
LL | if let Some(thing) = maybe {
| ^^^^^ value moved here in previous iteration of loop
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:30
|
@ -36,25 +55,6 @@ LL | if let Some(thing) = maybe {
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `maybe` (Mir)
--> $DIR/issue-41962.rs:17:16
|
LL | if let Some(thing) = maybe {
| ^^^^^-----^
| | |
| | value moved here
| value used here after move
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error[E0382]: use of moved value (Mir)
--> $DIR/issue-41962.rs:17:21
|
LL | if let Some(thing) = maybe {
| ^^^^^ value moved here in previous iteration of loop
|
= note: move occurs because value has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0382`.

View File

@ -4,6 +4,7 @@ error[E0507]: cannot move out of borrowed content
LL | let opt = a.iter().enumerate().find(|(_, &s)| {
| ^^^^^-^
| | |
| | data moved here
| | help: to prevent move, use ref or ref mut: `ref s`
| cannot move out of borrowed content

View File

@ -1,13 +1,3 @@
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/two-phase-multi-mut.rs:23:16
|
LL | foo.method(&mut foo);
| -----------^^^^^^^^-
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
| borrow later used here
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/two-phase-multi-mut.rs:23:5
|
@ -18,6 +8,16 @@ LL | foo.method(&mut foo);
| second mutable borrow occurs here
| borrow later used here
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/two-phase-multi-mut.rs:23:16
|
LL | foo.method(&mut foo);
| -----------^^^^^^^^-
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
| borrow later used here
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0499`.

View File

@ -4,7 +4,10 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
LL | match (S {f:"foo".to_string()}) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
LL | S {f:_s} => {} //~ ERROR cannot move out
| -- help: to prevent move, use ref or ref mut: `ref _s`
| --
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref _s`
error: aborting due to previous error

View File

@ -10,7 +10,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
--> $DIR/issue-39544.rs:26:17
|
LL | fn foo<'z>(&'z self) {
| -------- help: consider changing this to be a mutable reference: `&mut self`
| -------- help: consider changing this to be a mutable reference: `&'z mut self`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
| ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@ -35,7 +35,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
--> $DIR/issue-39544.rs:35:17
|
LL | fn foo2<'a>(&'a self, other: &Z) {
| -------- help: consider changing this to be a mutable reference: `&mut self`
| -------- help: consider changing this to be a mutable reference: `&'a mut self`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
| ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@ -52,7 +52,7 @@ error[E0596]: cannot borrow `self.x` as mutable, as it is behind a `&` reference
--> $DIR/issue-39544.rs:40:17
|
LL | fn foo3<'a>(self: &'a Self, other: &Z) {
| -------- help: consider changing this to be a mutable reference: `&mut Z`
| -------- help: consider changing this to be a mutable reference: `&'a mut Self`
LL | let _ = &mut self.x; //~ ERROR cannot borrow
| ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable

View File

@ -1,14 +1,3 @@
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:38:42
|
LL | $foo.x
| ------ value moved here
...
LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
| ^^^^^ value used here after move
|
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:28:9
|
@ -25,6 +14,17 @@ LL | assert_two_copies(copy_legacy!(foo), foo.x); //~ ERROR use of moved val
|
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:38:42
|
LL | $foo.x
| ------ value moved here
...
LL | assert_two_copies(copy_modern!(foo), foo.x); //~ ERROR use of moved value: `foo.x`
| ^^^^^ value used here after move
|
= note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait
error[E0382]: use of moved value: `foo.x`
--> $DIR/fields-move.rs:39:42
|

View File

@ -3,28 +3,40 @@ error[E0508]: cannot move out of type `[T]`, a non-copy slice
|
LL | match (l1, l2) {
| ^^^^^^^^ cannot move out of here
LL | (&[], &[]) => println!("both empty"),
LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
| -- data moved here
...
LL | (&[hd1, ..], &[hd2, ..])
| --- ... and here
help: to prevent move, use ref or ref mut
|
LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | => println!("one empty"),
LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
LL | (&[hd1, ..], &[ref hd2, ..])
| ^^^^^^^
|
error[E0508]: cannot move out of type `[T]`, a non-copy slice
--> $DIR/issue-12567.rs:14:11
|
LL | match (l1, l2) {
| ^^^^^^^^ cannot move out of here
LL | (&[], &[]) => println!("both empty"),
LL | (&[], &[hd, ..]) | (&[hd, ..], &[])
| -- data moved here
...
LL | (&[hd1, ..], &[hd2, ..])
| --- ... and here
help: to prevent move, use ref or ref mut
|
LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[])
| ^^^^^^
help: to prevent move, use ref or ref mut
|
LL | => println!("one empty"),
LL | //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
LL | //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
LL | (&[ref hd1, ..], &[hd2, ..])
| ^^^^^^^
|
error: aborting due to 2 previous errors

View File

@ -1,11 +1,3 @@
error[E0597]: borrowed value does not live long enough
--> $DIR/issue-27592.rs:26:33
|
LL | write(|| format_args!("{}", String::from("Hello world")));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
| |
| temporary value does not live long enough
error[E0597]: borrowed value does not live long enough
--> $DIR/issue-27592.rs:26:27
|
@ -14,6 +6,14 @@ LL | write(|| format_args!("{}", String::from("Hello world")));
| |
| temporary value does not live long enough
error[E0597]: borrowed value does not live long enough
--> $DIR/issue-27592.rs:26:33
|
LL | write(|| format_args!("{}", String::from("Hello world")));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value only lives until here
| |
| temporary value does not live long enough
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.

View File

@ -22,4 +22,6 @@ fn main() {
println!("{} %f", "one", 2.0); //~ ERROR never used
println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
//~^ ERROR multiple unused formatting arguments
}

View File

@ -52,10 +52,25 @@ error: named argument never used
--> $DIR/format-foreign.rs:24:39
|
LL | println!("Hi there, $NAME.", NAME="Tim"); //~ ERROR never used
| ^^^^^
| ----- ^^^^^
| |
| help: format specifiers use curly braces: `{NAME}`
|
= help: `$NAME` should be written as `{NAME}`
= note: shell formatting not supported; see the documentation for `std::fmt`
error: aborting due to 5 previous errors
error: multiple unused formatting arguments
--> $DIR/format-foreign.rs:25:32
|
LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3);
| ---------------- ^ ^ ^
| |
| multiple missing formatting specifiers
|
= note: shell formatting not supported; see the documentation for `std::fmt`
help: format specifiers use curly braces
|
LL | println!("{1} {0} $$ {NAME}", 1, 2, NAME=3);
| ^^^ ^^^ ^^^^^^
error: aborting due to 6 previous errors

View File

@ -30,7 +30,10 @@ error: multiple unused formatting arguments
--> $DIR/format-unused-lables.rs:24:9
|
LL | println!("Some more $STUFF",
| ------------------ multiple missing formatting specifiers
| ------------------
| | |
| | help: format specifiers use curly braces: `{STUFF}`
| multiple missing formatting specifiers
LL | "woo!", //~ ERROR multiple unused formatting arguments
| ^^^^^^
LL | STUFF=
@ -39,7 +42,6 @@ LL | "things"
LL | , UNUSED="args");
| ^^^^^^
|
= help: `$STUFF` should be written as `{STUFF}`
= note: shell formatting not supported; see the documentation for `std::fmt`
error: aborting due to 4 previous errors

View File

@ -4,15 +4,6 @@ warning: not reporting region error due to nll
LL | let mut closure = expect_sig(|p, y| *p = y);
| ^
error: unsatisfied lifetime constraints
--> $DIR/escape-argument-callee.rs:36:45
|
LL | let mut closure = expect_sig(|p, y| *p = y);
| - - ^^^^^^ requires that `'1` must outlive `'2`
| | |
| | has type `&'1 i32`
| has type `&mut &'2 i32`
note: No external requirements
--> $DIR/escape-argument-callee.rs:36:38
|
@ -24,6 +15,15 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32))
]
error: unsatisfied lifetime constraints
--> $DIR/escape-argument-callee.rs:36:45
|
LL | let mut closure = expect_sig(|p, y| *p = y);
| - - ^^^^^^ requires that `'1` must outlive `'2`
| | |
| | has type `&'1 i32`
| has type `&mut &'2 i32`
note: No external requirements
--> $DIR/escape-argument-callee.rs:30:1
|

View File

@ -4,17 +4,6 @@ warning: not reporting region error due to nll
LL | let p = x.get();
| ^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
|
LL | |_outlives1, _outlives2, _outlives3, x, y| {
| ---------- ---------- has type `std::cell::Cell<&'2 &u32>`
| |
| has type `std::cell::Cell<&&'1 u32>`
...
LL | demand_y(x, y, p) //~ ERROR
| ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-approximated-fail-no-postdom.rs:53:9
|
@ -31,6 +20,17 @@ LL | | },
for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
]
error: unsatisfied lifetime constraints
--> $DIR/propagate-approximated-fail-no-postdom.rs:57:13
|
LL | |_outlives1, _outlives2, _outlives3, x, y| {
| ---------- ---------- has type `std::cell::Cell<&'2 &u32>`
| |
| has type `std::cell::Cell<&&'1 u32>`
...
LL | demand_y(x, y, p) //~ ERROR
| ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-approximated-fail-no-postdom.rs:48:1
|

View File

@ -4,17 +4,6 @@ warning: not reporting region error due to nll
LL | foo(cell, |cell_a, cell_x| {
| ^^^
error: borrowed data escapes outside of closure
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
|
LL | foo(cell, |cell_a, cell_x| {
| ------ ------ `cell_x` is a reference that is only valid in the closure body
| |
| `cell_a` is declared here, outside of the closure body
LL | //~^ WARNING not reporting region error due to nll
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15
|
@ -31,6 +20,17 @@ LL | | })
for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) u32>))
]
error: borrowed data escapes outside of closure
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9
|
LL | foo(cell, |cell_a, cell_x| {
| ------ ------ `cell_x` is a reference that is only valid in the closure body
| |
| `cell_a` is declared here, outside of the closure body
LL | //~^ WARNING not reporting region error due to nll
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:28:1
|

View File

@ -23,19 +23,6 @@ LL | | });
= note: number of external vids: 4
= note: where '_#1r: '_#0r
error: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the function body
LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
LL | | //~^ ERROR
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
LL | | });
| |______^ `cell_a` escapes the function body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1
|
@ -50,5 +37,18 @@ LL | | }
|
= note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs []
error: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the function body
LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
LL | | //~^ ERROR
LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll
LL | | });
| |______^ `cell_a` escapes the function body here
error: aborting due to previous error

View File

@ -23,19 +23,6 @@ LL | | });
= note: number of external vids: 5
= note: where '_#1r: '_#0r
error: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the function body
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | | //~^ ERROR
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | | //~^ WARNING not reporting region error due to nll
LL | | });
| |______^ `cell_a` escapes the function body here
note: No external requirements
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1
|
@ -50,5 +37,18 @@ LL | | }
|
= note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs []
error: borrowed data escapes outside of function
--> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| ------ `cell_a` is a reference that is only valid in the function body
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | | //~^ ERROR
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
LL | | //~^ WARNING not reporting region error due to nll
LL | | });
| |______^ `cell_a` escapes the function body here
error: aborting due to previous error

View File

@ -4,17 +4,6 @@ warning: not reporting region error due to nll
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
| --------- - has type `&std::cell::Cell<&'1 u32>`
| |
| has type `&std::cell::Cell<&'2 &u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47
|
@ -32,6 +21,17 @@ LL | | });
for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>))
]
error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
| --------- - has type `&std::cell::Cell<&'1 u32>`
| |
| has type `&std::cell::Cell<&'2 &u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:44:1
|

View File

@ -4,17 +4,6 @@ warning: not reporting region error due to nll
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^
error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| ---------- ---------- has type `&std::cell::Cell<&'2 &u32>`
| |
| has type `&std::cell::Cell<&'1 &u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47
|
@ -32,6 +21,17 @@ LL | | });
for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't2)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) u32>, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't3)) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't1)) u32>))
]
error: unsatisfied lifetime constraints
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| ---------- ---------- has type `&std::cell::Cell<&'2 &u32>`
| |
| has type `&std::cell::Cell<&'1 &u32>`
LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
note: No external requirements
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:48:1
|

View File

@ -26,21 +26,6 @@ LL | | });
= note: number of external vids: 3
= note: where T: '_#1r
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/propagate-from-trait-match.rs:42:36
|
LL | establish_relationships(value, |value| {
| ____________________________________^
LL | | //~^ ERROR the parameter type `T` may not live long enough
LL | |
LL | | // This function call requires that
... |
LL | | //~^ WARNING not reporting region error due to nll
LL | | });
| |_____^
|
= help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
note: No external requirements
--> $DIR/propagate-from-trait-match.rs:38:1
|
@ -58,6 +43,21 @@ LL | | }
T
]
error[E0309]: the parameter type `T` may not live long enough
--> $DIR/propagate-from-trait-match.rs:42:36
|
LL | establish_relationships(value, |value| {
| ____________________________________^
LL | | //~^ ERROR the parameter type `T` may not live long enough
LL | |
LL | | // This function call requires that
... |
LL | | //~^ WARNING not reporting region error due to nll
LL | | });
| |_____^
|
= help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
error: aborting due to previous error
For more information about this error, try `rustc --explain E0309`.

View File

@ -4,15 +4,6 @@ warning: not reporting region error due to nll
LL | expect_sig(|a, b| b); // ought to return `a`
| ^
error: unsatisfied lifetime constraints
--> $DIR/return-wrong-bound-region.rs:21:23
|
LL | expect_sig(|a, b| b); // ought to return `a`
| - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
| | |
| | has type `&'1 i32`
| has type `&'2 i32`
note: No external requirements
--> $DIR/return-wrong-bound-region.rs:21:16
|
@ -24,6 +15,15 @@ LL | expect_sig(|a, b| b); // ought to return `a`
for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32
]
error: unsatisfied lifetime constraints
--> $DIR/return-wrong-bound-region.rs:21:23
|
LL | expect_sig(|a, b| b); // ought to return `a`
| - - ^ closure was supposed to return data with lifetime `'1` but it is returning data with lifetime `'2`
| | |
| | has type `&'1 i32`
| has type `&'2 i32`
note: No external requirements
--> $DIR/return-wrong-bound-region.rs:20:1
|

View File

@ -55,10 +55,19 @@ fn parse_dot_or_call_expr_with(mut attrs: Vec<u32>) {
);
}
// Found when trying to bootstrap rustc
fn if_guard(x: Result<i32, i32>) {
match x {
Ok(mut r) | Err(mut r) if true => r = 1,
_ => (),
}
}
fn main() {
ref_argument(0);
mutable_upvar();
generator_mutable_upvar();
ref_closure_argument();
parse_dot_or_call_expr_with(Vec::new());
if_guard(Ok(0));
}

View File

@ -1,5 +1,5 @@
error[E0623]: lifetime mismatch
--> $DIR/issue-52133.rs:43:9
--> $DIR/issue-52113.rs:43:9
|
LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
| -------------------- ------- these two types are declared with different lifetimes...

View File

@ -59,6 +59,7 @@ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
LL | let C(D(s)) = c;
| - ^ cannot move out of here
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref s`
error[E0507]: cannot move out of borrowed content
@ -88,7 +89,10 @@ LL | match x {
| ^ cannot move out of here
...
LL | B::U(D(s)) => (),
| - help: to prevent move, use ref or ref mut: `ref s`
| -
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref s`
error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
--> $DIR/move-errors.rs:105:11
@ -97,7 +101,10 @@ LL | match x {
| ^ cannot move out of here
...
LL | (D(s), &t) => (),
| - help: to prevent move, use ref or ref mut: `ref s`
| -
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref s`
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:105:11
@ -106,21 +113,25 @@ LL | match x {
| ^ cannot move out of borrowed content
...
LL | (D(s), &t) => (),
| - help: to prevent move, use ref or ref mut: `ref t`
| -
| |
| data moved here
| help: to prevent move, use ref or ref mut: `ref t`
error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
--> $DIR/move-errors.rs:115:11
|
LL | match x {
| ^ cannot move out of here
LL | //~^ ERROR
LL | F(s, mut t) => (),
| - ----- ... and here
| |
| data moved here
help: to prevent move, use ref or ref mut
|
LL | F(ref s, mut t) => (),
| ^^^^^
help: to prevent move, use ref or ref mut
|
LL | F(s, ref mut t) => (),
| ^^^^^^^^^
LL | F(ref s, ref mut t) => (),
| ^^^^^ ^^^^^^^^^
error[E0507]: cannot move out of borrowed content
--> $DIR/move-errors.rs:123:11

View File

@ -25,14 +25,6 @@ LL | with_signature(x, |mut y| Box::new(y.next()))
= note: number of external vids: 4
= note: where <T as std::iter::Iterator>::Item: '_#2r
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:35:23
|
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
note: No external requirements
--> $DIR/projection-no-regions-closure.rs:31:1
|
@ -50,6 +42,14 @@ LL | | }
T
]
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:35:23
|
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
note: External requirements
--> $DIR/projection-no-regions-closure.rs:45:23
|
@ -97,14 +97,6 @@ LL | with_signature(x, |mut y| Box::new(y.next()))
= note: number of external vids: 5
= note: where <T as std::iter::Iterator>::Item: '_#3r
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:53:23
|
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
note: No external requirements
--> $DIR/projection-no-regions-closure.rs:49:1
|
@ -123,6 +115,14 @@ LL | | }
T
]
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
--> $DIR/projection-no-regions-closure.rs:53:23
|
LL | with_signature(x, |mut y| Box::new(y.next()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
note: External requirements
--> $DIR/projection-no-regions-closure.rs:64:23
|

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