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:
commit
8c069ceba8
@ -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
|
||||
|
21
RELEASES.md
21
RELEASES.md
@ -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
|
||||
---------
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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> {
|
||||
|
@ -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>`
|
||||
|
@ -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>()`.
|
||||
///
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>");
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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 => {
|
||||
|
@ -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 { .. } => (),
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
32
src/librustc_target/spec/aarch64_unknown_hermit.rs
Normal file
32
src/librustc_target/spec/aarch64_unknown_hermit.rs
Normal 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,
|
||||
})
|
||||
}
|
37
src/librustc_target/spec/hermit_base.rs
Normal file
37
src/librustc_target/spec/hermit_base.rs
Normal 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()
|
||||
}
|
||||
}
|
@ -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.
|
||||
|
33
src/librustc_target/spec/x86_64_unknown_hermit.rs
Normal file
33
src/librustc_target/spec/x86_64_unknown_hermit.rs
Normal 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,
|
||||
})
|
||||
}
|
@ -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 {
|
||||
|
@ -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<()> {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(¬e))
|
||||
MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes))
|
||||
} else {
|
||||
format!("Deprecating in {}{}",
|
||||
Escape(&depr.since),
|
||||
MarkdownHtml(¬e))
|
||||
MarkdownHtml(¬e, 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() {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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]
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
|
@ -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];
|
||||
|
@ -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
389
src/libstd/os/hermit/fs.rs
Normal 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
|
||||
}
|
||||
}
|
16
src/libstd/os/hermit/mod.rs
Normal file
16
src/libstd/os/hermit/mod.rs
Normal 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;
|
27
src/libstd/os/hermit/raw.rs
Normal file
27
src/libstd/os/hermit/raw.rs
Normal 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};
|
@ -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")]
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = "";
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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!"))
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
///
|
||||
|
@ -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" }
|
@ -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::*;
|
@ -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`
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
42
src/test/codegen/slice-position-bounds-check.rs
Normal file
42
src/test/codegen/slice-position-bounds-check.rs
Normal 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]
|
||||
}
|
@ -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]
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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:
|
||||
|
48
src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
Normal file
48
src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
Normal 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);
|
||||
}
|
24
src/test/ui-fulldeps/lint_tool_test.rs
Normal file
24
src/test/ui-fulldeps/lint_tool_test.rs
Normal 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() { }
|
||||
}
|
8
src/test/ui-fulldeps/lint_tool_test.stderr
Normal file
8
src/test/ui-fulldeps/lint_tool_test.stderr
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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`.
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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...
|
@ -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
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user