Auto merge of #55012 - kennytm:rollup, r=kennytm
Rollup of 16 pull requests Successful merges: - #54755 (Documents reference equality by address (#54197)) - #54811 (During rustc bootstrap, make default for `optimize` independent of `debug`) - #54825 (NLL says "borrowed content" instead of more precise "dereference of raw pointer") - #54860 (Add doc comments about safest way to initialize a vector of zeros) - #54869 (Fix mobile docs) - #54891 (Fix tracking issue for Once::is_completed) - #54913 (doc fix: it's auto traits that make for automatic implementations) - #54920 (Fix handling of #[must_use] on unit and uninhabited types) - #54932 (A handful of random string-related improvements) - #54936 (impl Eq+Hash for TyLayout) - #54950 (std: Synchronize global allocator on wasm32) - #54956 ("(using ..." doesn't have the matching ")") - #54958 (add a macro for static (compile-time) assertions) - #54967 (Remove incorrect span for second label inner macro invocation) - #54983 (Fix slice's benchmarks) - #54989 (Fix spelling in the documentation to htmldocck.py) Failed merges: r? @ghost
This commit is contained in:
commit
945372d268
31 changed files with 294 additions and 130 deletions
|
|
@ -1269,7 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "minifier"
|
||||
version = "0.0.19"
|
||||
version = "0.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -2484,7 +2484,7 @@ dependencies = [
|
|||
name = "rustdoc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -3289,7 +3289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d"
|
||||
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
|
||||
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
|
||||
"checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11"
|
||||
"checksum minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474"
|
||||
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
|
||||
"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226"
|
||||
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
|
||||
|
|
|
|||
|
|
@ -628,6 +628,9 @@ impl Config {
|
|||
let default = false;
|
||||
config.llvm_assertions = llvm_assertions.unwrap_or(default);
|
||||
|
||||
let default = true;
|
||||
config.rust_optimize = optimize.unwrap_or(default);
|
||||
|
||||
let default = match &config.channel[..] {
|
||||
"stable" | "beta" | "nightly" => true,
|
||||
_ => false,
|
||||
|
|
@ -640,7 +643,6 @@ impl Config {
|
|||
config.debug_jemalloc = debug_jemalloc.unwrap_or(default);
|
||||
config.rust_debuginfo = debuginfo.unwrap_or(default);
|
||||
config.rust_debug_assertions = debug_assertions.unwrap_or(default);
|
||||
config.rust_optimize = optimize.unwrap_or(!default);
|
||||
|
||||
let default = config.channel == "dev";
|
||||
config.ignore_git = ignore_git.unwrap_or(default);
|
||||
|
|
|
|||
|
|
@ -91,13 +91,13 @@ pub fn try_run_suppressed(cmd: &mut Command) -> bool {
|
|||
output.status.success()
|
||||
}
|
||||
|
||||
pub fn gnu_target(target: &str) -> String {
|
||||
pub fn gnu_target(target: &str) -> &str {
|
||||
match target {
|
||||
"i686-pc-windows-msvc" => "i686-pc-win32".to_string(),
|
||||
"x86_64-pc-windows-msvc" => "x86_64-pc-win32".to_string(),
|
||||
"i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(),
|
||||
"x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(),
|
||||
s => s.to_string(),
|
||||
"i686-pc-windows-msvc" => "i686-pc-win32",
|
||||
"x86_64-pc-windows-msvc" => "x86_64-pc-win32",
|
||||
"i686-pc-windows-gnu" => "i686-w64-mingw32",
|
||||
"x86_64-pc-windows-gnu" => "x86_64-w64-mingw32",
|
||||
s => s,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,65 +15,66 @@ htmldocck.py is a custom checker script for Rustdoc HTML outputs.
|
|||
|
||||
The principle is simple: This script receives a path to generated HTML
|
||||
documentation and a "template" script, which has a series of check
|
||||
commands like `@has` or `@matches`. Each command can be used to check if
|
||||
commands like `@has` or `@matches`. Each command is used to check if
|
||||
some pattern is present or not present in the particular file or in
|
||||
the particular node of HTML tree. In many cases, the template script
|
||||
happens to be a source code given to rustdoc.
|
||||
a particular node of the HTML tree. In many cases, the template script
|
||||
happens to be the source code given to rustdoc.
|
||||
|
||||
While it indeed is possible to test in smaller portions, it has been
|
||||
hard to construct tests in this fashion and major rendering errors were
|
||||
discovered much later. This script is designed for making the black-box
|
||||
and regression testing of Rustdoc easy. This does not preclude the needs
|
||||
for unit testing, but can be used to complement related tests by quickly
|
||||
discovered much later. This script is designed to make black-box and
|
||||
regression testing of Rustdoc easy. This does not preclude the needs for
|
||||
unit testing, but can be used to complement related tests by quickly
|
||||
showing the expected renderings.
|
||||
|
||||
In order to avoid one-off dependencies for this task, this script uses
|
||||
a reasonably working HTML parser and the existing XPath implementation
|
||||
from Python's standard library. Hopefully we won't render
|
||||
from Python's standard library. Hopefully, we won't render
|
||||
non-well-formed HTML.
|
||||
|
||||
# Commands
|
||||
|
||||
Commands start with an `@` followed by a command name (letters and
|
||||
hyphens), and zero or more arguments separated by one or more whitespace
|
||||
and optionally delimited with single or double quotes. The `@` mark
|
||||
cannot be preceded by a non-whitespace character. Other lines (including
|
||||
every text up to the first `@`) are ignored, but it is recommended to
|
||||
avoid the use of `@` in the template file.
|
||||
characters and optionally delimited with single or double quotes. The `@`
|
||||
mark cannot be preceded by a non-whitespace character. Other lines
|
||||
(including every text up to the first `@`) are ignored, but it is
|
||||
recommended to avoid the use of `@` in the template file.
|
||||
|
||||
There are a number of supported commands:
|
||||
|
||||
* `@has PATH` checks for the existence of given file.
|
||||
* `@has PATH` checks for the existence of the given file.
|
||||
|
||||
`PATH` is relative to the output directory. It can be given as `-`
|
||||
which repeats the most recently used `PATH`.
|
||||
|
||||
* `@has PATH PATTERN` and `@matches PATH PATTERN` checks for
|
||||
the occurrence of given `PATTERN` in the given file. Only one
|
||||
occurrence of given pattern is enough.
|
||||
the occurrence of the given pattern `PATTERN` in the specified file.
|
||||
Only one occurrence of the pattern is enough.
|
||||
|
||||
For `@has`, `PATTERN` is a whitespace-normalized (every consecutive
|
||||
whitespace being replaced by one single space character) string.
|
||||
The entire file is also whitespace-normalized including newlines.
|
||||
|
||||
For `@matches`, `PATTERN` is a Python-supported regular expression.
|
||||
The file remains intact but the regexp is matched with no `MULTILINE`
|
||||
and `IGNORECASE` option. You can still use a prefix `(?m)` or `(?i)`
|
||||
The file remains intact but the regexp is matched without the `MULTILINE`
|
||||
and `IGNORECASE` options. You can still use a prefix `(?m)` or `(?i)`
|
||||
to override them, and `\A` and `\Z` for definitely matching
|
||||
the beginning and end of the file.
|
||||
|
||||
(The same distinction goes to other variants of these commands.)
|
||||
|
||||
* `@has PATH XPATH PATTERN` and `@matches PATH XPATH PATTERN` checks for
|
||||
the presence of given `XPATH` in the given HTML file, and also
|
||||
the occurrence of given `PATTERN` in the matching node or attribute.
|
||||
Only one occurrence of given pattern in the match is enough.
|
||||
the presence of the given XPath `XPATH` in the specified HTML file,
|
||||
and also the occurrence of the given pattern `PATTERN` in the matching
|
||||
node or attribute. Only one occurrence of the pattern in the match
|
||||
is enough.
|
||||
|
||||
`PATH` should be a valid and well-formed HTML file. It does *not*
|
||||
accept arbitrary HTML5; it should have matching open and close tags
|
||||
and correct entity references at least.
|
||||
|
||||
`XPATH` is an XPath expression to match. This is fairly limited:
|
||||
`XPATH` is an XPath expression to match. The XPath is fairly limited:
|
||||
`tag`, `*`, `.`, `//`, `..`, `[@attr]`, `[@attr='value']`, `[tag]`,
|
||||
`[POS]` (element located in given `POS`), `[last()-POS]`, `text()`
|
||||
and `@attr` (both as the last segment) are supported. Some examples:
|
||||
|
|
@ -85,7 +86,7 @@ There are a number of supported commands:
|
|||
- `//h1[@class="fqn"]/span[1]/a[last()]/@class` matches a value of
|
||||
`class` attribute in the last `a` element (can be followed by more
|
||||
elements that are not `a`) inside the first `span` in the `h1` with
|
||||
a class of `fqn`. Note that there cannot be no additional elements
|
||||
a class of `fqn`. Note that there cannot be any additional elements
|
||||
between them due to the use of `/` instead of `//`.
|
||||
|
||||
Do not try to use non-absolute paths, it won't work due to the flawed
|
||||
|
|
@ -93,11 +94,12 @@ There are a number of supported commands:
|
|||
|
||||
For the text matches (i.e. paths not ending with `@attr`), any
|
||||
subelements are flattened into one string; this is handy for ignoring
|
||||
highlights for example. If you want to simply check the presence of
|
||||
given node or attribute, use an empty string (`""`) as a `PATTERN`.
|
||||
highlights for example. If you want to simply check for the presence of
|
||||
a given node or attribute, use an empty string (`""`) as a `PATTERN`.
|
||||
|
||||
* `@count PATH XPATH COUNT' checks for the occurrence of given XPath
|
||||
in the given file. The number of occurrences must match the given count.
|
||||
* `@count PATH XPATH COUNT' checks for the occurrence of the given XPath
|
||||
in the specified file. The number of occurrences must match the given
|
||||
count.
|
||||
|
||||
* `@has-dir PATH` checks for the existence of the given directory.
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use std::mem;
|
|||
use std::ptr;
|
||||
|
||||
use rand::{Rng, SeedableRng, XorShiftRng};
|
||||
use rand::distributions::{Standard, Alphanumeric};
|
||||
use test::{Bencher, black_box};
|
||||
|
||||
#[bench]
|
||||
|
|
@ -192,18 +193,20 @@ fn gen_descending(len: usize) -> Vec<u64> {
|
|||
(0..len as u64).rev().collect()
|
||||
}
|
||||
|
||||
const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
||||
|
||||
fn gen_random(len: usize) -> Vec<u64> {
|
||||
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
|
||||
rng.gen_iter::<u64>().take(len).collect()
|
||||
let mut rng = XorShiftRng::from_seed(SEED);
|
||||
rng.sample_iter(&Standard).take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_random_bytes(len: usize) -> Vec<u8> {
|
||||
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
|
||||
rng.gen_iter::<u8>().take(len).collect()
|
||||
let mut rng = XorShiftRng::from_seed(SEED);
|
||||
rng.sample_iter(&Standard).take(len).collect()
|
||||
}
|
||||
|
||||
fn gen_mostly_ascending(len: usize) -> Vec<u64> {
|
||||
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
|
||||
let mut rng = XorShiftRng::from_seed(SEED);
|
||||
let mut v = gen_ascending(len);
|
||||
for _ in (0usize..).take_while(|x| x * x <= len) {
|
||||
let x = rng.gen::<usize>() % len;
|
||||
|
|
@ -214,7 +217,7 @@ fn gen_mostly_ascending(len: usize) -> Vec<u64> {
|
|||
}
|
||||
|
||||
fn gen_mostly_descending(len: usize) -> Vec<u64> {
|
||||
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
|
||||
let mut rng = XorShiftRng::from_seed(SEED);
|
||||
let mut v = gen_descending(len);
|
||||
for _ in (0usize..).take_while(|x| x * x <= len) {
|
||||
let x = rng.gen::<usize>() % len;
|
||||
|
|
@ -225,18 +228,18 @@ fn gen_mostly_descending(len: usize) -> Vec<u64> {
|
|||
}
|
||||
|
||||
fn gen_strings(len: usize) -> Vec<String> {
|
||||
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
|
||||
let mut rng = XorShiftRng::from_seed(SEED);
|
||||
let mut v = vec![];
|
||||
for _ in 0..len {
|
||||
let n = rng.gen::<usize>() % 20 + 1;
|
||||
v.push(rng.gen_ascii_chars().take(n).collect());
|
||||
v.push(rng.sample_iter(&Alphanumeric).take(n).collect());
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
|
||||
let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
|
||||
rng.gen_iter().map(|x| [x; 16]).take(len).collect()
|
||||
let mut rng = XorShiftRng::from_seed(SEED);
|
||||
rng.sample_iter(&Standard).map(|x| [x; 16]).take(len).collect()
|
||||
}
|
||||
|
||||
macro_rules! sort {
|
||||
|
|
|
|||
|
|
@ -120,11 +120,17 @@ use raw_vec::RawVec;
|
|||
/// assert_eq!(vec, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
///
|
||||
/// It can also initialize each element of a `Vec<T>` with a given value:
|
||||
/// It can also initialize each element of a `Vec<T>` with a given value.
|
||||
/// This may be more efficient than performing allocation and initialization
|
||||
/// in separate steps, especially when initializing a vector of zeros:
|
||||
///
|
||||
/// ```
|
||||
/// let vec = vec![0; 5];
|
||||
/// assert_eq!(vec, [0, 0, 0, 0, 0]);
|
||||
///
|
||||
/// // The following is equivalent, but potentially slower:
|
||||
/// let mut vec1 = Vec::with_capacity(5);
|
||||
/// vec1.resize(5, 0);
|
||||
/// ```
|
||||
///
|
||||
/// Use a `Vec<T>` as an efficient stack:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@
|
|||
#![feature(nll)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![cfg_attr(
|
||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||
feature(integer_atomics, stdsimd)
|
||||
)]
|
||||
#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
|
||||
#![rustc_alloc_kind = "lib"]
|
||||
|
||||
|
|
@ -331,29 +335,76 @@ mod platform {
|
|||
use core::alloc::{GlobalAlloc, Layout};
|
||||
use System;
|
||||
|
||||
// No need for synchronization here as wasm is currently single-threaded
|
||||
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
|
||||
|
||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||
unsafe impl GlobalAlloc for System {
|
||||
#[inline]
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
let _lock = lock::lock();
|
||||
DLMALLOC.malloc(layout.size(), layout.align())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||
let _lock = lock::lock();
|
||||
DLMALLOC.calloc(layout.size(), layout.align())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
let _lock = lock::lock();
|
||||
DLMALLOC.free(ptr, layout.size(), layout.align())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
let _lock = lock::lock();
|
||||
DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_feature = "atomics")]
|
||||
mod lock {
|
||||
use core::arch::wasm32;
|
||||
use core::sync::atomic::{AtomicI32, Ordering::SeqCst};
|
||||
|
||||
static LOCKED: AtomicI32 = AtomicI32::new(0);
|
||||
|
||||
pub struct DropLock;
|
||||
|
||||
pub fn lock() -> DropLock {
|
||||
loop {
|
||||
if LOCKED.swap(1, SeqCst) == 0 {
|
||||
return DropLock
|
||||
}
|
||||
unsafe {
|
||||
let r = wasm32::atomic::wait_i32(
|
||||
&LOCKED as *const AtomicI32 as *mut i32,
|
||||
1, // expected value
|
||||
-1, // timeout
|
||||
);
|
||||
debug_assert!(r == 0 || r == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DropLock {
|
||||
fn drop(&mut self) {
|
||||
let r = LOCKED.swap(0, SeqCst);
|
||||
debug_assert_eq!(r, 1);
|
||||
unsafe {
|
||||
wasm32::atomic::wake(
|
||||
&LOCKED as *const AtomicI32 as *mut i32,
|
||||
1, // only one thread
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_feature = "atomics"))]
|
||||
mod lock {
|
||||
pub fn lock() {} // no atomics, no threads, that's easy!
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,16 @@ macro_rules! span_bug {
|
|||
})
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! static_assert {
|
||||
($name:ident: $test:expr) => {
|
||||
// Use the bool to access an array such that if the bool is false, the access
|
||||
// is out-of-bounds.
|
||||
#[allow(dead_code)]
|
||||
static $name: () = [()][!$test as usize];
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! __impl_stable_hash_field {
|
||||
($field:ident, $ctx:expr, $hasher:expr) => ($field.hash_stable($ctx, $hasher));
|
||||
|
|
|
|||
|
|
@ -167,8 +167,7 @@ newtype_index! {
|
|||
impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private });
|
||||
|
||||
// compilation error if size of `ScopeData` is not the same as a `u32`
|
||||
#[allow(dead_code)]
|
||||
static ASSERT: () = [()][!(mem::size_of::<ScopeData>() == 4) as usize];
|
||||
static_assert!(ASSERT_SCOPE_DATA: mem::size_of::<ScopeData>() == 4);
|
||||
|
||||
impl Scope {
|
||||
/// Returns a item-local id associated with this scope.
|
||||
|
|
|
|||
|
|
@ -829,12 +829,9 @@ impl<'tcx> CommonTypes<'tcx> {
|
|||
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
|
||||
// Ensure our type representation does not grow
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[allow(dead_code)]
|
||||
static ASSERT_TY_KIND: () =
|
||||
[()][!(::std::mem::size_of::<ty::TyKind<'_>>() <= 24) as usize];
|
||||
static_assert!(ASSERT_TY_KIND: ::std::mem::size_of::<ty::TyKind<'_>>() <= 24);
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[allow(dead_code)]
|
||||
static ASSERT_TYS: () = [()][!(::std::mem::size_of::<ty::TyS<'_>>() <= 32) as usize];
|
||||
static_assert!(ASSERT_TYS: ::std::mem::size_of::<ty::TyS<'_>>() <= 32);
|
||||
|
||||
let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
|
||||
let mk_region = |r| {
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@ pub enum StringPart {
|
|||
}
|
||||
|
||||
impl StringPart {
|
||||
pub fn content(&self) -> String {
|
||||
pub fn content(&self) -> &str {
|
||||
match self {
|
||||
&StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s.to_owned()
|
||||
&StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -398,7 +398,7 @@ impl Diagnostic {
|
|||
}
|
||||
|
||||
pub fn message(&self) -> String {
|
||||
self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
|
||||
self.message.iter().map(|i| i.0.as_str()).collect::<String>()
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &Vec<(String, Style)> {
|
||||
|
|
@ -448,7 +448,7 @@ impl Diagnostic {
|
|||
|
||||
impl SubDiagnostic {
|
||||
pub fn message(&self) -> String {
|
||||
self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
|
||||
self.message.iter().map(|i| i.0.as_str()).collect::<String>()
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &Vec<(String, Style)> {
|
||||
|
|
|
|||
|
|
@ -59,15 +59,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
|||
}
|
||||
|
||||
let t = cx.tables.expr_ty(&expr);
|
||||
let ty_warned = match t.sty {
|
||||
ty::Tuple(ref tys) if tys.is_empty() => return,
|
||||
ty::Never => return,
|
||||
// FIXME(varkor): replace with `t.is_unit() || t.conservative_is_uninhabited()`.
|
||||
let type_permits_no_use = match t.sty {
|
||||
ty::Tuple(ref tys) if tys.is_empty() => true,
|
||||
ty::Never => true,
|
||||
ty::Adt(def, _) => {
|
||||
if def.variants.is_empty() {
|
||||
return;
|
||||
true
|
||||
} else {
|
||||
check_must_use(cx, def.did, s.span, "")
|
||||
}
|
||||
check_must_use(cx, def.did, s.span, "")
|
||||
},
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
|
@ -95,7 +97,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
|||
if let Some(def) = maybe_def {
|
||||
let def_id = def.def_id();
|
||||
fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
|
||||
} else if type_permits_no_use {
|
||||
// We don't warn about unused unit or uninhabited types.
|
||||
// (See https://github.com/rust-lang/rust/issues/43806 for details.)
|
||||
return;
|
||||
}
|
||||
|
||||
let must_use_op = match expr.node {
|
||||
// Hardcoding operators here seemed more expedient than the
|
||||
// refactoring that would be needed to look up the `#[must_use]`
|
||||
|
|
@ -139,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
|
|||
op_warned = true;
|
||||
}
|
||||
|
||||
if !(ty_warned || fn_warned || op_warned) {
|
||||
if !(type_permits_no_use || fn_warned || op_warned) {
|
||||
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +240,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
|
|||
.find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel)
|
||||
.is_some();
|
||||
|
||||
// Has a plugin registered this attribute as one which must be used at
|
||||
// Has a plugin registered this attribute as one that must be used at
|
||||
// the crate level?
|
||||
let plugin_crate = plugin_attributes.iter()
|
||||
.find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ enum GroupedMoveError<'tcx> {
|
|||
enum BorrowedContentSource {
|
||||
Arc,
|
||||
Rc,
|
||||
DerefRawPointer,
|
||||
Other,
|
||||
}
|
||||
|
||||
|
|
@ -76,6 +77,7 @@ impl Display for BorrowedContentSource {
|
|||
match *self {
|
||||
BorrowedContentSource::Arc => write!(f, "an `Arc`"),
|
||||
BorrowedContentSource::Rc => write!(f, "an `Rc`"),
|
||||
BorrowedContentSource::DerefRawPointer => write!(f, "dereference of raw pointer"),
|
||||
BorrowedContentSource::Other => write!(f, "borrowed content"),
|
||||
}
|
||||
}
|
||||
|
|
@ -279,6 +281,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
self.prefixes(&original_path, PrefixSet::All)
|
||||
.any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx)
|
||||
.is_some());
|
||||
debug!("report: ty={:?}", ty);
|
||||
match ty.sty {
|
||||
ty::Array(..) | ty::Slice(..) =>
|
||||
self.infcx.tcx.cannot_move_out_of_interior_noncopy(
|
||||
|
|
@ -582,6 +585,18 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// If we didn't find an `Arc` or an `Rc`, then check specifically for
|
||||
// a dereference of a place that has the type of a raw pointer.
|
||||
// We can't use `place.ty(..).to_ty(..)` here as that strips away the raw pointer.
|
||||
if let Place::Projection(box Projection {
|
||||
base,
|
||||
elem: ProjectionElem::Deref,
|
||||
}) = place {
|
||||
if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() {
|
||||
return BorrowedContentSource::DerefRawPointer;
|
||||
}
|
||||
}
|
||||
|
||||
BorrowedContentSource::Other
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
//! Functions concerning immediate values and operands, and reading from operands.
|
||||
//! All high-level functions to read from memory work on operands as sources.
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::convert::TryInto;
|
||||
|
||||
use rustc::{mir, ty};
|
||||
|
|
@ -290,7 +289,7 @@ impl<Tag> Operand<Tag> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct OpTy<'tcx, Tag=()> {
|
||||
crate op: Operand<Tag>, // ideally we'd make this private, but const_prop needs this
|
||||
pub layout: TyLayout<'tcx>,
|
||||
|
|
@ -324,26 +323,6 @@ impl<'tcx, Tag> From<ValTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
|
|||
}
|
||||
}
|
||||
|
||||
// Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type
|
||||
impl<'tcx, Tag> Hash for OpTy<'tcx, Tag>
|
||||
where Tag: Hash
|
||||
{
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.op.hash(state);
|
||||
self.layout.ty.hash(state);
|
||||
}
|
||||
}
|
||||
impl<'tcx, Tag> PartialEq for OpTy<'tcx, Tag>
|
||||
where Tag: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.op == other.op && self.layout.ty == other.layout.ty
|
||||
}
|
||||
}
|
||||
impl<'tcx, Tag> Eq for OpTy<'tcx, Tag>
|
||||
where Tag: Eq
|
||||
{}
|
||||
|
||||
impl<'tcx, Tag> OpTy<'tcx, Tag>
|
||||
{
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -874,7 +874,7 @@ impl LayoutDetails {
|
|||
/// to those obtained from `layout_of(ty)`, as we need to produce
|
||||
/// layouts for which Rust types do not exist, such as enum variants
|
||||
/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct TyLayout<'a, Ty> {
|
||||
pub ty: Ty,
|
||||
pub details: &'a LayoutDetails
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
pulldown-cmark = { version = "0.1.2", default-features = false }
|
||||
minifier = "0.0.19"
|
||||
minifier = "0.0.20"
|
||||
tempfile = "3"
|
||||
parking_lot = "0.6.4"
|
||||
|
|
|
|||
|
|
@ -4098,12 +4098,13 @@ impl<'a> fmt::Display for Sidebar<'a> {
|
|||
</div>",
|
||||
version)?;
|
||||
}
|
||||
|
||||
write!(fmt, "<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
|
||||
it.name.as_ref().expect("crates always have a name"))?;
|
||||
}
|
||||
|
||||
write!(fmt, "<div class=\"sidebar-elems\">")?;
|
||||
if it.is_crate() {
|
||||
write!(fmt, "<a id='all-types' href='all.html'><p>See all {}'s items</p></a>",
|
||||
it.name.as_ref().expect("crates always have a name"))?;
|
||||
}
|
||||
match it.inner {
|
||||
clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?,
|
||||
clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?,
|
||||
|
|
|
|||
|
|
@ -908,10 +908,9 @@ span.since {
|
|||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
body > .sidebar {
|
||||
height: 45px;
|
||||
min-height: 40px;
|
||||
width: calc(100% + 30px);
|
||||
margin: 0;
|
||||
margin-left: -15px;
|
||||
padding: 0 15px;
|
||||
|
|
@ -1013,6 +1012,10 @@ span.since {
|
|||
.anchor {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
h1.fqn {
|
||||
overflow: initial;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
|
@ -1112,6 +1115,18 @@ h4 > .important-traits {
|
|||
top: 2px;
|
||||
}
|
||||
|
||||
#all-types {
|
||||
text-align: center;
|
||||
border: 1px solid;
|
||||
margin: 0 10px;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
border-radius: 7px;
|
||||
}
|
||||
#all-types > p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
h4 > .important-traits {
|
||||
position: absolute;
|
||||
|
|
@ -1135,6 +1150,9 @@ h4 > .important-traits {
|
|||
background-color: rgba(0,0,0,0);
|
||||
height: 100%;
|
||||
}
|
||||
.sidebar {
|
||||
width: calc(100% + 30px);
|
||||
}
|
||||
|
||||
.show-it {
|
||||
display: block;
|
||||
|
|
@ -1180,6 +1198,10 @@ h4 > .important-traits {
|
|||
.impl > .collapse-toggle {
|
||||
left: -10px;
|
||||
}
|
||||
|
||||
#all-types {
|
||||
margin: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1383,17 +1405,6 @@ kbd {
|
|||
#main > ul > li {
|
||||
list-style: none;
|
||||
}
|
||||
#all-types {
|
||||
text-align: center;
|
||||
border: 1px solid;
|
||||
margin: 0 10px;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
border-radius: 7px;
|
||||
}
|
||||
#all-types > p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.non-exhaustive {
|
||||
margin-bottom: 1em;
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ impl OpenOptions {
|
|||
/// If a file is opened with both read and append access, beware that after
|
||||
/// opening, and after every write, the position for reading may be set at the
|
||||
/// end of the file. So, before writing, save the current position (using
|
||||
/// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`, and restore it before the next read.
|
||||
/// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`), and restore it before the next read.
|
||||
///
|
||||
/// ## Note
|
||||
///
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ pub use core::panic::{PanicInfo, Location};
|
|||
///
|
||||
/// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow
|
||||
/// witnessing a broken invariant through the use of `catch_unwind` (catching a
|
||||
/// panic). This trait is a marker trait, so it is automatically implemented for
|
||||
/// panic). This trait is an auto trait, so it is automatically implemented for
|
||||
/// many types, and it is also structurally composed (e.g. a struct is unwind
|
||||
/// safe if all of its components are unwind safe).
|
||||
///
|
||||
|
|
|
|||
|
|
@ -908,11 +908,36 @@ mod prim_usize { }
|
|||
/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
|
||||
/// references with longer lifetimes can be freely coerced into references with shorter ones.
|
||||
///
|
||||
/// Reference equality by address, instead of comparing the values pointed to, is accomplished via
|
||||
/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while
|
||||
/// [`PartialEq`] compares values.
|
||||
///
|
||||
/// [`ptr::eq`]: ptr/fn.eq.html
|
||||
/// [`PartialEq`]: cmp/trait.PartialEq.html
|
||||
///
|
||||
/// ```
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// let five = 5;
|
||||
/// let other_five = 5;
|
||||
/// let five_ref = &five;
|
||||
/// let same_five_ref = &five;
|
||||
/// let other_five_ref = &other_five;
|
||||
///
|
||||
/// assert!(five_ref == same_five_ref);
|
||||
/// assert!(five_ref == other_five_ref);
|
||||
///
|
||||
/// assert!(ptr::eq(five_ref, same_five_ref));
|
||||
/// assert!(!ptr::eq(five_ref, other_five_ref));
|
||||
/// ```
|
||||
///
|
||||
/// For more information on how to use references, see [the book's section on "References and
|
||||
/// Borrowing"][book-refs].
|
||||
///
|
||||
/// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html
|
||||
///
|
||||
/// # Trait implementations
|
||||
///
|
||||
/// The following traits are implemented for all `&T`, regardless of the type of its referent:
|
||||
///
|
||||
/// * [`Copy`]
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ impl Once {
|
|||
/// assert!(handle.join().is_err());
|
||||
/// assert_eq!(INIT.is_completed(), false);
|
||||
/// ```
|
||||
#[unstable(feature = "once_is_completed", issue = "42")]
|
||||
#[unstable(feature = "once_is_completed", issue = "54890")]
|
||||
#[inline]
|
||||
pub fn is_completed(&self) -> bool {
|
||||
// An `Acquire` load is enough because that makes all the initialization
|
||||
|
|
|
|||
|
|
@ -772,6 +772,11 @@ impl<'a> Parser<'a> {
|
|||
// | expected one of 8 possible tokens here
|
||||
err.span_label(self.span, label_exp);
|
||||
}
|
||||
_ if self.prev_span == syntax_pos::DUMMY_SP => {
|
||||
// Account for macro context where the previous span might not be
|
||||
// available to avoid incorrect output (#54841).
|
||||
err.span_label(self.span, "unexpected token");
|
||||
}
|
||||
_ => {
|
||||
err.span_label(sp, label_exp);
|
||||
err.span_label(self.span, "unexpected token");
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ extern crate rustdoc_nonreachable_impls;
|
|||
pub use rustdoc_nonreachable_impls::hidden::Wobble;
|
||||
|
||||
// @has issue_31948_1/trait.Bark.html
|
||||
// FIXME(33025): has - '//code' 'for Foo'
|
||||
// @has - '//code' 'for Foo'
|
||||
// @has - '//code' 'for Wobble'
|
||||
// @!has - '//code' 'for Wibble'
|
||||
pub use rustdoc_nonreachable_impls::Bark;
|
||||
|
||||
// @has issue_31948_1/trait.Woof.html
|
||||
// FIXME(33025): has - '//code' 'for Foo'
|
||||
// @has - '//code' 'for Foo'
|
||||
// @has - '//code' 'for Wobble'
|
||||
// @!has - '//code' 'for Wibble'
|
||||
pub use rustdoc_nonreachable_impls::Woof;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ extern crate rustdoc_nonreachable_impls;
|
|||
pub use rustdoc_nonreachable_impls::hidden::Wobble;
|
||||
|
||||
// @has issue_31948_2/trait.Qux.html
|
||||
// FIXME(33025): has - '//code' 'for Foo'
|
||||
// @has - '//code' 'for Foo'
|
||||
// @has - '//code' 'for Wobble'
|
||||
pub use rustdoc_nonreachable_impls::hidden::Qux;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
error[E0507]: cannot move out of borrowed content
|
||||
error[E0507]: cannot move out of dereference of raw pointer
|
||||
--> $DIR/borrowck-move-from-unsafe-ptr.rs:13:13
|
||||
|
|
||||
LL | let y = *x; //~ ERROR cannot move out of dereference of raw pointer
|
||||
| ^^
|
||||
| |
|
||||
| cannot move out of borrowed content
|
||||
| cannot move out of dereference of raw pointer
|
||||
| help: consider removing the `*`: `x`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
|
|||
|
|
@ -16,22 +16,22 @@ LL | let b = unsafe { *imm_ref() };
|
|||
| cannot move out of borrowed content
|
||||
| help: consider removing the `*`: `imm_ref()`
|
||||
|
||||
error[E0507]: cannot move out of borrowed content
|
||||
error[E0507]: cannot move out of dereference of raw pointer
|
||||
--> $DIR/issue-20801.rs:42:22
|
||||
|
|
||||
LL | let c = unsafe { *mut_ptr() };
|
||||
| ^^^^^^^^^^
|
||||
| |
|
||||
| cannot move out of borrowed content
|
||||
| cannot move out of dereference of raw pointer
|
||||
| help: consider removing the `*`: `mut_ptr()`
|
||||
|
||||
error[E0507]: cannot move out of borrowed content
|
||||
error[E0507]: cannot move out of dereference of raw pointer
|
||||
--> $DIR/issue-20801.rs:45:22
|
||||
|
|
||||
LL | let d = unsafe { *const_ptr() };
|
||||
| ^^^^^^^^^^^^
|
||||
| |
|
||||
| cannot move out of borrowed content
|
||||
| cannot move out of dereference of raw pointer
|
||||
| help: consider removing the `*`: `const_ptr()`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
|
|
|||
17
src/test/ui/lint/must_use-unit.rs
Normal file
17
src/test/ui/lint/must_use-unit.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#![feature(never_type)]
|
||||
|
||||
#![deny(unused_must_use)]
|
||||
|
||||
#[must_use]
|
||||
fn foo() {}
|
||||
|
||||
#[must_use]
|
||||
fn bar() -> ! {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(); //~ unused return value of `foo`
|
||||
|
||||
bar(); //~ unused return value of `bar`
|
||||
}
|
||||
20
src/test/ui/lint/must_use-unit.stderr
Normal file
20
src/test/ui/lint/must_use-unit.stderr
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
error: unused return value of `foo` which must be used
|
||||
--> $DIR/must_use-unit.rs:14:5
|
||||
|
|
||||
LL | foo(); //~ unused return value of `foo`
|
||||
| ^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/must_use-unit.rs:3:9
|
||||
|
|
||||
LL | #![deny(unused_must_use)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused return value of `bar` which must be used
|
||||
--> $DIR/must_use-unit.rs:16:5
|
||||
|
|
||||
LL | bar(); //~ unused return value of `bar`
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let`
|
||||
--> $DIR/issue-54441.rs:5:9
|
||||
|
|
||||
LL | #![feature(macros_in_extern)]
|
||||
| - expected one of `crate`, `fn`, `pub`, `static`, or `type` here
|
||||
...
|
||||
LL | let //~ ERROR expected
|
||||
| ^^^ unexpected token
|
||||
...
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue