Auto merge of #59226 - kennytm:rollup, r=kennytm

Rollup of 37 pull requests

Successful merges:

 - #58854 (appveyor: Use VS2017 for all our images)
 - #58855 (std: Spin for a global malloc lock on wasm32)
 - #58873 (Fix "Auto-hide item methods documentation" setting)
 - #58901 (Change `std::fs::copy` to use `copyfile` on MacOS and iOS)
 - #58933 (Move alloc::prelude::* to alloc::prelude::v1, make alloc a subset of std)
 - #58938 (core: ensure VaList passes improper_ctypes lint)
 - #58941 (MIPS: add r6 support)
 - #58949 (SGX target: Expose thread id function in os module)
 - #58959 (Add release notes for PR #56243)
 - #58976 (Default to integrated `rust-lld` linker for UEFI targets)
 - #59009 (Fix SGX implementations of read/write_vectored.)
 - #59025 (Fix generic argument lookup for Self)
 - #59036 (Fix ICE in MIR pretty printing)
 - #59037 (Avoid some common false positives in intra doc link checking)
 - #59072 (we can now skip should_panic tests with the libtest harness)
 - #59079 (add suggestions to invalid macro item error)
 - #59082 (A few improvements to comments in user-facing crates)
 - #59102 (Consistent naming for duration_float methods and additional f32 methods)
 - #59118 (rustc: fix ICE when trait alias has bare Self)
 - #59139 (Unregress using scalar unions in constants.)
 - #59146 (Suggest return lifetime when there's only one named lifetime)
 - #59147 (Make std time tests more robust for platform differences)
 - #59152 (Stabilize Range*::contains.)
 - #59156 ([wg-async-await] Add regression test for #55809.)
 - #59158 (Revert "Don't generate minification variable if minification disabled")
 - #59169 (Add `-Z allow_features=...` flag)
 - #59173 (bootstrap: Default to a sensible llvm-suffix.)
 - #59175 (Don't run test launching `echo` since that doesn't exist on Windows)
 - #59180 (Use try blocks in rustc_codegen_ssa)
 - #59185 (No old chestnuts in iter::repeat docs)
 - #59201 (Remove restriction on isize/usize in repr(simd))
 - #59204 (Output diagnostic information for rustdoc)
 - #59206 (Improved test output)
 - #59208 (Reduce a Code Repetition Related to Bit Operation)
 - #59212 (Add x86_64 musl host to the manifest)
 - #59221 (Option and Result: Add references to documentation of as_ref and as_mut)
 - #59231 (Stabilize Option::copied)
This commit is contained in:
bors 2019-03-16 14:46:43 +00:00
commit 2c8bbf50db
109 changed files with 1184 additions and 492 deletions

View File

@ -110,8 +110,11 @@ Compatibility Notes
methods instead.
- The `Error::cause` method has been deprecated in favor of `Error::source` which supports
downcasting.
- [Libtest no longer creates a new thread for each test when
`--test-threads=1`. It also runs the tests in deterministic order][56243]
[55982]: https://github.com/rust-lang/rust/pull/55982/
[56243]: https://github.com/rust-lang/rust/pull/56243
[56303]: https://github.com/rust-lang/rust/pull/56303/
[56351]: https://github.com/rust-lang/rust/pull/56351/
[56362]: https://github.com/rust-lang/rust/pull/56362

View File

@ -1,4 +1,7 @@
environment:
# This is required for at least an AArch64 compiler in one image, and is also
# going to soon be required for compiling LLVM.
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview
# By default schannel checks revocation of certificates unlike some other SSL
# backends, but we've historically had problems on CI where a revocation
@ -81,7 +84,6 @@ environment:
DIST_REQUIRE_ALL_TOOLS: 1
DEPLOY: 1
CI_JOB_NAME: dist-x86_64-msvc
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 Preview
- RUST_CONFIGURE_ARGS: >
--build=i686-pc-windows-msvc
--target=i586-pc-windows-msvc

View File

@ -35,7 +35,7 @@ fn main() {
.arg("--cfg")
.arg("dox")
.arg("--sysroot")
.arg(sysroot)
.arg(&sysroot)
.env(bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap());
@ -72,7 +72,13 @@ fn main() {
}
if verbose > 1 {
eprintln!("rustdoc command: {:?}", cmd);
eprintln!(
"rustdoc command: {:?}={:?} {:?}",
bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap(),
cmd,
);
eprintln!("sysroot: {:?}", sysroot);
eprintln!("libdir: {:?}", libdir);
}

View File

@ -408,11 +408,11 @@ impl<'a> Builder<'a> {
test::RustdocJSStd,
test::RustdocJSNotStd,
test::RustdocTheme,
test::RustdocUi,
// Run bootstrap close to the end as it's unlikely to fail
test::Bootstrap,
// Run run-make last, since these won't pass without make on Windows
test::RunMake,
test::RustdocUi
),
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
Kind::Doc => describe!(

View File

@ -241,6 +241,8 @@ pub struct Build {
clippy_info: channel::GitInfo,
miri_info: channel::GitInfo,
rustfmt_info: channel::GitInfo,
in_tree_llvm_info: channel::GitInfo,
emscripten_llvm_info: channel::GitInfo,
local_rebuild: bool,
fail_fast: bool,
doc_tests: DocTests,
@ -363,6 +365,8 @@ impl Build {
let clippy_info = channel::GitInfo::new(&config, &src.join("src/tools/clippy"));
let miri_info = channel::GitInfo::new(&config, &src.join("src/tools/miri"));
let rustfmt_info = channel::GitInfo::new(&config, &src.join("src/tools/rustfmt"));
let in_tree_llvm_info = channel::GitInfo::new(&config, &src.join("src/llvm-project"));
let emscripten_llvm_info = channel::GitInfo::new(&config, &src.join("src/llvm-emscripten"));
let mut build = Build {
initial_rustc: config.initial_rustc.clone(),
@ -386,6 +390,8 @@ impl Build {
clippy_info,
miri_info,
rustfmt_info,
in_tree_llvm_info,
emscripten_llvm_info,
cc: HashMap::new(),
cxx: HashMap::new(),
ar: HashMap::new(),

View File

@ -18,6 +18,7 @@ use build_helper::output;
use cmake;
use cc;
use crate::channel;
use crate::util::{self, exe};
use build_helper::up_to_date;
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
@ -231,7 +232,26 @@ impl Step for Llvm {
}
if let Some(ref suffix) = builder.config.llvm_version_suffix {
cfg.define("LLVM_VERSION_SUFFIX", suffix);
// Allow version-suffix="" to not define a version suffix at all.
if !suffix.is_empty() {
cfg.define("LLVM_VERSION_SUFFIX", suffix);
}
} else {
let mut default_suffix = format!(
"-rust-{}-{}",
channel::CFG_RELEASE_NUM,
builder.config.channel,
);
let llvm_info = if self.emscripten {
&builder.emscripten_llvm_info
} else {
&builder.in_tree_llvm_info
};
if let Some(sha) = llvm_info.sha_short() {
default_suffix.push_str("-");
default_suffix.push_str(sha);
}
cfg.define("LLVM_VERSION_SUFFIX", default_suffix);
}
if let Some(ref linker) = builder.config.llvm_use_linker {

View File

@ -1,19 +0,0 @@
//! The alloc Prelude
//!
//! The purpose of this module is to alleviate imports of commonly-used
//! items of the `alloc` crate by adding a glob import to the top of modules:
//!
//! ```
//! # #![allow(unused_imports)]
//! # #![feature(alloc)]
//! extern crate alloc;
//! use alloc::prelude::*;
//! ```
#![unstable(feature = "alloc", issue = "27783")]
#[unstable(feature = "alloc", issue = "27783")] pub use crate::borrow::ToOwned;
#[unstable(feature = "alloc", issue = "27783")] pub use crate::boxed::Box;
#[unstable(feature = "alloc", issue = "27783")] pub use crate::slice::SliceConcatExt;
#[unstable(feature = "alloc", issue = "27783")] pub use crate::string::{String, ToString};
#[unstable(feature = "alloc", issue = "27783")] pub use crate::vec::Vec;

View File

@ -0,0 +1,16 @@
//! The alloc Prelude
//!
//! The purpose of this module is to alleviate imports of commonly-used
//! items of the `alloc` crate by adding a glob import to the top of modules:
//!
//! ```
//! # #![allow(unused_imports)]
//! # #![feature(alloc)]
//! #![feature(alloc_prelude)]
//! extern crate alloc;
//! use alloc::prelude::v1::*;
//! ```
#![unstable(feature = "alloc_prelude", issue = "58935")]
pub mod v1;

View File

@ -0,0 +1,11 @@
//! The first version of the prelude of `alloc` crate.
//!
//! See the [module-level documentation](../index.html) for more.
#![unstable(feature = "alloc_prelude", issue = "58935")]
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::borrow::ToOwned;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::boxed::Box;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::slice::SliceConcatExt;
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::string::{String, ToString};
#[unstable(feature = "alloc_prelude", issue = "58935")] pub use crate::vec::Vec;

View File

@ -282,7 +282,7 @@ fn assert_covariance() {
//
// Destructors must be called exactly once per element.
#[test]
#[cfg(not(miri))] // Miri does not support panics
#[cfg(not(miri))] // Miri does not support panics nor entropy
fn panic_safe() {
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);

View File

@ -226,7 +226,6 @@ fn test_range_equal_empty_cases() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_range_equal_excluded() {
let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
map.range((Excluded(2), Excluded(2)));
@ -234,7 +233,6 @@ fn test_range_equal_excluded() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_range_backwards_1() {
let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
map.range((Included(3), Included(2)));
@ -242,7 +240,6 @@ fn test_range_backwards_1() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_range_backwards_2() {
let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
map.range((Included(3), Excluded(2)));
@ -250,7 +247,6 @@ fn test_range_backwards_2() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_range_backwards_3() {
let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
map.range((Excluded(3), Included(2)));
@ -258,7 +254,6 @@ fn test_range_backwards_3() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_range_backwards_4() {
let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
map.range((Excluded(3), Excluded(2)));

View File

@ -258,7 +258,6 @@ fn test_swap_remove() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_swap_remove_fail() {
let mut v = vec![1];
let _ = v.swap_remove(0);
@ -632,7 +631,6 @@ fn test_insert() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_insert_oob() {
let mut a = vec![1, 2, 3];
a.insert(4, 5);
@ -657,7 +655,6 @@ fn test_remove() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_remove_fail() {
let mut a = vec![1];
let _ = a.remove(0);
@ -939,7 +936,6 @@ fn test_windowsator() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_windowsator_0() {
let v = &[1, 2, 3, 4];
let _it = v.windows(0);
@ -964,7 +960,6 @@ fn test_chunksator() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_chunksator_0() {
let v = &[1, 2, 3, 4];
let _it = v.chunks(0);
@ -989,7 +984,6 @@ fn test_chunks_exactator() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_chunks_exactator_0() {
let v = &[1, 2, 3, 4];
let _it = v.chunks_exact(0);
@ -1014,7 +1008,6 @@ fn test_rchunksator() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_rchunksator_0() {
let v = &[1, 2, 3, 4];
let _it = v.rchunks(0);
@ -1039,7 +1032,6 @@ fn test_rchunks_exactator() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_rchunks_exactator_0() {
let v = &[1, 2, 3, 4];
let _it = v.rchunks_exact(0);
@ -1092,7 +1084,6 @@ fn test_vec_default() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_overflow_does_not_cause_segfault() {
let mut v = vec![];
v.reserve_exact(!0);
@ -1102,7 +1093,6 @@ fn test_overflow_does_not_cause_segfault() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_overflow_does_not_cause_segfault_managed() {
let mut v = vec![Rc::new(1)];
v.reserve_exact(!0);
@ -1278,7 +1268,6 @@ fn test_mut_chunks_rev() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mut_chunks_0() {
let mut v = [1, 2, 3, 4];
let _it = v.chunks_mut(0);
@ -1311,7 +1300,6 @@ fn test_mut_chunks_exact_rev() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mut_chunks_exact_0() {
let mut v = [1, 2, 3, 4];
let _it = v.chunks_exact_mut(0);
@ -1344,7 +1332,6 @@ fn test_mut_rchunks_rev() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mut_rchunks_0() {
let mut v = [1, 2, 3, 4];
let _it = v.rchunks_mut(0);
@ -1377,7 +1364,6 @@ fn test_mut_rchunks_exact_rev() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mut_rchunks_exact_0() {
let mut v = [1, 2, 3, 4];
let _it = v.rchunks_exact_mut(0);
@ -1411,7 +1397,7 @@ fn test_box_slice_clone() {
#[test]
#[allow(unused_must_use)] // here, we care about the side effects of `.clone()`
#[cfg_attr(target_os = "emscripten", ignore)]
#[cfg(not(miri))] // Miri does not support panics
#[cfg(not(miri))] // Miri does not support threads nor entropy
fn test_box_slice_clone_panics() {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
@ -1476,7 +1462,6 @@ fn test_copy_from_slice() {
#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
#[cfg(not(miri))] // Miri does not support panics
fn test_copy_from_slice_dst_longer() {
let src = [0, 1, 2, 3];
let mut dst = [0; 5];
@ -1485,7 +1470,6 @@ fn test_copy_from_slice_dst_longer() {
#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
#[cfg(not(miri))] // Miri does not support panics
fn test_copy_from_slice_dst_shorter() {
let src = [0, 1, 2, 3];
let mut dst = [0; 3];
@ -1605,7 +1589,7 @@ thread_local!(static SILENCE_PANIC: Cell<bool> = Cell::new(false));
#[test]
#[cfg_attr(target_os = "emscripten", ignore)] // no threads
#[cfg(not(miri))] // Miri does not support panics
#[cfg(not(miri))] // Miri does not support threads nor entropy
fn panic_safe() {
let prev = panic::take_hook();
panic::set_hook(Box::new(move |info| {

View File

@ -7,7 +7,7 @@ fn test_le() {
assert!("" <= "");
assert!("" <= "foo");
assert!("foo" <= "foo");
assert!("foo" != "bar");
assert_ne!("foo", "bar");
}
#[test]
@ -351,7 +351,6 @@ mod slice_index {
// to be used in `should_panic`)
#[test]
#[should_panic(expected = "out of bounds")]
#[cfg(not(miri))] // Miri does not support panics
fn assert_range_eq_can_fail_by_panic() {
assert_range_eq!("abc", 0..5, "abc");
}
@ -361,7 +360,6 @@ mod slice_index {
// to be used in `should_panic`)
#[test]
#[should_panic(expected = "==")]
#[cfg(not(miri))] // Miri does not support panics
fn assert_range_eq_can_fail_by_inequality() {
assert_range_eq!("abc", 0..2, "abc");
}
@ -409,7 +407,6 @@ mod slice_index {
#[test]
#[should_panic(expected = $expect_msg)]
#[cfg(not(miri))] // Miri does not support panics
fn index_fail() {
let v: String = $data.into();
let v: &str = &v;
@ -418,7 +415,6 @@ mod slice_index {
#[test]
#[should_panic(expected = $expect_msg)]
#[cfg(not(miri))] // Miri does not support panics
fn index_mut_fail() {
let mut v: String = $data.into();
let v: &mut str = &mut v;
@ -514,7 +510,6 @@ mod slice_index {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_fail() {
&"中华Việt Nam"[0..2];
}
@ -666,14 +661,12 @@ mod slice_index {
// check the panic includes the prefix of the sliced string
#[test]
#[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_fail_truncated_1() {
&LOREM_PARAGRAPH[..1024];
}
// check the truncation in the panic message
#[test]
#[should_panic(expected="luctus, im`[...]")]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_fail_truncated_2() {
&LOREM_PARAGRAPH[..1024];
}
@ -688,7 +681,6 @@ fn test_str_slice_rangetoinclusive_ok() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_str_slice_rangetoinclusive_notok() {
let s = "abcαβγ";
&s[..=3];
@ -704,7 +696,6 @@ fn test_str_slicemut_rangetoinclusive_ok() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_str_slicemut_rangetoinclusive_notok() {
let mut s = "abcαβγ".to_owned();
let s: &mut str = &mut s;
@ -894,7 +885,6 @@ fn test_as_bytes() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_as_bytes_fail() {
// Don't double free. (I'm not sure if this exercises the
// original problem code path anymore.)
@ -984,7 +974,6 @@ fn test_split_at_mut() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_split_at_boundscheck() {
let s = "ศไทย中华Việt Nam";
s.split_at(1);

View File

@ -231,7 +231,6 @@ fn test_split_off_empty() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_split_off_past_end() {
let orig = "Hello, world!";
let mut split = String::from(orig);
@ -240,7 +239,6 @@ fn test_split_off_past_end() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_split_off_mid_char() {
let mut orig = String::from("");
orig.split_off(1);
@ -289,7 +287,6 @@ fn test_str_truncate_invalid_len() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_str_truncate_split_codepoint() {
let mut s = String::from("\u{FC}"); // ü
s.truncate(1);
@ -324,7 +321,6 @@ fn remove() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn remove_bad() {
"".to_string().remove(1);
}
@ -360,13 +356,11 @@ fn insert() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn insert_bad1() {
"".to_string().insert(1, 't');
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn insert_bad2() {
"".to_string().insert(1, 't');
}
@ -447,7 +441,6 @@ fn test_replace_range() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_replace_range_char_boundary() {
let mut s = "Hello, 世界!".to_owned();
s.replace_range(..8, "");
@ -464,7 +457,6 @@ fn test_replace_range_inclusive_range() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_replace_range_out_of_bounds() {
let mut s = String::from("12345");
s.replace_range(5..6, "789");
@ -472,7 +464,6 @@ fn test_replace_range_out_of_bounds() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_replace_range_inclusive_out_of_bounds() {
let mut s = String::from("12345");
s.replace_range(5..=5, "789");

View File

@ -368,7 +368,6 @@ fn test_vec_truncate_drop() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_vec_truncate_fail() {
struct BadElem(i32);
impl Drop for BadElem {
@ -392,7 +391,6 @@ fn test_index() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_index_out_of_bounds() {
let vec = vec![1, 2, 3];
let _ = vec[3];
@ -400,7 +398,6 @@ fn test_index_out_of_bounds() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_out_of_bounds_1() {
let x = vec![1, 2, 3, 4, 5];
&x[!0..];
@ -408,7 +405,6 @@ fn test_slice_out_of_bounds_1() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_out_of_bounds_2() {
let x = vec![1, 2, 3, 4, 5];
&x[..6];
@ -416,7 +412,6 @@ fn test_slice_out_of_bounds_2() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_out_of_bounds_3() {
let x = vec![1, 2, 3, 4, 5];
&x[!0..4];
@ -424,7 +419,6 @@ fn test_slice_out_of_bounds_3() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_out_of_bounds_4() {
let x = vec![1, 2, 3, 4, 5];
&x[1..6];
@ -432,7 +426,6 @@ fn test_slice_out_of_bounds_4() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_slice_out_of_bounds_5() {
let x = vec![1, 2, 3, 4, 5];
&x[3..2];
@ -440,7 +433,6 @@ fn test_slice_out_of_bounds_5() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_swap_remove_empty() {
let mut vec = Vec::<i32>::new();
vec.swap_remove(0);
@ -511,7 +503,6 @@ fn test_drain_items_zero_sized() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_drain_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
v.drain(5..6);
@ -585,7 +576,6 @@ fn test_drain_max_vec_size() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_drain_inclusive_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
v.drain(5..=5);
@ -615,7 +605,6 @@ fn test_splice_inclusive_range() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_splice_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
let a = [10, 11, 12];
@ -624,7 +613,6 @@ fn test_splice_out_of_bounds() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_splice_inclusive_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
let a = [10, 11, 12];

View File

@ -108,7 +108,6 @@ fn test_index() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_index_out_of_bounds() {
let mut deq = VecDeque::new();
for i in 1..4 {

View File

@ -79,9 +79,9 @@ impl fmt::Debug for VaListImpl {
all supported platforms",
issue = "44930")]
struct VaListImpl {
stack: *mut (),
gr_top: *mut (),
vr_top: *mut (),
stack: *mut c_void,
gr_top: *mut c_void,
vr_top: *mut c_void,
gr_offs: i32,
vr_offs: i32,
}
@ -98,8 +98,8 @@ struct VaListImpl {
gpr: u8,
fpr: u8,
reserved: u16,
overflow_arg_area: *mut (),
reg_save_area: *mut (),
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
}
/// x86_64 ABI implementation of a `va_list`.
@ -113,8 +113,8 @@ struct VaListImpl {
struct VaListImpl {
gp_offset: i32,
fp_offset: i32,
overflow_arg_area: *mut (),
reg_save_area: *mut (),
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
}
/// A wrapper for a `va_list`

View File

@ -1198,7 +1198,7 @@ impl<I: Iterator> Peekable<I> {
}
}
/// An iterator that rejects elements while `predicate` is true.
/// An iterator that rejects elements while `predicate` returns `true`.
///
/// This `struct` is created by the [`skip_while`] method on [`Iterator`]. See its
/// documentation for more.
@ -1286,7 +1286,7 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P>
impl<I, P> FusedIterator for SkipWhile<I, P>
where I: FusedIterator, P: FnMut(&I::Item) -> bool {}
/// An iterator that only accepts elements while `predicate` is true.
/// An iterator that only accepts elements while `predicate` returns `true`.
///
/// This `struct` is created by the [`take_while`] method on [`Iterator`]. See its
/// documentation for more.

View File

@ -39,8 +39,7 @@ unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
/// Creates a new iterator that endlessly repeats a single element.
///
/// The `repeat()` function repeats a single value over and over and over and
/// over and over and 🔁.
/// The `repeat()` function repeats a single value over and over again.
///
/// Infinite iterators like `repeat()` are often used with adapters like
/// [`take`], in order to make them finite.
@ -128,8 +127,7 @@ unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
/// Creates a new iterator that repeats elements of type `A` endlessly by
/// applying the provided closure, the repeater, `F: FnMut() -> A`.
///
/// The `repeat_with()` function calls the repeater over and over and over and
/// over and over and 🔁.
/// The `repeat_with()` function calls the repeater over and over again.
///
/// Infinite iterators like `repeat_with()` are often used with adapters like
/// [`take`], in order to make them finite.

View File

@ -1111,11 +1111,12 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
/// ```
///
/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
//
// FIXME before stabilizing, explain how to initialize a struct field-by-field.
#[allow(missing_debug_implementations)]
#[unstable(feature = "maybe_uninit", issue = "53491")]
#[derive(Copy)]
// NOTE after stabilizing `MaybeUninit` proceed to deprecate `mem::uninitialized`.
// NOTE: after stabilizing `MaybeUninit`, proceed to deprecate `mem::uninitialized`.
pub union MaybeUninit<T> {
uninit: (),
value: ManuallyDrop<T>,
@ -1125,13 +1126,13 @@ pub union MaybeUninit<T> {
impl<T: Copy> Clone for MaybeUninit<T> {
#[inline(always)]
fn clone(&self) -> Self {
// Not calling T::clone(), we cannot know if we are initialized enough for that.
// Not calling `T::clone()`, we cannot know if we are initialized enough for that.
*self
}
}
impl<T> MaybeUninit<T> {
/// Create a new `MaybeUninit<T>` initialized with the given value.
/// Creates a new `MaybeUninit<T>` initialized with the given value.
///
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
@ -1239,6 +1240,7 @@ impl<T> MaybeUninit<T> {
/// let x_vec = unsafe { &*x.as_ptr() };
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
/// ```
///
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
/// until they are, it is advisable to avoid them.)
#[unstable(feature = "maybe_uninit", issue = "53491")]
@ -1277,6 +1279,7 @@ impl<T> MaybeUninit<T> {
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
/// // We have created a reference to an uninitialized vector! This is undefined behavior.
/// ```
///
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
/// until they are, it is advisable to avoid them.)
#[unstable(feature = "maybe_uninit", issue = "53491")]

View File

@ -326,7 +326,7 @@ pub fn algorithm_m<T: RawFloat>(f: &Big, e: i16) -> T {
round_by_remainder(v, rem, q, z)
}
/// Skip over most Algorithm M iterations by checking the bit length.
/// Skips over most Algorithm M iterations by checking the bit length.
fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
// The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v).
// The estimate is off by at most 1, but always an under-estimate, so the error on log(u)

View File

@ -304,8 +304,8 @@ fn simplify(decimal: &mut Decimal) {
}
}
/// Quick and dirty upper bound on the size (log10) of the largest value that Algorithm R and
/// Algorithm M will compute while working on the given decimal.
/// Returns a quick-an-dirty upper bound on the size (log10) of the largest value that Algorithm R
/// and Algorithm M will compute while working on the given decimal.
fn bound_intermediate_digits(decimal: &Decimal, e: i64) -> u64 {
// We don't need to worry too much about overflow here thanks to trivial_cases() and the
// parser, which filter out the most extreme inputs for us.
@ -324,7 +324,7 @@ fn bound_intermediate_digits(decimal: &Decimal, e: i64) -> u64 {
}
}
/// Detect obvious overflows and underflows without even looking at the decimal digits.
/// Detects obvious overflows and underflows without even looking at the decimal digits.
fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
// There were zeros but they were stripped by simplify()
if decimal.integral.is_empty() && decimal.fractional.is_empty() {

View File

@ -78,7 +78,7 @@ pub fn parse_decimal(s: &str) -> ParseResult {
}
}
/// Carve off decimal digits up to the first non-digit character.
/// Carves off decimal digits up to the first non-digit character.
fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) {
let mut i = 0;
while i < s.len() && b'0' <= s[i] && s[i] <= b'9' {

View File

@ -10,7 +10,7 @@ use num::dec2flt::rawfp::RawFloat;
///
/// - Any number from `(mant - minus) * 2^exp` to `(mant + plus) * 2^exp` will
/// round to the original value. The range is inclusive only when
/// `inclusive` is true.
/// `inclusive` is `true`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Decoded {
/// The scaled mantissa.

View File

@ -315,15 +315,15 @@ fn digits_to_dec_str<'a>(buf: &'a [u8], exp: i16, frac_digits: usize,
}
}
/// Formats given decimal digits `0.<...buf...> * 10^exp` into the exponential form
/// with at least given number of significant digits. When `upper` is true,
/// Formats the given decimal digits `0.<...buf...> * 10^exp` into the exponential
/// form with at least the given number of significant digits. When `upper` is `true`,
/// the exponent will be prefixed by `E`; otherwise that's `e`. The result is
/// stored to the supplied parts array and a slice of written parts is returned.
///
/// `min_digits` can be less than the number of actual significant digits in `buf`;
/// it will be ignored and full digits will be printed. It is only used to print
/// additional zeroes after rendered digits. Thus `min_digits` of 0 means that
/// it will only print given digits and nothing else.
/// additional zeroes after rendered digits. Thus, `min_digits == 0` means that
/// it will only print the given digits and nothing else.
fn digits_to_exp_str<'a>(buf: &'a [u8], exp: i16, min_ndigits: usize, upper: bool,
parts: &'a mut [Part<'a>]) -> &'a [Part<'a>] {
assert!(!buf.is_empty());
@ -384,7 +384,7 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static
}
}
/// Formats given floating point number into the decimal form with at least
/// Formats the given floating point number into the decimal form with at least
/// given number of fractional digits. The result is stored to the supplied parts
/// array while utilizing given byte buffer as a scratch. `upper` is currently
/// unused but left for the future decision to change the case of non-finite values,
@ -438,7 +438,7 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
}
}
/// Formats given floating point number into the decimal form or
/// Formats the given floating point number into the decimal form or
/// the exponential form, depending on the resulting exponent. The result is
/// stored to the supplied parts array while utilizing given byte buffer
/// as a scratch. `upper` is used to determine the case of non-finite values
@ -497,7 +497,7 @@ pub fn to_shortest_exp_str<'a, T, F>(mut format_shortest: F, v: T,
}
}
/// Returns rather crude approximation (upper bound) for the maximum buffer size
/// Returns a rather crude approximation (upper bound) for the maximum buffer size
/// calculated from the given decoded exponent.
///
/// The exact limit is:

View File

@ -71,7 +71,7 @@ impl fmt::Debug for RangeFull {
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
/// ```
#[doc(alias = "..")]
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Range<Idx> {
/// The lower bound of the range (inclusive).
@ -95,8 +95,6 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
///
/// use std::f32;
///
/// assert!(!(3..5).contains(&2));
@ -112,7 +110,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// assert!(!(0.0..f32::NAN).contains(&0.5));
/// assert!(!(f32::NAN..1.0).contains(&0.5));
/// ```
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
@ -175,7 +173,7 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
///
/// [`Iterator`]: ../iter/trait.IntoIterator.html
#[doc(alias = "..")]
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFrom<Idx> {
/// The lower bound of the range (inclusive).
@ -196,8 +194,6 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
///
/// use std::f32;
///
/// assert!(!(3..).contains(&2));
@ -208,7 +204,7 @@ impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// assert!(!(0.0..).contains(&f32::NAN));
/// assert!(!(f32::NAN..).contains(&0.5));
/// ```
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
@ -280,8 +276,6 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
///
/// use std::f32;
///
/// assert!( (..5).contains(&-1_000_000_000));
@ -292,7 +286,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// assert!(!(..1.0).contains(&f32::NAN));
/// assert!(!(..f32::NAN).contains(&0.5));
/// ```
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
@ -329,7 +323,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive
/// ```
#[doc(alias = "..=")]
#[derive(Clone)] // not Copy -- see #27186
#[derive(Clone)] // not Copy -- see #27186
#[stable(feature = "inclusive_range", since = "1.26.0")]
pub struct RangeInclusive<Idx> {
pub(crate) start: Idx,
@ -365,7 +359,8 @@ impl<T: PartialOrd> RangeInclusiveEquality for T {
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.start == other.start && self.end == other.end
self.start == other.start
&& self.end == other.end
&& RangeInclusiveEquality::canonicalized_is_empty(self)
== RangeInclusiveEquality::canonicalized_is_empty(other)
}
@ -397,7 +392,11 @@ impl<Idx> RangeInclusive<Idx> {
#[inline]
#[rustc_promotable]
pub const fn new(start: Idx, end: Idx) -> Self {
Self { start, end, is_empty: None }
Self {
start,
end,
is_empty: None,
}
}
/// Returns the lower bound of the range (inclusive).
@ -478,8 +477,6 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
///
/// use std::f32;
///
/// assert!(!(3..=5).contains(&2));
@ -496,7 +493,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// assert!(!(0.0..=f32::NAN).contains(&0.0));
/// assert!(!(f32::NAN..=1.0).contains(&1.0));
/// ```
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
@ -609,15 +606,12 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
}
}
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains)]
///
/// use std::f32;
///
/// assert!( (..=5).contains(&-1_000_000_000));
@ -628,7 +622,7 @@ impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// assert!(!(..=1.0).contains(&f32::NAN));
/// assert!(!(..=f32::NAN).contains(&0.5));
/// ```
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
#[stable(feature = "range_contains", since = "1.35.0")]
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
@ -730,14 +724,11 @@ pub trait RangeBounds<T: ?Sized> {
#[stable(feature = "collections_range", since = "1.28.0")]
fn end_bound(&self) -> Bound<&T>;
/// Returns `true` if `item` is contained in the range.
///
/// # Examples
///
/// ```
/// #![feature(range_contains)]
///
/// use std::f32;
///
/// assert!( (3..5).contains(&4));
@ -747,7 +738,7 @@ pub trait RangeBounds<T: ?Sized> {
/// assert!(!(0.0..1.0).contains(&f32::NAN));
/// assert!(!(0.0..f32::NAN).contains(&0.5));
/// assert!(!(f32::NAN..1.0).contains(&0.5));
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
#[stable(feature = "range_contains", since = "1.35.0")]
fn contains<U>(&self, item: &U) -> bool
where
T: PartialOrd<U>,
@ -757,9 +748,7 @@ pub trait RangeBounds<T: ?Sized> {
Included(ref start) => *start <= item,
Excluded(ref start) => *start < item,
Unbounded => true,
})
&&
(match self.end_bound() {
}) && (match self.end_bound() {
Included(ref end) => item <= *end,
Excluded(ref end) => item < *end,
Unbounded => true,
@ -835,7 +824,7 @@ impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
match *self {
(Included(ref start), _) => Included(start),
(Excluded(ref start), _) => Excluded(start),
(Unbounded, _) => Unbounded,
(Unbounded, _) => Unbounded,
}
}
@ -843,7 +832,7 @@ impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
match *self {
(_, Included(ref end)) => Included(end),
(_, Excluded(ref end)) => Excluded(end),
(_, Unbounded) => Unbounded,
(_, Unbounded) => Unbounded,
}
}
}

View File

@ -210,7 +210,7 @@ impl<T> Option<T> {
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////
/// Converts from `Option<T>` to `Option<&T>`.
/// Converts from `&Option<T>` to `Option<&T>`.
///
/// # Examples
///
@ -239,7 +239,7 @@ impl<T> Option<T> {
}
}
/// Converts from `Option<T>` to `Option<&mut T>`.
/// Converts from `&mut Option<T>` to `Option<&mut T>`.
///
/// # Examples
///
@ -881,15 +881,13 @@ impl<T: Copy> Option<&T> {
/// # Examples
///
/// ```
/// #![feature(copied)]
///
/// let x = 12;
/// let opt_x = Some(&x);
/// assert_eq!(opt_x, Some(&12));
/// let copied = opt_x.copied();
/// assert_eq!(copied, Some(12));
/// ```
#[unstable(feature = "copied", issue = "57126")]
#[stable(feature = "copied", since = "1.35.0")]
pub fn copied(self) -> Option<T> {
self.map(|&t| t)
}
@ -902,15 +900,13 @@ impl<T: Copy> Option<&mut T> {
/// # Examples
///
/// ```
/// #![feature(copied)]
///
/// let mut x = 12;
/// let opt_x = Some(&mut x);
/// assert_eq!(opt_x, Some(&mut 12));
/// let copied = opt_x.copied();
/// assert_eq!(copied, Some(12));
/// ```
#[unstable(feature = "copied", issue = "57126")]
#[stable(feature = "copied", since = "1.35.0")]
pub fn copied(self) -> Option<T> {
self.map(|&mut t| t)
}

View File

@ -1,4 +1,4 @@
//! Types which pin data to its location in memory
//! Types that pin data to its location in memory.
//!
//! It is sometimes useful to have objects that are guaranteed to not move,
//! in the sense that their placement in memory does not change, and can thus be relied upon.

View File

@ -369,7 +369,7 @@ impl<T, E> Result<T, E> {
// Adapter for working with references
/////////////////////////////////////////////////////////////////////////
/// Converts from `Result<T, E>` to `Result<&T, &E>`.
/// Converts from `&Result<T, E>` to `Result<&T, &E>`.
///
/// Produces a new `Result`, containing a reference
/// into the original, leaving the original in place.
@ -394,7 +394,7 @@ impl<T, E> Result<T, E> {
}
}
/// Converts from `Result<T, E>` to `Result<&mut T, &mut E>`.
/// Converts from `&mut Result<T, E>` to `Result<&mut T, &mut E>`.
///
/// # Examples
///

View File

@ -2968,7 +2968,7 @@ impl str {
///
/// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
/// elements. This is true for, e.g., [`char`], but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
///
@ -3143,7 +3143,7 @@ impl str {
///
/// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
/// elements. This is true for, e.g., [`char`], but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
///
@ -3326,7 +3326,7 @@ impl str {
///
/// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
/// elements. This is true for, e.g., [`char`], but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
///
@ -3402,7 +3402,7 @@ impl str {
///
/// The returned iterator will be a [`DoubleEndedIterator`] if the pattern
/// allows a reverse search and forward/reverse search yields the same
/// elements. This is true for, eg, [`char`] but not for `&str`.
/// elements. This is true for, e.g., [`char`], but not for `&str`.
///
/// [`DoubleEndedIterator`]: iter/trait.DoubleEndedIterator.html
///

View File

@ -108,7 +108,7 @@ impl Waker {
unsafe { (self.waker.vtable.wake)(self.waker.data) }
}
/// Returns whether or not this `Waker` and other `Waker` have awaken the same task.
/// Returns `true` if this `Waker` and another `Waker` have awoken the same task.
///
/// This function works on a best-effort basis, and may return false even
/// when the `Waker`s would awaken the same task. However, if this function

View File

@ -5,15 +5,15 @@ use std::mem::drop;
#[test]
fn smoketest_cell() {
let x = Cell::new(10);
assert!(x == Cell::new(10));
assert!(x.get() == 10);
assert_eq!(x, Cell::new(10));
assert_eq!(x.get(), 10);
x.set(20);
assert!(x == Cell::new(20));
assert!(x.get() == 20);
assert_eq!(x, Cell::new(20));
assert_eq!(x.get(), 20);
let y = Cell::new((30, 40));
assert!(y == Cell::new((30, 40)));
assert!(y.get() == (30, 40));
assert_eq!(y, Cell::new((30, 40)));
assert_eq!(y.get(), (30, 40));
}
#[test]
@ -109,7 +109,6 @@ fn double_borrow_single_release_no_borrow_mut() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn discard_doesnt_unborrow() {
let x = RefCell::new(0);
let _b = x.borrow();
@ -350,7 +349,6 @@ fn refcell_ref_coercion() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn refcell_swap_borrows() {
let x = RefCell::new(0);
let _b = x.borrow();
@ -360,7 +358,6 @@ fn refcell_swap_borrows() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn refcell_replace_borrows() {
let x = RefCell::new(0);
let _b = x.borrow();

View File

@ -253,7 +253,6 @@ fn test_iterator_step_by_nth_overflow() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_iterator_step_by_zero() {
let mut it = (0..).step_by(0);
it.next();
@ -1442,7 +1441,6 @@ fn test_rposition() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_rposition_panic() {
let v: [(Box<_>, Box<_>); 4] =
[(box 0, box 0), (box 0, box 0),

View File

@ -1,6 +1,5 @@
#![feature(box_syntax)]
#![feature(cell_update)]
#![feature(copied)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
#![feature(dec2flt)]

View File

@ -3,7 +3,6 @@ use core::num::bignum::tests::Big8x3 as Big;
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_from_u64_overflow() {
Big::from_u64(0x1000000);
}
@ -20,14 +19,12 @@ fn test_add() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_add_overflow_1() {
Big::from_small(1).add(&Big::from_u64(0xffffff));
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_add_overflow_2() {
Big::from_u64(0xffffff).add(&Big::from_small(1));
}
@ -45,7 +42,6 @@ fn test_add_small() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_add_small_overflow() {
Big::from_u64(0xffffff).add_small(1);
}
@ -61,14 +57,12 @@ fn test_sub() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_sub_underflow_1() {
Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_sub_underflow_2() {
Big::from_small(0).sub(&Big::from_u64(0x123456));
}
@ -82,7 +76,6 @@ fn test_mul_small() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_small_overflow() {
Big::from_u64(0x800000).mul_small(2);
}
@ -101,14 +94,12 @@ fn test_mul_pow2() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_pow2_overflow_1() {
Big::from_u64(0x1).mul_pow2(24);
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_pow2_overflow_2() {
Big::from_u64(0x123).mul_pow2(16);
}
@ -127,14 +118,12 @@ fn test_mul_pow5() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_pow5_overflow_1() {
Big::from_small(1).mul_pow5(12);
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_pow5_overflow_2() {
Big::from_small(230).mul_pow5(8);
}
@ -152,14 +141,12 @@ fn test_mul_digits() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_digits_overflow_1() {
Big::from_u64(0x800000).mul_digits(&[2]);
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_mul_digits_overflow_2() {
Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
}
@ -219,7 +206,6 @@ fn test_get_bit() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_get_bit_out_of_range() {
Big::from_small(42).get_bit(24);
}

View File

@ -12,7 +12,7 @@ mod tests {
fn test_overflows() {
assert!(MAX > 0);
assert!(MIN <= 0);
assert!(MIN + MAX + 1 == 0);
assert_eq!(MIN + MAX + 1, 0);
}
#[test]
@ -22,22 +22,22 @@ mod tests {
#[test]
fn test_rem_euclid() {
assert!((-1 as $T).rem_euclid(MIN) == MAX);
assert_eq!((-1 as $T).rem_euclid(MIN), MAX);
}
#[test]
pub fn test_abs() {
assert!((1 as $T).abs() == 1 as $T);
assert!((0 as $T).abs() == 0 as $T);
assert!((-1 as $T).abs() == 1 as $T);
assert_eq!((1 as $T).abs(), 1 as $T);
assert_eq!((0 as $T).abs(), 0 as $T);
assert_eq!((-1 as $T).abs(), 1 as $T);
}
#[test]
fn test_signum() {
assert!((1 as $T).signum() == 1 as $T);
assert!((0 as $T).signum() == 0 as $T);
assert!((-0 as $T).signum() == 0 as $T);
assert!((-1 as $T).signum() == -1 as $T);
assert_eq!((1 as $T).signum(), 1 as $T);
assert_eq!((0 as $T).signum(), 0 as $T);
assert_eq!((-0 as $T).signum(), 0 as $T);
assert_eq!((-1 as $T).signum(), -1 as $T);
}
#[test]
@ -58,12 +58,12 @@ mod tests {
#[test]
fn test_bitwise_operators() {
assert!(0b1110 as $T == (0b1100 as $T).bitor(0b1010 as $T));
assert!(0b1000 as $T == (0b1100 as $T).bitand(0b1010 as $T));
assert!(0b0110 as $T == (0b1100 as $T).bitxor(0b1010 as $T));
assert!(0b1110 as $T == (0b0111 as $T).shl(1));
assert!(0b0111 as $T == (0b1110 as $T).shr(1));
assert!(-(0b11 as $T) - (1 as $T) == (0b11 as $T).not());
assert_eq!(0b1110 as $T, (0b1100 as $T).bitor(0b1010 as $T));
assert_eq!(0b1000 as $T, (0b1100 as $T).bitand(0b1010 as $T));
assert_eq!(0b0110 as $T, (0b1100 as $T).bitxor(0b1010 as $T));
assert_eq!(0b1110 as $T, (0b0111 as $T).shl(1));
assert_eq!(0b0111 as $T, (0b1110 as $T).shr(1));
assert_eq!(-(0b11 as $T) - (1 as $T), (0b11 as $T).not());
}
const A: $T = 0b0101100;
@ -75,17 +75,17 @@ mod tests {
#[test]
fn test_count_ones() {
assert!(A.count_ones() == 3);
assert!(B.count_ones() == 2);
assert!(C.count_ones() == 5);
assert_eq!(A.count_ones(), 3);
assert_eq!(B.count_ones(), 2);
assert_eq!(C.count_ones(), 5);
}
#[test]
fn test_count_zeros() {
let bits = mem::size_of::<$T>() * 8;
assert!(A.count_zeros() == bits as u32 - 3);
assert!(B.count_zeros() == bits as u32 - 2);
assert!(C.count_zeros() == bits as u32 - 5);
assert_eq!(A.count_zeros(), bits as u32 - 3);
assert_eq!(B.count_zeros(), bits as u32 - 2);
assert_eq!(C.count_zeros(), bits as u32 - 5);
}
#[test]
@ -148,9 +148,9 @@ mod tests {
#[test]
fn test_signed_checked_div() {
assert!((10 as $T).checked_div(2) == Some(5));
assert!((5 as $T).checked_div(0) == None);
assert!(isize::MIN.checked_div(-1) == None);
assert_eq!((10 as $T).checked_div(2), Some(5));
assert_eq!((5 as $T).checked_div(0), None);
assert_eq!(isize::MIN.checked_div(-1), None);
}
#[test]

View File

@ -7,11 +7,11 @@ fn test_range() {
let r = Range { start: 2, end: 10 };
let mut count = 0;
for (i, ri) in r.enumerate() {
assert!(ri == i + 2);
assert_eq!(ri, i + 2);
assert!(ri >= 2 && ri < 10);
count += 1;
}
assert!(count == 8);
assert_eq!(count, 8);
}
#[test]
@ -19,11 +19,11 @@ fn test_range_from() {
let r = RangeFrom { start: 2 };
let mut count = 0;
for (i, ri) in r.take(10).enumerate() {
assert!(ri == i + 2);
assert_eq!(ri, i + 2);
assert!(ri >= 2 && ri < 12);
count += 1;
}
assert!(count == 10);
assert_eq!(count, 10);
}
#[test]

View File

@ -69,7 +69,6 @@ fn test_option_dance() {
}
#[test] #[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_option_too_much_dance() {
struct A;
let mut y = Some(A);
@ -130,7 +129,6 @@ fn test_unwrap() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_unwrap_panic1() {
let x: Option<isize> = None;
x.unwrap();
@ -138,7 +136,6 @@ fn test_unwrap_panic1() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn test_unwrap_panic2() {
let x: Option<String> = None;
x.unwrap();

View File

@ -117,7 +117,6 @@ fn test_unwrap_or_else() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
pub fn test_unwrap_or_else_panic() {
fn handler(msg: &'static str) -> isize {
if msg == "I got this." {
@ -139,7 +138,6 @@ pub fn test_expect_ok() {
}
#[test]
#[should_panic(expected="Got expected error: \"All good\"")]
#[cfg(not(miri))] // Miri does not support panics
pub fn test_expect_err() {
let err: Result<isize, &'static str> = Err("All good");
err.expect("Got expected error");
@ -153,7 +151,6 @@ pub fn test_expect_err_err() {
}
#[test]
#[should_panic(expected="Got expected ok: \"All good\"")]
#[cfg(not(miri))] // Miri does not support panics
pub fn test_expect_err_ok() {
let err: Result<&'static str, isize> = Ok("All good");
err.expect_err("Got expected ok");

View File

@ -782,7 +782,6 @@ mod slice_index {
// to be used in `should_panic`)
#[test]
#[should_panic(expected = "out of range")]
#[cfg(not(miri))] // Miri does not support panics
fn assert_range_eq_can_fail_by_panic() {
assert_range_eq!([0, 1, 2], 0..5, [0, 1, 2]);
}
@ -792,7 +791,6 @@ mod slice_index {
// to be used in `should_panic`)
#[test]
#[should_panic(expected = "==")]
#[cfg(not(miri))] // Miri does not support panics
fn assert_range_eq_can_fail_by_inequality() {
assert_range_eq!([0, 1, 2], 0..2, [0, 1, 2]);
}
@ -842,7 +840,6 @@ mod slice_index {
#[test]
#[should_panic(expected = $expect_msg)]
#[cfg(not(miri))] // Miri does not support panics
fn index_fail() {
let v = $data;
let v: &[_] = &v;
@ -851,7 +848,6 @@ mod slice_index {
#[test]
#[should_panic(expected = $expect_msg)]
#[cfg(not(miri))] // Miri does not support panics
fn index_mut_fail() {
let mut v = $data;
let v: &mut [_] = &mut v;
@ -1304,7 +1300,6 @@ fn test_copy_within() {
#[test]
#[should_panic(expected = "src is out of bounds")]
#[cfg(not(miri))] // Miri does not support panics
fn test_copy_within_panics_src_too_long() {
let mut bytes = *b"Hello, World!";
// The length is only 13, so 14 is out of bounds.
@ -1313,7 +1308,6 @@ fn test_copy_within_panics_src_too_long() {
#[test]
#[should_panic(expected = "dest is out of bounds")]
#[cfg(not(miri))] // Miri does not support panics
fn test_copy_within_panics_dest_too_long() {
let mut bytes = *b"Hello, World!";
// The length is only 13, so a slice of length 4 starting at index 10 is out of bounds.
@ -1321,7 +1315,6 @@ fn test_copy_within_panics_dest_too_long() {
}
#[test]
#[should_panic(expected = "src end is before src start")]
#[cfg(not(miri))] // Miri does not support panics
fn test_copy_within_panics_src_inverted() {
let mut bytes = *b"Hello, World!";
// 2 is greater than 1, so this range is invalid.

View File

@ -107,14 +107,12 @@ fn checked_sub() {
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn sub_bad1() {
let _ = Duration::new(0, 0) - Duration::new(0, 1);
}
#[test]
#[should_panic]
#[cfg(not(miri))] // Miri does not support panics
fn sub_bad2() {
let _ = Duration::new(0, 0) - Duration::new(1, 0);
}

View File

@ -21,7 +21,6 @@ const NANOS_PER_MILLI: u32 = 1_000_000;
const NANOS_PER_MICRO: u32 = 1_000;
const MILLIS_PER_SEC: u64 = 1_000;
const MICROS_PER_SEC: u64 = 1_000_000;
const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
@ -510,15 +509,34 @@ impl Duration {
/// use std::time::Duration;
///
/// let dur = Duration::new(2, 700_000_000);
/// assert_eq!(dur.as_float_secs(), 2.7);
/// assert_eq!(dur.as_secs_f64(), 2.7);
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub const fn as_float_secs(&self) -> f64 {
pub const fn as_secs_f64(&self) -> f64 {
(self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
}
/// Creates a new `Duration` from the specified number of seconds.
/// Returns the number of seconds contained by this `Duration` as `f32`.
///
/// The returned value does include the fractional (nanosecond) part of the duration.
///
/// # Examples
/// ```
/// #![feature(duration_float)]
/// use std::time::Duration;
///
/// let dur = Duration::new(2, 700_000_000);
/// assert_eq!(dur.as_secs_f32(), 2.7);
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub const fn as_secs_f32(&self) -> f32 {
(self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32)
}
/// Creates a new `Duration` from the specified number of seconds represented
/// as `f64`.
///
/// # Panics
/// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
@ -528,12 +546,14 @@ impl Duration {
/// #![feature(duration_float)]
/// use std::time::Duration;
///
/// let dur = Duration::from_float_secs(2.7);
/// let dur = Duration::from_secs_f64(2.7);
/// assert_eq!(dur, Duration::new(2, 700_000_000));
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn from_float_secs(secs: f64) -> Duration {
pub fn from_secs_f64(secs: f64) -> Duration {
const MAX_NANOS_F64: f64 =
((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
let nanos = secs * (NANOS_PER_SEC as f64);
if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration");
@ -551,6 +571,42 @@ impl Duration {
}
}
/// Creates a new `Duration` from the specified number of seconds represented
/// as `f32`.
///
/// # Panics
/// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
///
/// # Examples
/// ```
/// #![feature(duration_float)]
/// use std::time::Duration;
///
/// let dur = Duration::from_secs_f32(2.7);
/// assert_eq!(dur, Duration::new(2, 700_000_000));
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn from_secs_f32(secs: f32) -> Duration {
const MAX_NANOS_F32: f32 =
((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f32;
let nanos = secs * (NANOS_PER_SEC as f32);
if !nanos.is_finite() {
panic!("got non-finite value when converting float to duration");
}
if nanos >= MAX_NANOS_F32 {
panic!("overflow when converting float to duration");
}
if nanos < 0.0 {
panic!("underflow when converting float to duration");
}
let nanos = nanos as u128;
Duration {
secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
}
}
/// Multiplies `Duration` by `f64`.
///
/// # Panics
@ -568,7 +624,29 @@ impl Duration {
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn mul_f64(self, rhs: f64) -> Duration {
Duration::from_float_secs(rhs * self.as_float_secs())
Duration::from_secs_f64(rhs * self.as_secs_f64())
}
/// Multiplies `Duration` by `f32`.
///
/// # Panics
/// This method will panic if result is not finite, negative or overflows `Duration`.
///
/// # Examples
/// ```
/// #![feature(duration_float)]
/// use std::time::Duration;
///
/// let dur = Duration::new(2, 700_000_000);
/// // note that due to rounding errors result is slightly different
/// // from 8.478 and 847800.0
/// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_640));
/// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847799, 969_120_256));
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn mul_f32(self, rhs: f32) -> Duration {
Duration::from_secs_f32(rhs * self.as_secs_f32())
}
/// Divide `Duration` by `f64`.
@ -589,7 +667,30 @@ impl Duration {
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn div_f64(self, rhs: f64) -> Duration {
Duration::from_float_secs(self.as_float_secs() / rhs)
Duration::from_secs_f64(self.as_secs_f64() / rhs)
}
/// Divide `Duration` by `f32`.
///
/// # Panics
/// This method will panic if result is not finite, negative or overflows `Duration`.
///
/// # Examples
/// ```
/// #![feature(duration_float)]
/// use std::time::Duration;
///
/// let dur = Duration::new(2, 700_000_000);
/// // note that due to rounding errors result is slightly
/// // different from 0.859_872_611
/// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_576));
/// // note that truncation is used, not rounding
/// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_598));
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn div_f32(self, rhs: f32) -> Duration {
Duration::from_secs_f32(self.as_secs_f32() / rhs)
}
/// Divide `Duration` by `Duration` and return `f64`.
@ -601,12 +702,29 @@ impl Duration {
///
/// let dur1 = Duration::new(2, 700_000_000);
/// let dur2 = Duration::new(5, 400_000_000);
/// assert_eq!(dur1.div_duration(dur2), 0.5);
/// assert_eq!(dur1.div_duration_f64(dur2), 0.5);
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn div_duration(self, rhs: Duration) -> f64 {
self.as_float_secs() / rhs.as_float_secs()
pub fn div_duration_f64(self, rhs: Duration) -> f64 {
self.as_secs_f64() / rhs.as_secs_f64()
}
/// Divide `Duration` by `Duration` and return `f32`.
///
/// # Examples
/// ```
/// #![feature(duration_float)]
/// use std::time::Duration;
///
/// let dur1 = Duration::new(2, 700_000_000);
/// let dur2 = Duration::new(5, 400_000_000);
/// assert_eq!(dur1.div_duration_f32(dur2), 0.5);
/// ```
#[unstable(feature = "duration_float", issue = "54361")]
#[inline]
pub fn div_duration_f32(self, rhs: Duration) -> f32 {
self.as_secs_f32() / rhs.as_secs_f32()
}
}

View File

@ -541,7 +541,8 @@ impl<'hir> Map<'hir> {
pub fn ty_param_owner(&self, id: HirId) -> HirId {
match self.get_by_hir_id(id) {
Node::Item(&Item { node: ItemKind::Trait(..), .. }) => id,
Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => id,
Node::GenericParam(_) => self.get_parent_node_by_hir_id(id),
_ => bug!("ty_param_owner: {} not a type parameter", self.hir_to_string(id))
}
@ -549,7 +550,8 @@ impl<'hir> Map<'hir> {
pub fn ty_param_name(&self, id: HirId) -> Name {
match self.get_by_hir_id(id) {
Node::Item(&Item { node: ItemKind::Trait(..), .. }) => keywords::SelfUpper.name(),
Node::Item(&Item { node: ItemKind::Trait(..), .. }) |
Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => keywords::SelfUpper.name(),
Node::GenericParam(param) => param.name.ident().name,
_ => bug!("ty_param_name: {} not a type parameter", self.hir_to_string(id)),
}

View File

@ -2299,6 +2299,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let span = lifetime_refs[0].span;
let mut late_depth = 0;
let mut scope = self.scope;
let mut lifetime_names = FxHashSet::default();
let error = loop {
match *scope {
// Do not assign any resolution, it will be inferred.
@ -2306,12 +2307,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
Scope::Root => break None,
Scope::Binder { s, .. } => {
Scope::Binder { s, ref lifetimes, .. } => {
// collect named lifetimes for suggestions
for name in lifetimes.keys() {
if let hir::ParamName::Plain(name) = name {
lifetime_names.insert(*name);
}
}
late_depth += 1;
scope = s;
}
Scope::Elision { ref elide, .. } => {
Scope::Elision { ref elide, ref s, .. } => {
let lifetime = match *elide {
Elide::FreshLateAnon(ref counter) => {
for lifetime_ref in lifetime_refs {
@ -2321,7 +2328,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
return;
}
Elide::Exact(l) => l.shifted(late_depth),
Elide::Error(ref e) => break Some(e),
Elide::Error(ref e) => {
if let Scope::Binder { ref lifetimes, .. } = s {
// collect named lifetimes for suggestions
for name in lifetimes.keys() {
if let hir::ParamName::Plain(name) = name {
lifetime_names.insert(*name);
}
}
}
break Some(e);
}
};
for lifetime_ref in lifetime_refs {
self.insert_lifetime(lifetime_ref, lifetime);
@ -2344,7 +2361,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
if add_label {
add_missing_lifetime_specifiers_label(&mut err, span, lifetime_refs.len());
add_missing_lifetime_specifiers_label(
&mut err,
span,
lifetime_refs.len(),
&lifetime_names,
self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()),
);
}
err.emit();
@ -2885,10 +2908,23 @@ fn add_missing_lifetime_specifiers_label(
err: &mut DiagnosticBuilder<'_>,
span: Span,
count: usize,
lifetime_names: &FxHashSet<ast::Ident>,
snippet: Option<&str>,
) {
if count > 1 {
err.span_label(span, format!("expected {} lifetime parameters", count));
} else if let (1, Some(name), Some("&")) = (
lifetime_names.len(),
lifetime_names.iter().next(),
snippet,
) {
err.span_suggestion(
span,
"consider using the named lifetime",
format!("&{} ", name),
Applicability::MaybeIncorrect,
);
} else {
err.span_label(span, "expected lifetime parameter");
};
}
}

View File

@ -800,6 +800,7 @@ macro_rules! options {
pub const parse_opt_pathbuf: Option<&str> = Some("a path");
pub const parse_list: Option<&str> = Some("a space-separated list of strings");
pub const parse_opt_list: Option<&str> = Some("a space-separated list of strings");
pub const parse_opt_comma_list: Option<&str> = Some("a comma-separated list of strings");
pub const parse_uint: Option<&str> = Some("a number");
pub const parse_passes: Option<&str> =
Some("a space-separated list of passes, or `all`");
@ -926,6 +927,18 @@ macro_rules! options {
}
}
fn parse_opt_comma_list(slot: &mut Option<Vec<String>>, v: Option<&str>)
-> bool {
match v {
Some(s) => {
let v = s.split(',').map(|s| s.to_string()).collect();
*slot = Some(v);
true
},
None => false,
}
}
fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool {
match v.and_then(|s| s.parse().ok()) {
Some(i) => { *slot = i; true },
@ -1427,6 +1440,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
"control the operation of the MergeFunctions LLVM pass, taking
the same values as the target option of the same name"),
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
"only allow the listed language features to be enabled in code (space separated)"),
}
pub fn default_lib_output() -> CrateType {
@ -3273,6 +3288,10 @@ mod tests {
opts = reference.clone();
opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.allow_features = Some(vec![String::from("lang_items")]);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
}
#[test]

View File

@ -1911,7 +1911,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
pub fn is_machine(&self) -> bool {
match self.sty {
Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => false,
Int(..) | Uint(..) | Float(..) => true,
_ => false,
}

View File

@ -15,7 +15,6 @@
#![allow(unused_attributes)]
#![feature(libc)]
#![feature(nll)]
#![feature(range_contains)]
#![feature(rustc_diagnostic_macros)]
#![feature(optin_builtin_traits)]
#![feature(concat_idents)]

View File

@ -382,20 +382,19 @@ impl<'a> Linker for GccLinker<'a> {
if self.sess.target.target.options.is_like_osx {
// Write a plain, newline-separated list of symbols
let res = (|| -> io::Result<()> {
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
for sym in self.info.exports[&crate_type].iter() {
debug!(" _{}", sym);
writeln!(f, "_{}", sym)?;
}
Ok(())
})();
};
if let Err(e) = res {
self.sess.fatal(&format!("failed to write lib.def file: {}", e));
}
} else {
// Write an LD version script
let res = (|| -> io::Result<()> {
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
writeln!(f, "{{\n global:")?;
for sym in self.info.exports[&crate_type].iter() {
@ -403,8 +402,7 @@ impl<'a> Linker for GccLinker<'a> {
writeln!(f, " {};", sym)?;
}
writeln!(f, "\n local:\n *;\n}};")?;
Ok(())
})();
};
if let Err(e) = res {
self.sess.fatal(&format!("failed to write version script: {}", e));
}
@ -644,7 +642,7 @@ impl<'a> Linker for MsvcLinker<'a> {
tmpdir: &Path,
crate_type: CrateType) {
let path = tmpdir.join("lib.def");
let res = (|| -> io::Result<()> {
let res: io::Result<()> = try {
let mut f = BufWriter::new(File::create(&path)?);
// Start off with the standard module name header and then go
@ -655,8 +653,7 @@ impl<'a> Linker for MsvcLinker<'a> {
debug!(" _{}", symbol);
writeln!(f, " {}", symbol)?;
}
Ok(())
})();
};
if let Err(e) = res {
self.sess.fatal(&format!("failed to write lib.def file: {}", e));
}

View File

@ -7,6 +7,7 @@
#![feature(libc)]
#![feature(rustc_diagnostic_macros)]
#![feature(stmt_expr_attributes)]
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![allow(unused_attributes)]

View File

@ -2,7 +2,6 @@
#![feature(custom_attribute)]
#![allow(unused_attributes)]
#![feature(range_contains)]
#![cfg_attr(unix, feature(libc))]
#![feature(nll)]
#![feature(optin_builtin_traits)]

View File

@ -243,6 +243,7 @@ pub fn register_plugins<'a>(
krate,
&sess.parse_sess,
sess.edition(),
&sess.opts.debugging_opts.allow_features,
);
// these need to be set "early" so that expansion sees `quote` if enabled.
sess.init_features(features);

View File

@ -114,14 +114,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
(Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0)
}
ty::Int(ity) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
let max = truncate(u128::max_value(), size);
let bias = 1u128 << (size.bits() - 1);
(Some((0, max, size)), bias)
}
ty::Uint(uty) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
let max = truncate(u128::max_value(), size);
(Some((0, max, size)), 0)

View File

@ -65,12 +65,12 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
fn mplace_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
mplace: MPlaceTy<'tcx>,
) -> EvalResult<'tcx, ty::Const<'tcx>> {
) -> ty::Const<'tcx> {
let MemPlace { ptr, align, meta } = *mplace;
// extract alloc-offset pair
assert!(meta.is_none());
let ptr = ptr.to_ptr()?;
let alloc = ecx.memory.get(ptr.alloc_id)?;
let ptr = ptr.to_ptr().unwrap();
let alloc = ecx.memory.get(ptr.alloc_id).unwrap();
assert!(alloc.align >= align);
assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= mplace.layout.size.bytes());
let mut alloc = alloc.clone();
@ -79,16 +79,16 @@ fn mplace_to_const<'tcx>(
// interned this? I thought that is the entire point of that `FinishStatic` stuff?
let alloc = ecx.tcx.intern_const_alloc(alloc);
let val = ConstValue::ByRef(ptr, alloc);
Ok(ty::Const { val, ty: mplace.layout.ty })
ty::Const { val, ty: mplace.layout.ty }
}
fn op_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
op: OpTy<'tcx>,
) -> EvalResult<'tcx, ty::Const<'tcx>> {
// We do not normalize just any data. Only scalar layout and slices.
) -> ty::Const<'tcx> {
// We do not normalize just any data. Only non-union scalars and slices.
let normalize = match op.layout.abi {
layout::Abi::Scalar(..) => true,
layout::Abi::Scalar(..) => op.layout.ty.ty_adt_def().map_or(true, |adt| !adt.is_union()),
layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(),
_ => false,
};
@ -100,11 +100,11 @@ fn op_to_const<'tcx>(
let val = match normalized_op {
Ok(mplace) => return mplace_to_const(ecx, mplace),
Err(Immediate::Scalar(x)) =>
ConstValue::Scalar(x.not_undef()?),
ConstValue::Scalar(x.not_undef().unwrap()),
Err(Immediate::ScalarPair(a, b)) =>
ConstValue::Slice(a.not_undef()?, b.to_usize(ecx)?),
ConstValue::Slice(a.not_undef().unwrap(), b.to_usize(ecx).unwrap()),
};
Ok(ty::Const { val, ty: op.layout.ty })
ty::Const { val, ty: op.layout.ty }
}
fn eval_body_and_ecx<'a, 'mir, 'tcx>(
@ -488,7 +488,7 @@ pub fn const_field<'a, 'tcx>(
let field = ecx.operand_field(down, field.index() as u64).unwrap();
// and finally move back to the const world, always normalizing because
// this is not called for statics.
op_to_const(&ecx, field).unwrap()
op_to_const(&ecx, field)
}
// this function uses `unwrap` copiously, because an already validated constant must have valid
@ -534,9 +534,9 @@ fn validate_and_turn_into_const<'a, 'tcx>(
// Now that we validated, turn this into a proper constant.
let def_id = cid.instance.def.def_id();
if tcx.is_static(def_id).is_some() || cid.promoted.is_some() {
mplace_to_const(&ecx, mplace)
Ok(mplace_to_const(&ecx, mplace))
} else {
op_to_const(&ecx, mplace.into())
Ok(op_to_const(&ecx, mplace.into()))
}
})();

View File

@ -172,7 +172,7 @@ use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
use rustc::mir::Field;
use rustc::mir::interpret::{ConstValue, Scalar};
use rustc::mir::interpret::{ConstValue, Scalar, truncate};
use rustc::util::common::ErrorReported;
use syntax::attr::{SignedInt, UnsignedInt};
@ -678,16 +678,14 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
]
}
ty::Int(ity) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
let min = 1u128 << (bits - 1);
let max = (1u128 << (bits - 1)) - 1;
let max = min - 1;
vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)]
}
ty::Uint(uty) => {
// FIXME(49937): refactor these bit manipulations into interpret.
let bits = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size().bits() as u128;
let max = !0u128 >> (128 - bits);
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
let max = truncate(u128::max_value(), size);
vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included)]
}
_ => {

View File

@ -14,7 +14,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
#![feature(const_fn)]
#![feature(decl_macro)]
#![feature(exhaustive_patterns)]
#![feature(range_contains)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_attrs)]
#![feature(never_type)]

View File

@ -1,4 +1,5 @@
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::hir::def::CtorKind;
use rustc::mir::*;
use rustc::mir::visit::Visitor;
use rustc::ty::{self, TyCtxt};
@ -596,7 +597,8 @@ fn write_mir_sig(
trace!("write_mir_sig: {:?}", src.instance);
let descr = tcx.describe_def(src.def_id());
let is_function = match descr {
Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::StructCtor(..)) => true,
Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Variant(..)) |
Some(Def::StructCtor(_, CtorKind::Fn)) => true,
_ => tcx.is_closure(src.def_id()),
};
match (descr, src.promoted) {

View File

@ -0,0 +1,23 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
Ok(Target {
llvm_target: "mipsisa32r6-unknown-linux-gnu".to_string(),
target_endian: "big".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
arch: "mips".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32r6".to_string(),
features: "+mips32r6".to_string(),
max_atomic_width: Some(32),
..super::linux_base::opts()
},
})
}

View File

@ -0,0 +1,24 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
Ok(Target {
llvm_target: "mipsisa32r6el-unknown-linux-gnu".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
arch: "mips".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
cpu: "mips32r6".to_string(),
features: "+mips32r6".to_string(),
max_atomic_width: Some(32),
..super::linux_base::opts()
},
})
}

View File

@ -0,0 +1,24 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
Ok(Target {
llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".to_string(),
target_endian: "big".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-n32:64-S128".to_string(),
arch: "mips64".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// NOTE(mips64r6) matches C toolchain
cpu: "mips64r6".to_string(),
features: "+mips64r6".to_string(),
max_atomic_width: Some(64),
..super::linux_base::opts()
},
})
}

View File

@ -0,0 +1,24 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
Ok(Target {
llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".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-n32:64-S128".to_string(),
arch: "mips64".to_string(),
target_os: "linux".to_string(),
target_env: "gnu".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: TargetOptions {
// NOTE(mips64r6) matches C toolchain
cpu: "mips64r6".to_string(),
features: "+mips64r6".to_string(),
max_atomic_width: Some(64),
..super::linux_base::opts()
},
})
}

View File

@ -335,6 +335,10 @@ supported_targets! {
("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
("mipsisa32r6-unknown-linux-gnu", mipsisa32r6_unknown_linux_gnu),
("mipsisa32r6el-unknown-linux-gnu", mipsisa32r6el_unknown_linux_gnu),
("mipsisa64r6-unknown-linux-gnuabi64", mipsisa64r6_unknown_linux_gnuabi64),
("mipsisa64r6el-unknown-linux-gnuabi64", mipsisa64r6el_unknown_linux_gnuabi64),
("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),

View File

@ -59,7 +59,7 @@ pub fn opts() -> TargetOptions {
singlethread: true,
emit_debug_gdb_scripts: false,
linker: Some("lld-link".to_string()),
linker: Some("rust-lld".to_string()),
lld_flavor: LldFlavor::Link,
pre_link_args,

View File

@ -5288,6 +5288,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
}
// Rewrite `SelfCtor` to `StructCtor`
pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) {
let tcx = self.tcx;
if let Def::SelfCtor(impl_def_id) = def {
let ty = self.impl_self_ty(span, impl_def_id).ty;
let adt_def = ty.ty_adt_def();
match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
let def = Def::StructCtor(variant.did, variant.ctor_kind);
(def, variant.did, tcx.type_of(variant.did))
}
_ => {
let mut err = tcx.sess.struct_span_err(span,
"the `Self` constructor can only be used with tuple or unit structs");
if let Some(adt_def) = adt_def {
match adt_def.adt_kind() {
AdtKind::Enum => {
err.help("did you mean to use one of the enum's variants?");
},
AdtKind::Struct |
AdtKind::Union => {
err.span_suggestion(
span,
"use curly brackets",
String::from("Self { /* fields */ }"),
Applicability::HasPlaceholders,
);
}
}
}
err.emit();
(def, impl_def_id, tcx.types.err)
}
}
} else {
let def_id = def.def_id();
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = tcx.type_of(def_id);
(def, def_id, ty)
}
}
// Instantiates the given path, which must refer to an item with the given
// number of type parameters and type.
pub fn instantiate_value_path(&self,
@ -5307,6 +5354,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let tcx = self.tcx;
match def {
Def::Local(nid) | Def::Upvar(nid, ..) => {
let hid = self.tcx.hir().node_to_hir_id(nid);
let ty = self.local_ty(span, hid).decl_ty;
let ty = self.normalize_associated_types_in(span, &ty);
self.write_ty(hir_id, ty);
return (ty, def);
}
_ => {}
}
let (def, def_id, ty) = self.rewrite_self_ctor(def, span);
let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def);
let mut user_self_ty = None;
@ -5368,17 +5427,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
user_self_ty = None;
}
match def {
Def::Local(nid) | Def::Upvar(nid, ..) => {
let hid = self.tcx.hir().node_to_hir_id(nid);
let ty = self.local_ty(span, hid).decl_ty;
let ty = self.normalize_associated_types_in(span, &ty);
self.write_ty(hir_id, ty);
return (ty, def);
}
_ => {}
}
// Now we have to compare the types that the user *actually*
// provided against the types that were *expected*. If the user
// did not provide any types, then we want to substitute inference
@ -5411,53 +5459,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
tcx.generics_of(*def_id).has_self
}).unwrap_or(false);
let mut new_def = def;
let (def_id, ty) = match def {
Def::SelfCtor(impl_def_id) => {
let ty = self.impl_self_ty(span, impl_def_id).ty;
let adt_def = ty.ty_adt_def();
match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
(variant.did, tcx.type_of(variant.did))
}
_ => {
let mut err = tcx.sess.struct_span_err(span,
"the `Self` constructor can only be used with tuple or unit structs");
if let Some(adt_def) = adt_def {
match adt_def.adt_kind() {
AdtKind::Enum => {
err.help("did you mean to use one of the enum's variants?");
},
AdtKind::Struct |
AdtKind::Union => {
err.span_suggestion(
span,
"use curly brackets",
String::from("Self { /* fields */ }"),
Applicability::HasPlaceholders,
);
}
}
}
err.emit();
(impl_def_id, tcx.types.err)
}
}
}
_ => {
let def_id = def.def_id();
// The things we are substituting into the type should not contain
// escaping late-bound regions, and nor should the base type scheme.
let ty = tcx.type_of(def_id);
(def_id, ty)
}
};
let substs = AstConv::create_substs_for_generic_args(
tcx,
def_id,
@ -5573,7 +5574,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty_substituted);
self.write_substs(hir_id, substs);
(ty_substituted, new_def)
(ty_substituted, def)
}
fn check_rustc_args_require_const(&self,

View File

@ -1117,11 +1117,7 @@ themePicker.onblur = handleThemeButtonsBlur;
// with rustdoc running in parallel.
all_indexes.sort();
let mut w = try_err!(File::create(&dst), &dst);
if options.enable_minification {
try_err!(writeln!(&mut w, "var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={{}};"), &dst);
} else {
try_err!(writeln!(&mut w, "var searchIndex={{}};"), &dst);
}
try_err!(writeln!(&mut w, "var N=null,E=\"\",T=\"t\",U=\"u\",searchIndex={{}};"), &dst);
try_err!(write_minify_replacer(&mut w,
&format!("{}\n{}", variables.join(""), all_indexes.join("\n")),
options.enable_minification),

View File

@ -2077,16 +2077,22 @@ if (!DOMTokenList.prototype.remove) {
}
var toggle = createSimpleToggle(false);
var hideMethodDocs = getCurrentValue("rustdoc-method-docs") !== "false";
var pageId = getPageId();
var func = function(e) {
var next = e.nextElementSibling;
if (!next) {
return;
}
if (hasClass(next, "docblock") ||
(hasClass(next, "stability") &&
hasClass(next.nextElementSibling, "docblock"))) {
insertAfter(toggle.cloneNode(true), e.childNodes[e.childNodes.length - 1]);
if (hasClass(next, "docblock") === true ||
(hasClass(next, "stability") === true &&
hasClass(next.nextElementSibling, "docblock") === true)) {
var newToggle = toggle.cloneNode(true);
insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
if (hideMethodDocs === true && hasClass(e, "method") === true) {
collapseDocs(newToggle, "hide", pageId);
}
}
};
@ -2107,17 +2113,16 @@ if (!DOMTokenList.prototype.remove) {
onEachLazy(document.getElementsByClassName("associatedconstant"), func);
onEachLazy(document.getElementsByClassName("impl"), funcImpl);
var impl_call = function() {};
if (getCurrentValue("rustdoc-method-docs") !== "false") {
if (hideMethodDocs === true) {
impl_call = function(e, newToggle, pageId) {
if (e.id.match(/^impl(?:-\d+)?$/) === null) {
// Automatically minimize all non-inherent impls
if (hasClass(e, "impl")) {
if (hasClass(e, "impl") === true) {
collapseDocs(newToggle, "hide", pageId);
}
}
};
}
var pageId = getPageId();
var newToggle = document.createElement("a");
newToggle.href = "javascript:void(0)";
newToggle.className = "collapse-toggle hidden-default collapsed";
@ -2163,7 +2168,7 @@ if (!DOMTokenList.prototype.remove) {
var inner_toggle = newToggle.cloneNode(true);
inner_toggle.onclick = toggleClicked;
e.insertBefore(inner_toggle, e.firstChild);
impl_call(e, inner_toggle, pageId);
impl_call(e.previousSibling, inner_toggle, pageId);
}
});
@ -2265,30 +2270,6 @@ if (!DOMTokenList.prototype.remove) {
onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper);
onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper);
// In the search display, allows to switch between tabs.
function printTab(nb) {
if (nb === 0 || nb === 1 || nb === 2) {
currentTab = nb;
}
var nb_copy = nb;
onEachLazy(document.getElementById("titles").childNodes, function(elem) {
if (nb_copy === 0) {
addClass(elem, "selected");
} else {
removeClass(elem, "selected");
}
nb_copy -= 1;
});
onEachLazy(document.getElementById("results").childNodes, function(elem) {
if (nb === 0) {
elem.style.display = "";
} else {
elem.style.display = "none";
}
nb -= 1;
});
}
function createToggleWrapper(tog) {
var span = document.createElement("span");
span.className = "toggle-label";
@ -2374,6 +2355,30 @@ if (!DOMTokenList.prototype.remove) {
};
});
// In the search display, allows to switch between tabs.
function printTab(nb) {
if (nb === 0 || nb === 1 || nb === 2) {
currentTab = nb;
}
var nb_copy = nb;
onEachLazy(document.getElementById("titles").childNodes, function(elem) {
if (nb_copy === 0) {
addClass(elem, "selected");
} else {
removeClass(elem, "selected");
}
nb_copy -= 1;
});
onEachLazy(document.getElementById("results").childNodes, function(elem) {
if (nb === 0) {
elem.style.display = "";
} else {
elem.style.display = "none";
}
nb -= 1;
});
}
function putBackSearch(search_input) {
if (search_input.value !== "") {
addClass(main, "hidden");

View File

@ -288,6 +288,12 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
if ori_link.contains('/') {
continue;
}
// [] is mostly likely not supposed to be a link
if ori_link.is_empty() {
continue;
}
let link = ori_link.replace("`", "");
let (def, fragment) = {
let mut kind = PathKind::Unknown;

View File

@ -19,7 +19,7 @@ use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucke
use super::table::BucketState::{Empty, Full};
use super::table::Fallibility::{Fallible, Infallible};
const MIN_NONZERO_RAW_CAPACITY: usize = 32; // must be a power of two
const MIN_NONZERO_RAW_CAPACITY: usize = 32; // must be a power of two
/// The default behavior of HashMap implements a maximum load factor of 90.9%.
#[derive(Clone)]

View File

@ -8,7 +8,7 @@ use super::Recover;
use super::map::{self, HashMap, Keys, RandomState};
// Future Optimization (FIXME!)
// =============================
// ============================
//
// Iteration over zero sized values is a noop. There is no need
// for `bucket.val` in the case of HashSet. I suppose we would need HKT

View File

@ -211,7 +211,7 @@ pub struct DirBuilder {
recursive: bool,
}
/// How large a buffer to pre-allocate before reading the entire file.
/// Indicates how large a buffer to pre-allocate before reading the entire file.
fn initial_buffer_size(file: &File) -> usize {
// Allocate one extra byte so the buffer doesn't need to grow before the
// final `read` call at the end of the file. Don't worry about `usize`
@ -1581,7 +1581,8 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
/// `O_CLOEXEC` is set for returned file descriptors.
/// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
/// NTFS streams are copied but only the size of the main stream is returned by
/// this function.
/// this function. On MacOS, this function corresponds to `copyfile` with
/// `COPYFILE_ALL`.
/// Note that, this [may change in the future][changes].
///
/// [changes]: ../io/index.html#platform-specific-behavior
@ -2836,6 +2837,26 @@ mod tests {
assert_eq!(check!(out_path.metadata()).len(), copied_len);
}
#[test]
fn copy_file_follows_dst_symlink() {
let tmp = tmpdir();
if !got_symlink_permission(&tmp) { return };
let in_path = tmp.join("in.txt");
let out_path = tmp.join("out.txt");
let out_path_symlink = tmp.join("out_symlink.txt");
check!(fs::write(&in_path, "foo"));
check!(fs::write(&out_path, "bar"));
check!(symlink_file(&out_path, &out_path_symlink));
check!(fs::copy(&in_path, &out_path_symlink));
assert!(check!(out_path_symlink.symlink_metadata()).file_type().is_symlink());
assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec());
assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec());
}
#[test]
fn symlinks_work() {
let tmpdir = tmpdir();

View File

@ -390,6 +390,28 @@ fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
ret
}
pub(crate) fn default_read_vectored<F>(read: F, bufs: &mut [IoVecMut<'_>]) -> Result<usize>
where
F: FnOnce(&mut [u8]) -> Result<usize>
{
let buf = bufs
.iter_mut()
.find(|b| !b.is_empty())
.map_or(&mut [][..], |b| &mut **b);
read(buf)
}
pub(crate) fn default_write_vectored<F>(write: F, bufs: &[IoVec<'_>]) -> Result<usize>
where
F: FnOnce(&[u8]) -> Result<usize>
{
let buf = bufs
.iter()
.find(|b| !b.is_empty())
.map_or(&[][..], |b| &**b);
write(buf)
}
/// The `Read` trait allows for reading bytes from a source.
///
/// Implementors of the `Read` trait are called 'readers'.
@ -528,14 +550,11 @@ pub trait Read {
/// written to possibly being only partially filled. This method must behave
/// as a single call to `read` with the buffers concatenated would.
///
/// The default implementation simply passes the first nonempty buffer to
/// `read`.
/// The default implementation calls `read` with either the first nonempty
/// buffer provided, or an empty one if none exists.
#[unstable(feature = "iovec", issue = "58452")]
fn read_vectored(&mut self, bufs: &mut [IoVecMut<'_>]) -> Result<usize> {
match bufs.iter_mut().find(|b| !b.is_empty()) {
Some(buf) => self.read(buf),
None => Ok(0),
}
default_read_vectored(|b| self.read(b), bufs)
}
/// Determines if this `Read`er can work with buffers of uninitialized
@ -1107,14 +1126,11 @@ pub trait Write {
/// read from possibly being only partially consumed. This method must
/// behave as a call to `write` with the buffers concatenated would.
///
/// The default implementation simply passes the first nonempty buffer to
/// `write`.
/// The default implementation calls `write` with either the first nonempty
/// buffer provided, or an empty one if none exists.
#[unstable(feature = "iovec", issue = "58452")]
fn write_vectored(&mut self, bufs: &[IoVec<'_>]) -> Result<usize> {
match bufs.iter().find(|b| !b.is_empty()) {
Some(buf) => self.write(buf),
None => Ok(0),
}
default_write_vectored(|b| self.write(b), bufs)
}
/// Flush this output stream, ensuring that all intermediately buffered

View File

@ -221,7 +221,7 @@
#![cfg_attr(test, feature(print_internals, set_stdio, test, update_panic_count))]
#![cfg_attr(all(target_vendor = "fortanix", target_env = "sgx"),
feature(global_asm, range_contains, slice_index_methods,
feature(global_asm, slice_index_methods,
decl_macro, coerce_unsized, sgx_platform, ptr_wrapping_offset_from))]
// std is implemented with unstable features, many of which are internal

View File

@ -43,3 +43,8 @@ pub mod mem {
}
pub use crate::sys::ext::{io, arch, ffi};
/// Functions for querying thread-related information.
pub mod thread {
pub use crate::sys::abi::thread::current;
}

View File

@ -8,7 +8,7 @@
//!
//! The [`Command`] struct is used to configure and spawn processes:
//!
//! ```
//! ```no_run
//! use std::process::Command;
//!
//! let output = Command::new("echo")

View File

@ -190,7 +190,7 @@ impl Condvar {
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
/// while !*started {
/// started = cvar.wait(started).unwrap();
/// }
@ -254,7 +254,7 @@ impl Condvar {
///
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// // As long as the value inside the `Mutex` is false, we wait.
/// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
/// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap();
/// ```
#[unstable(feature = "wait_until", issue = "47960")]
@ -311,7 +311,7 @@ impl Condvar {
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
/// loop {
/// let result = cvar.wait_timeout_ms(started, 10).unwrap();
/// // 10 milliseconds have passed, or maybe the value changed!
@ -384,7 +384,7 @@ impl Condvar {
/// // wait for the thread to start up
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // as long as the value inside the `Mutex` is false, we wait
/// // as long as the value inside the `Mutex<bool>` is `false`, we wait
/// loop {
/// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
/// // 10 milliseconds have passed, or maybe the value changed!
@ -518,7 +518,7 @@ impl Condvar {
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
/// while !*started {
/// started = cvar.wait(started).unwrap();
/// }
@ -558,7 +558,7 @@ impl Condvar {
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// // As long as the value inside the `Mutex<bool>` is `false`, we wait.
/// while !*started {
/// started = cvar.wait(started).unwrap();
/// }

View File

@ -35,10 +35,7 @@ impl TcpStream {
}
pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
match bufs.iter_mut().find(|b| !b.is_empty()) {
Some(buf) => self.read(buf),
None => Ok(0),
}
io::default_read_vectored(|b| self.read(b), bufs)
}
pub fn write(&self, buf: &[u8]) -> Result<usize> {
@ -46,10 +43,7 @@ impl TcpStream {
}
pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
match bufs.iter().find(|b| !b.is_empty()) {
Some(buf) => self.write(buf),
None => Ok(0),
}
io::default_write_vectored(|b| self.write(b), bufs)
}
pub fn take_error(&self) -> Result<Option<Error>> {

View File

@ -4,6 +4,7 @@ use fortanix_sgx_abi::Tcs;
/// all currently running threads in the enclave, and it is guaranteed to be
/// constant for the lifetime of the thread. More specifically for SGX, there
/// is a one-to-one correspondence of the ID to the address of the TCS.
#[unstable(feature = "sgx_platform", issue = "56975")]
pub fn current() -> Tcs {
extern "C" { fn get_tcs_addr() -> Tcs; }
unsafe { get_tcs_addr() }

View File

@ -103,24 +103,16 @@ impl TcpStream {
self.inner.inner.read(buf)
}
pub fn read_vectored(&self, buf: &mut [IoVecMut<'_>]) -> io::Result<usize> {
let buf = match buf.get_mut(0) {
Some(buf) => buf,
None => return Ok(0),
};
self.read(buf)
pub fn read_vectored(&self, bufs: &mut [IoVecMut<'_>]) -> io::Result<usize> {
io::default_read_vectored(|b| self.read(b), bufs)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.inner.write(buf)
}
pub fn write_vectored(&self, buf: &[IoVec<'_>]) -> io::Result<usize> {
let buf = match buf.get(0) {
Some(buf) => buf,
None => return Ok(0),
};
self.write(buf)
pub fn write_vectored(&self, bufs: &[IoVec<'_>]) -> io::Result<usize> {
io::default_write_vectored(|b| self.write(b), bufs)
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {

View File

@ -827,7 +827,10 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
Ok(PathBuf::from(OsString::from_vec(buf)))
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
#[cfg(not(any(target_os = "linux",
target_os = "android",
target_os = "macos",
target_os = "ios")))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
use crate::fs::File;
if !from.is_file() {
@ -937,3 +940,85 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
writer.set_permissions(perm)?;
Ok(written)
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
const COPYFILE_ACL: u32 = 1 << 0;
const COPYFILE_STAT: u32 = 1 << 1;
const COPYFILE_XATTR: u32 = 1 << 2;
const COPYFILE_DATA: u32 = 1 << 3;
const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL;
const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR;
const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA;
const COPYFILE_STATE_COPIED: u32 = 8;
#[allow(non_camel_case_types)]
type copyfile_state_t = *mut libc::c_void;
#[allow(non_camel_case_types)]
type copyfile_flags_t = u32;
extern "C" {
fn copyfile(
from: *const libc::c_char,
to: *const libc::c_char,
state: copyfile_state_t,
flags: copyfile_flags_t,
) -> libc::c_int;
fn copyfile_state_alloc() -> copyfile_state_t;
fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int;
fn copyfile_state_get(
state: copyfile_state_t,
flag: u32,
dst: *mut libc::c_void,
) -> libc::c_int;
}
struct FreeOnDrop(copyfile_state_t);
impl Drop for FreeOnDrop {
fn drop(&mut self) {
// The code below ensures that `FreeOnDrop` is never a null pointer
unsafe {
// `copyfile_state_free` returns -1 if the `to` or `from` files
// cannot be closed. However, this is not considerd this an
// error.
copyfile_state_free(self.0);
}
}
}
if !from.is_file() {
return Err(Error::new(ErrorKind::InvalidInput,
"the source path is not an existing regular file"))
}
// We ensure that `FreeOnDrop` never contains a null pointer so it is
// always safe to call `copyfile_state_free`
let state = unsafe {
let state = copyfile_state_alloc();
if state.is_null() {
return Err(crate::io::Error::last_os_error());
}
FreeOnDrop(state)
};
cvt(unsafe {
copyfile(
cstr(from)?.as_ptr(),
cstr(to)?.as_ptr(),
state.0,
COPYFILE_ALL,
)
})?;
let mut bytes_copied: libc::off_t = 0;
cvt(unsafe {
copyfile_state_get(
state.0,
COPYFILE_STATE_COPIED,
&mut bytes_copied as *mut libc::off_t as *mut libc::c_void,
)
})?;
Ok(bytes_copied as u64)
}

View File

@ -49,7 +49,6 @@ unsafe impl GlobalAlloc for System {
#[cfg(target_feature = "atomics")]
mod lock {
use crate::arch::wasm32;
use crate::sync::atomic::{AtomicI32, Ordering::SeqCst};
static LOCKED: AtomicI32 = AtomicI32::new(0);
@ -61,14 +60,76 @@ mod lock {
if LOCKED.swap(1, SeqCst) == 0 {
return DropLock
}
unsafe {
let r = wasm32::i32_atomic_wait(
&LOCKED as *const AtomicI32 as *mut i32,
1, // expected value
-1, // timeout
);
debug_assert!(r == 0 || r == 1);
}
// Ok so here's where things get a little depressing. At this point
// in time we need to synchronously acquire a lock, but we're
// contending with some other thread. Typically we'd execute some
// form of `i32.atomic.wait` like so:
//
// unsafe {
// let r = core::arch::wasm32::i32_atomic_wait(
// &LOCKED as *const AtomicI32 as *mut i32,
// 1, // expected value
// -1, // timeout
// );
// debug_assert!(r == 0 || r == 1);
// }
//
// Unfortunately though in doing so we would cause issues for the
// main thread. The main thread in a web browser *cannot ever
// block*, no exceptions. This means that the main thread can't
// actually execute the `i32.atomic.wait` instruction.
//
// As a result if we want to work within the context of browsers we
// need to figure out some sort of allocation scheme for the main
// thread where when there's contention on the global malloc lock we
// do... something.
//
// Possible ideas include:
//
// 1. Attempt to acquire the global lock. If it fails, fall back to
// memory allocation via `memory.grow`. Later just ... somehow
// ... inject this raw page back into the main allocator as it
// gets sliced up over time. This strategy has the downside of
// forcing allocation of a page to happen whenever the main
// thread contents with other threads, which is unfortunate.
//
// 2. Maintain a form of "two level" allocator scheme where the main
// thread has its own allocator. Somehow this allocator would
// also be balanced with a global allocator, not only to have
// allocations cross between threads but also to ensure that the
// two allocators stay "balanced" in terms of free'd memory and
// such. This, however, seems significantly complicated.
//
// Out of a lack of other ideas, the current strategy implemented
// here is to simply spin. Typical spin loop algorithms have some
// form of "hint" here to the CPU that it's what we're doing to
// ensure that the CPU doesn't get too hot, but wasm doesn't have
// such an instruction.
//
// To be clear, spinning here is not a great solution.
// Another thread with the lock may take quite a long time to wake
// up. For example it could be in `memory.grow` or it could be
// evicted from the CPU for a timeslice like 10ms. For these periods
// of time our thread will "helpfully" sit here and eat CPU time
// until it itself is evicted or the lock holder finishes. This
// means we're just burning and wasting CPU time to no one's
// benefit.
//
// Spinning does have the nice properties, though, of being
// semantically correct, being fair to all threads for memory
// allocation, and being simple enough to implement.
//
// This will surely (hopefully) be replaced in the future with a
// real memory allocator that can handle the restriction of the main
// thread.
//
//
// FIXME: We can also possibly add an optimization here to detect
// when a thread is the main thread or not and block on all
// non-main-thread threads. Currently, however, we have no way
// of knowing which wasm thread is on the browser main thread, but
// if we could figure out we could at least somewhat mitigate the
// cost of this spinning.
}
}
@ -76,12 +137,16 @@ mod lock {
fn drop(&mut self) {
let r = LOCKED.swap(0, SeqCst);
debug_assert_eq!(r, 1);
unsafe {
wasm32::atomic_notify(
&LOCKED as *const AtomicI32 as *mut i32,
1, // only one thread
);
}
// Note that due to the above logic we don't actually need to wake
// anyone up, but if we did it'd likely look something like this:
//
// unsafe {
// core::arch::wasm32::atomic_notify(
// &LOCKED as *const AtomicI32 as *mut i32,
// 1, // only one thread
// );
// }
}
}
}

View File

@ -37,9 +37,9 @@ pub struct Pipes {
///
/// The ours/theirs pipes are *not* specifically readable or writable. Each
/// one only supports a read or a write, but which is which depends on the
/// boolean flag given. If `ours_readable` is true then `ours` is readable where
/// `theirs` is writable. Conversely if `ours_readable` is false then `ours` is
/// writable where `theirs` is readable.
/// boolean flag given. If `ours_readable` is `true`, then `ours` is readable and
/// `theirs` is writable. Conversely, if `ours_readable` is `false`, then `ours`
/// is writable and `theirs` is readable.
///
/// Also note that the `ours` pipe is always a handle opened up in overlapped
/// mode. This means that technically speaking it should only ever be used

View File

@ -712,13 +712,6 @@ mod tests {
assert_almost_eq!(a - second + second, a);
assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a);
// A difference of 80 and 800 years cannot fit inside a 32-bit time_t
if !(cfg!(unix) && crate::mem::size_of::<libc::time_t>() <= 4) {
let eighty_years = second * 60 * 60 * 24 * 365 * 80;
assert_almost_eq!(a - eighty_years + eighty_years, a);
assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
}
let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000)
+ Duration::new(0, 500_000_000);
@ -747,8 +740,8 @@ mod tests {
#[test]
fn since_epoch() {
let ts = SystemTime::now();
let a = ts.duration_since(UNIX_EPOCH).unwrap();
let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
let a = ts.duration_since(UNIX_EPOCH + Duration::new(1, 0)).unwrap();
let b = ts.duration_since(UNIX_EPOCH).unwrap();
assert!(b > a);
assert_eq!(b - a, Duration::new(1, 0));

View File

@ -24,8 +24,8 @@ pub struct StripUnconfigured<'a> {
}
// `cfg_attr`-process the crate's attributes and compute the crate's features.
pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
-> (ast::Crate, Features) {
pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition,
allow_features: &Option<Vec<String>>) -> (ast::Crate, Features) {
let features;
{
let mut strip_unconfigured = StripUnconfigured {
@ -43,7 +43,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
return (krate, Features::new());
}
features = get_features(&sess.span_diagnostic, &krate.attrs, edition);
features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features);
// Avoid reconfiguring malformed `cfg_attr`s
if err_count == sess.span_diagnostic.err_count() {

View File

@ -378,6 +378,21 @@ Erroneous code example:
"##,
E0725: r##"
A feature attribute named a feature that was disallowed in the compiler
command line flags.
Erroneous code example:
```ignore (can't specify compiler flags from doctests)
#![feature(never_type)] // error: the feature `never_type` is not in
// the list of allowed features
```
Delete the offending feature attribute, or add it to the list of allowed
features in the `-Z allow_features` flag.
"##,
}
register_diagnostics! {

View File

@ -2008,7 +2008,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
crate_edition: Edition) -> Features {
crate_edition: Edition, allow_features: &Option<Vec<String>>) -> Features {
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
if let Some(reason) = reason {
@ -2127,6 +2127,15 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
}
if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
if let Some(allowed) = allow_features.as_ref() {
if allowed.iter().find(|f| *f == name.as_str()).is_none() {
span_err!(span_handler, mi.span, E0725,
"the feature `{}` is not in the list of allowed features",
name);
continue;
}
}
set(&mut features, mi.span);
features.declared_lang_features.push((name, mi.span, None));
continue

View File

@ -5116,12 +5116,8 @@ impl<'a> Parser<'a> {
let ident = self.parse_ident()?;
let (delim, tokens) = self.expect_delimited_token_tree()?;
if delim != MacDelimiter::Brace {
if !self.eat(&token::Semi) {
let msg = "macros that expand to items must either \
be surrounded with braces or followed by a semicolon";
self.span_err(self.prev_span, msg);
}
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
(ident, ast::MacroDef { tokens: tokens, legacy: true })
@ -5264,13 +5260,8 @@ impl<'a> Parser<'a> {
// if it has a special ident, it's definitely an item
//
// Require a semicolon or braces.
if style != MacStmtStyle::Braces {
if !self.eat(&token::Semi) {
self.span_err(self.prev_span,
"macros that expand to items must \
either be surrounded with braces or \
followed by a semicolon");
}
if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
let span = lo.to(hi);
Stmt {
@ -8360,13 +8351,8 @@ impl<'a> Parser<'a> {
};
// eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;
if delim != MacDelimiter::Brace {
if !self.eat(&token::Semi) {
self.span_err(self.prev_span,
"macros that expand to items must either \
be surrounded with braces or followed by \
a semicolon");
}
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
let hi = self.prev_span;
@ -8597,6 +8583,25 @@ impl<'a> Parser<'a> {
}
}
}
fn report_invalid_macro_expansion_item(&self) {
self.struct_span_err(
self.prev_span,
"macros that expand to items must be delimited with braces or followed by a semicolon",
).multipart_suggestion(
"change the delimiters to curly braces",
vec![
(self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), String::from(" {")),
(self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()),
],
Applicability::MaybeIncorrect,
).span_suggestion(
self.sess.source_map.next_point(self.prev_span),
"add a semicolon",
';'.to_string(),
Applicability::MaybeIncorrect,
).emit();
}
}
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {

@ -1 +1 @@
Subproject commit 38ad31bde8ff681d862dc0f96930a5dd9b7a472e
Subproject commit 4fc9fb8245abe24680192535870c4522644a4212

View File

@ -7,11 +7,18 @@ impl A {
const ASSOCIATED_CONSTANT: i32 = 2;
}
// See #59021
enum Test {
X(usize),
Y { a: usize },
}
enum E {
V = 5,
}
fn main() {
let f = Test::X as fn(usize) -> Test;
let v = Vec::<i32>::new();
}
@ -64,3 +71,14 @@ fn main() {
// _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5];
// }
// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
// START rustc.Test-X.mir_map.0.mir
// fn Test::X(_1: usize) -> Test {
// let mut _0: Test;
//
// bb0: {
// _0 = Test::X(move _1,);
// return;
// }
// }
// END rustc.Test-X.mir_map.0.mir

View File

@ -14,7 +14,7 @@ pub fn main() {
let z : &str = "thing";
assert_eq!(v, x);
assert!(x != z);
assert_ne!(x, z);
let a = "aaaa";
let b = "bbbb";
@ -26,7 +26,7 @@ pub fn main() {
assert!(a < b);
assert!(a <= b);
assert!(a != b);
assert_ne!(a, b);
assert!(b >= a);
assert!(b > a);
@ -34,7 +34,7 @@ pub fn main() {
assert!(a < c);
assert!(a <= c);
assert!(a != c);
assert_ne!(a, c);
assert!(c >= a);
assert!(c > a);
@ -42,7 +42,7 @@ pub fn main() {
assert!(c < cc);
assert!(c <= cc);
assert!(c != cc);
assert_ne!(c, cc);
assert!(cc >= c);
assert!(cc > c);

View File

@ -0,0 +1,30 @@
// edition:2018
// run-pass
#![feature(async_await, await_macro, futures_api)]
trait Foo { }
impl Foo for () { }
impl<'a, T> Foo for &'a mut T where T: Foo { }
async fn foo_async<T>(_v: T) -> u8 where T: Foo {
0
}
async fn bad<T>(v: T) -> u8 where T: Foo {
await!(foo_async(v))
}
async fn async_main() {
let mut v = ();
let _ = await!(bad(&mut v));
let _ = await!(foo_async(&mut v));
let _ = await!(bad(v));
}
fn main() {
let _ = async_main();
}

View File

@ -0,0 +1,9 @@
pub struct Gcm<E>(E);
impl<E> Gcm<E> {
pub fn crash(e: E) -> Self {
Self::<E>(e)
}
}
fn main() {}

View File

@ -37,6 +37,22 @@ fn main() {
check::<f32x6>();
check::<f32x7>();
check::<f32x8>();
check::<usizex2>();
check::<usizex3>();
check::<usizex4>();
check::<usizex5>();
check::<usizex6>();
check::<usizex7>();
check::<usizex8>();
check::<isizex2>();
check::<isizex3>();
check::<isizex4>();
check::<isizex5>();
check::<isizex6>();
check::<isizex7>();
check::<isizex8>();
}
#[repr(simd)] struct u8x2(u8, u8);
@ -62,3 +78,19 @@ fn main() {
#[repr(simd)] struct f32x6(f32, f32, f32, f32, f32, f32);
#[repr(simd)] struct f32x7(f32, f32, f32, f32, f32, f32, f32);
#[repr(simd)] struct f32x8(f32, f32, f32, f32, f32, f32, f32, f32);
#[repr(simd)] struct usizex2(usize, usize);
#[repr(simd)] struct usizex3(usize, usize, usize);
#[repr(simd)] struct usizex4(usize, usize, usize, usize);
#[repr(simd)] struct usizex5(usize, usize, usize, usize, usize);
#[repr(simd)] struct usizex6(usize, usize, usize, usize, usize, usize);
#[repr(simd)] struct usizex7(usize, usize, usize, usize, usize, usize, usize);
#[repr(simd)] struct usizex8(usize, usize, usize, usize, usize, usize, usize, usize);
#[repr(simd)] struct isizex2(isize, isize);
#[repr(simd)] struct isizex3(isize, isize, isize);
#[repr(simd)] struct isizex4(isize, isize, isize, isize);
#[repr(simd)] struct isizex5(isize, isize, isize, isize, isize);
#[repr(simd)] struct isizex6(isize, isize, isize, isize, isize, isize);
#[repr(simd)] struct isizex7(isize, isize, isize, isize, isize, isize, isize);
#[repr(simd)] struct isizex8(isize, isize, isize, isize, isize, isize, isize, isize);

View File

@ -0,0 +1,11 @@
// compile-pass
union Uninit {
_never_use: *const u8,
uninit: (),
}
const UNINIT: Uninit = Uninit { uninit: () };
fn main() {}

View File

@ -0,0 +1,10 @@
// compile-flags: -Z allow_features=
// Note: This test uses rustc internal flags because they will never stabilize.
#![feature(rustc_diagnostic_macros)] //~ ERROR
#![feature(rustc_const_unstable)] //~ ERROR
#![feature(lang_items)] //~ ERROR
fn main() {}

View File

@ -0,0 +1,21 @@
error[E0725]: the feature `rustc_diagnostic_macros` is not in the list of allowed features
--> $DIR/allow-features-empty.rs:4:12
|
LL | #![feature(rustc_diagnostic_macros)]
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
--> $DIR/allow-features-empty.rs:6:12
|
LL | #![feature(rustc_const_unstable)]
| ^^^^^^^^^^^^^^^^^^^^
error[E0725]: the feature `lang_items` is not in the list of allowed features
--> $DIR/allow-features-empty.rs:8:12
|
LL | #![feature(lang_items)]
| ^^^^^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0725`.

View File

@ -0,0 +1,10 @@
// compile-flags: -Z allow_features=rustc_diagnostic_macros,lang_items
// Note: This test uses rustc internal flags because they will never stabilize.
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_const_unstable)] //~ ERROR
#![feature(lang_items)]
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0725]: the feature `rustc_const_unstable` is not in the list of allowed features
--> $DIR/allow-features.rs:6:12
|
LL | #![feature(rustc_const_unstable)]
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0725`.

View File

@ -12,7 +12,7 @@ pub fn main() {
foo!();
assert!({one! two()});
//~^ ERROR macros that expand to items must either be surrounded with braces or followed by a
//~^ ERROR macros that expand to items
//~| ERROR cannot find macro `one!` in this scope
//~| ERROR mismatched types

View File

@ -1,8 +1,16 @@
error: macros that expand to items must either be surrounded with braces or followed by a semicolon
error: macros that expand to items must be delimited with braces or followed by a semicolon
--> $DIR/issue-10536.rs:14:22
|
LL | assert!({one! two()});
| ^^
help: change the delimiters to curly braces
|
LL | assert!({one! two {}});
| ^^
help: add a semicolon
|
LL | assert!({one! two();});
| ^
error: expected `(` or `{`, found `}`
--> $DIR/issue-10536.rs:21:22

View File

@ -0,0 +1,8 @@
#![feature(trait_alias)]
trait Svc<Req> { type Res; }
trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
//~^ ERROR associated type `Res` not found for `Self`
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0220]: associated type `Res` not found for `Self`
--> $DIR/issue-59029-1.rs:5:46
|
LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
| ^^^^^^^^^ associated type `Res` not found
error: aborting due to previous error
For more information about this error, try `rustc --explain E0220`.

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