From: kennytm Date: Fri, 12 Oct 2018 14:04:16 +0000 (+0800) Subject: Rollup merge of #54967 - holmgr:master, r=estebank X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=644dbf99edf1b59e3b820bc14ea849c6505e3945;hp=05bb22d9e86bcf4953ad2dbba36fa0adb6ebc859;p=rust.git Rollup merge of #54967 - holmgr:master, r=estebank Remove incorrect span for second label inner macro invocation A fix for issue #54841 --- diff --git a/config.toml.example b/config.toml.example index 312270532af..1c851999130 100644 --- a/config.toml.example +++ b/config.toml.example @@ -243,19 +243,36 @@ # ============================================================================= [rust] -# Indicates that the build should be optimized for debugging Rust. Note that -# this is typically not what you want as it takes an incredibly large amount of -# time to have a debug-mode rustc compile any code (notably libstd). If this -# value is set to `true` it will affect a number of configuration options below -# as well, if unconfigured. -#debug = false - -# Whether or not to optimize the compiler and standard library +# Whether or not to optimize the compiler and standard library. +# # Note: the slowness of the non optimized compiler compiling itself usually # outweighs the time gains in not doing optimizations, therefore a -# full bootstrap takes much more time with optimize set to false. +# full bootstrap takes much more time with `optimize` set to false. #optimize = true +# Indicates that the build should be configured for debugging Rust. A +# `debug`-enabled compiler and standard library will be somewhat +# slower (due to e.g. checking of debug assertions) but should remain +# usable. +# +# Note: If this value is set to `true`, it will affect a number of +# configuration options below as well, if they have been left +# unconfigured in this file. +# +# Note: changes to the `debug` setting do *not* affect `optimize` +# above. In theory, a "maximally debuggable" environment would +# set `optimize` to `false` above to assist the introspection +# facilities of debuggers like lldb and gdb. To recreate such an +# environment, explicitly set `optimize` to `false` and `debug` +# to `true`. In practice, everyone leaves `optimize` set to +# `true`, because an unoptimized rustc with debugging +# enabled becomes *unusably slow* (e.g. rust-lang/rust#24840 +# reported a 25x slowdown) and bootstrapping the supposed +# "maximally debuggable" environment (notably libstd) takes +# hours to build. +# +#debug = false + # Number of codegen units to use for each compiler invocation. A value of 0 # means "the number of cores on this machine", and 1+ is passed through to the # compiler. diff --git a/src/Cargo.lock b/src/Cargo.lock index 6a9488226b1..c01086b3f6f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -270,7 +270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chalk-engine" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1269,7 +1269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "minifier" -version = "0.0.19" +version = "0.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1898,7 +1898,7 @@ dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "fmt_macros 0.0.0", "graphviz 0.0.0", @@ -2434,7 +2434,7 @@ name = "rustc_traits" version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", @@ -2484,7 +2484,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3195,7 +3195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" -"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0" +"checksum chalk-engine 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6749eb72e7d4355d944a99f15fbaea701b978c18c5e184a025fcde942b0c9779" "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" "checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" @@ -3289,7 +3289,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11" +"checksum minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" "checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index c3fbc8eeca6..a5ed096a735 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -628,6 +628,9 @@ pub fn parse(args: &[String]) -> Config { let default = false; config.llvm_assertions = llvm_assertions.unwrap_or(default); + let default = true; + config.rust_optimize = optimize.unwrap_or(default); + let default = match &config.channel[..] { "stable" | "beta" | "nightly" => true, _ => false, @@ -640,7 +643,6 @@ pub fn parse(args: &[String]) -> Config { config.debug_jemalloc = debug_jemalloc.unwrap_or(default); config.rust_debuginfo = debuginfo.unwrap_or(default); config.rust_debug_assertions = debug_assertions.unwrap_or(default); - config.rust_optimize = optimize.unwrap_or(!default); let default = config.channel == "dev"; config.ignore_git = ignore_git.unwrap_or(default); diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index ec94f57861d..5d174719ab2 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -91,13 +91,13 @@ pub fn try_run_suppressed(cmd: &mut Command) -> bool { output.status.success() } -pub fn gnu_target(target: &str) -> String { +pub fn gnu_target(target: &str) -> &str { match target { - "i686-pc-windows-msvc" => "i686-pc-win32".to_string(), - "x86_64-pc-windows-msvc" => "x86_64-pc-win32".to_string(), - "i686-pc-windows-gnu" => "i686-w64-mingw32".to_string(), - "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32".to_string(), - s => s.to_string(), + "i686-pc-windows-msvc" => "i686-pc-win32", + "x86_64-pc-windows-msvc" => "x86_64-pc-win32", + "i686-pc-windows-gnu" => "i686-w64-mingw32", + "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32", + s => s, } } diff --git a/src/doc/unstable-book/src/language-features/cfg-attr-multi.md b/src/doc/unstable-book/src/language-features/cfg-attr-multi.md new file mode 100644 index 00000000000..6365d3e71c6 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/cfg-attr-multi.md @@ -0,0 +1,20 @@ +# `cfg_attr_multi` + +The tracking issue for this feature is: [#54881] +The RFC for this feature is: [#2539] + +[#54881]: https://github.com/rust-lang/rust/issues/54881 +[#2539]: https://github.com/rust-lang/rfcs/pull/2539 + +------------------------ + +This feature flag lets you put multiple attributes into a `cfg_attr` attribute. + +Example: + +```rust,ignore +#[cfg_attr(all(), must_use, optimize)] +``` + +Because `cfg_attr` resolves before procedural macros, this does not affect +macro resolution at all. \ No newline at end of file diff --git a/src/doc/unstable-book/src/language-features/tool-lints.md b/src/doc/unstable-book/src/language-features/tool-lints.md deleted file mode 100644 index 5c0d33b5ab0..00000000000 --- a/src/doc/unstable-book/src/language-features/tool-lints.md +++ /dev/null @@ -1,35 +0,0 @@ -# `tool_lints` - -The tracking issue for this feature is: [#44690] - -[#44690]: https://github.com/rust-lang/rust/issues/44690 - ------------------------- - -Tool lints let you use scoped lints, to `allow`, `warn`, `deny` or `forbid` lints of -certain tools. - -Currently `clippy` is the only available lint tool. - -It is recommended for lint tools to implement the scoped lints like this: - -- `#[_(TOOL_NAME::lintname)]`: for lint names -- `#[_(TOOL_NAME::lintgroup)]`: for groups of lints -- `#[_(TOOL_NAME::all)]`: for (almost[^1]) all lints - -## An example - -```rust -#![feature(tool_lints)] - -#![warn(clippy::pedantic)] - -#[allow(clippy::filter_map)] -fn main() { - let v = vec![0; 10]; - let _ = v.into_iter().filter(|&x| x < 1).map(|x| x + 1).collect::>(); - println!("No filter_map()!"); -} -``` - -[^1]: Some defined lint groups can be excluded here. diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py index 216915dba5f..b1252f386df 100755 --- a/src/etc/gdb_rust_pretty_printing.py +++ b/src/etc/gdb_rust_pretty_printing.py @@ -322,8 +322,11 @@ class RustStdBTreeSetPrinter(object): def children(self): (length, data_ptr) = \ rustpp.extract_length_and_ptr_from_std_btreeset(self.__val) - val = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3) - gdb_ptr = val.get_wrapped_value() + leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference()) + maybe_uninit_keys = leaf_node.get_child_at_index(3) + manually_drop_keys = maybe_uninit_keys.get_child_at_index(1) + keys = manually_drop_keys.get_child_at_index(0) + gdb_ptr = keys.get_wrapped_value() for index in xrange(length): yield (str(index), gdb_ptr[index]) @@ -345,9 +348,14 @@ class RustStdBTreeMapPrinter(object): def children(self): (length, data_ptr) = \ rustpp.extract_length_and_ptr_from_std_btreemap(self.__val) - keys = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3) + leaf_node = GdbValue(data_ptr.get_wrapped_value().dereference()) + maybe_uninit_keys = leaf_node.get_child_at_index(3) + manually_drop_keys = maybe_uninit_keys.get_child_at_index(1) + keys = manually_drop_keys.get_child_at_index(0) keys_ptr = keys.get_wrapped_value() - vals = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(4) + maybe_uninit_vals = leaf_node.get_child_at_index(4) + manually_drop_vals = maybe_uninit_vals.get_child_at_index(1) + vals = manually_drop_vals.get_child_at_index(0) vals_ptr = vals.get_wrapped_value() for index in xrange(length): yield (str(index), keys_ptr[index]) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 0315545262b..deca9591fbd 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -42,7 +42,7 @@ // This implies that even an empty internal node has at least one edge. use core::marker::PhantomData; -use core::mem; +use core::mem::{self, MaybeUninit}; use core::ptr::{self, Unique, NonNull}; use core::slice; @@ -58,9 +58,6 @@ /// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned /// case. /// -/// See also rust-lang/rfcs#197, which would make this structure significantly more safe by -/// avoiding accidentally dropping unused and uninitialized keys and values. -/// /// We put the metadata first so that its position is the same for every `K` and `V`, in order /// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to /// prevent them from being reordered. @@ -73,7 +70,7 @@ struct LeafNode { /// This node's index into the parent node's `edges` array. /// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`. /// This is only guaranteed to be initialized when `parent` is nonnull. - parent_idx: u16, + parent_idx: MaybeUninit, /// The number of keys and values this node stores. /// @@ -83,8 +80,8 @@ struct LeafNode { /// The arrays storing the actual data of the node. Only the first `len` elements of each /// array are initialized and valid. - keys: [K; CAPACITY], - vals: [V; CAPACITY], + keys: MaybeUninit<[K; CAPACITY]>, + vals: MaybeUninit<[V; CAPACITY]>, } impl LeafNode { @@ -94,10 +91,10 @@ unsafe fn new() -> Self { LeafNode { // As a general policy, we leave fields uninitialized if they can be, as this should // be both slightly faster and easier to track in Valgrind. - keys: mem::uninitialized(), - vals: mem::uninitialized(), + keys: MaybeUninit::uninitialized(), + vals: MaybeUninit::uninitialized(), parent: ptr::null(), - parent_idx: mem::uninitialized(), + parent_idx: MaybeUninit::uninitialized(), len: 0 } } @@ -115,10 +112,10 @@ unsafe impl Sync for LeafNode<(), ()> {} // ever take a pointer past the first key. static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode { parent: ptr::null(), - parent_idx: 0, + parent_idx: MaybeUninit::uninitialized(), len: 0, - keys: [(); CAPACITY], - vals: [(); CAPACITY], + keys: MaybeUninit::uninitialized(), + vals: MaybeUninit::uninitialized(), }; /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden @@ -430,7 +427,7 @@ pub fn ascend(self) -> Result< root: self.root, _marker: PhantomData }, - idx: self.as_leaf().parent_idx as usize, + idx: unsafe { usize::from(*self.as_leaf().parent_idx.get_ref()) }, _marker: PhantomData }) } else { @@ -567,7 +564,7 @@ fn into_key_slice(self) -> &'a [K] { // the node, which is allowed by LLVM. unsafe { slice::from_raw_parts( - self.as_leaf().keys.as_ptr(), + self.as_leaf().keys.as_ptr() as *const K, self.len() ) } @@ -578,7 +575,7 @@ fn into_val_slice(self) -> &'a [V] { debug_assert!(!self.is_shared_root()); unsafe { slice::from_raw_parts( - self.as_leaf().vals.as_ptr(), + self.as_leaf().vals.as_ptr() as *const V, self.len() ) } @@ -605,7 +602,7 @@ fn into_key_slice_mut(mut self) -> &'a mut [K] { } else { unsafe { slice::from_raw_parts_mut( - &mut self.as_leaf_mut().keys as *mut [K] as *mut K, + self.as_leaf_mut().keys.get_mut() as *mut [K] as *mut K, self.len() ) } @@ -616,7 +613,7 @@ fn into_val_slice_mut(mut self) -> &'a mut [V] { debug_assert!(!self.is_shared_root()); unsafe { slice::from_raw_parts_mut( - &mut self.as_leaf_mut().vals as *mut [V] as *mut V, + self.as_leaf_mut().vals.get_mut() as *mut [V] as *mut V, self.len() ) } @@ -1013,7 +1010,7 @@ fn correct_parent_link(mut self) { let ptr = self.node.as_internal_mut() as *mut _; let mut child = self.descend(); child.as_leaf_mut().parent = ptr; - child.as_leaf_mut().parent_idx = idx; + child.as_leaf_mut().parent_idx.set(idx); } /// Unsafely asserts to the compiler some static information about whether the underlying @@ -1152,12 +1149,12 @@ pub fn split(mut self) ptr::copy_nonoverlapping( self.node.keys().as_ptr().add(self.idx + 1), - new_node.keys.as_mut_ptr(), + new_node.keys.as_mut_ptr() as *mut K, new_len ); ptr::copy_nonoverlapping( self.node.vals().as_ptr().add(self.idx + 1), - new_node.vals.as_mut_ptr(), + new_node.vals.as_mut_ptr() as *mut V, new_len ); @@ -1210,12 +1207,12 @@ pub fn split(mut self) ptr::copy_nonoverlapping( self.node.keys().as_ptr().add(self.idx + 1), - new_node.data.keys.as_mut_ptr(), + new_node.data.keys.as_mut_ptr() as *mut K, new_len ); ptr::copy_nonoverlapping( self.node.vals().as_ptr().add(self.idx + 1), - new_node.data.vals.as_mut_ptr(), + new_node.data.vals.as_mut_ptr() as *mut V, new_len ); ptr::copy_nonoverlapping( diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 78d1958b8fb..987572e6b74 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -119,6 +119,7 @@ #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] +#![feature(maybe_uninit)] // Allow testing this library diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 2bc037e3fee..f7a0bbdceaf 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -120,11 +120,17 @@ /// assert_eq!(vec, [1, 2, 3, 4]); /// ``` /// -/// It can also initialize each element of a `Vec` with a given value: +/// It can also initialize each element of a `Vec` with a given value. +/// This may be more efficient than performing allocation and initialization +/// in separate steps, especially when initializing a vector of zeros: /// /// ``` /// let vec = vec![0; 5]; /// assert_eq!(vec, [0, 0, 0, 0, 0]); +/// +/// // The following is equivalent, but potentially slower: +/// let mut vec1 = Vec::with_capacity(5); +/// vec1.resize(5, 0); /// ``` /// /// Use a `Vec` as an efficient stack: diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 3ef03ec6d58..15283036bb4 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -20,6 +20,10 @@ #![feature(nll)] #![feature(staged_api)] #![feature(rustc_attrs)] +#![cfg_attr( + all(target_arch = "wasm32", not(target_os = "emscripten")), + feature(integer_atomics, stdsimd) +)] #![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))] #![rustc_alloc_kind = "lib"] @@ -331,29 +335,76 @@ mod platform { use core::alloc::{GlobalAlloc, Layout}; use System; - // No need for synchronization here as wasm is currently single-threaded static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let _lock = lock::lock(); DLMALLOC.malloc(layout.size(), layout.align()) } #[inline] unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + let _lock = lock::lock(); DLMALLOC.calloc(layout.size(), layout.align()) } #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let _lock = lock::lock(); DLMALLOC.free(ptr, layout.size(), layout.align()) } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let _lock = lock::lock(); DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } } + + #[cfg(target_feature = "atomics")] + mod lock { + use core::arch::wasm32; + use core::sync::atomic::{AtomicI32, Ordering::SeqCst}; + + static LOCKED: AtomicI32 = AtomicI32::new(0); + + pub struct DropLock; + + pub fn lock() -> DropLock { + loop { + if LOCKED.swap(1, SeqCst) == 0 { + return DropLock + } + unsafe { + let r = wasm32::atomic::wait_i32( + &LOCKED as *const AtomicI32 as *mut i32, + 1, // expected value + -1, // timeout + ); + debug_assert!(r == 0 || r == 1); + } + } + } + + impl Drop for DropLock { + fn drop(&mut self) { + let r = LOCKED.swap(0, SeqCst); + debug_assert_eq!(r, 1); + unsafe { + wasm32::atomic::wake( + &LOCKED as *const AtomicI32 as *mut i32, + 1, // only one thread + ); + } + } + } + } + + #[cfg(not(target_feature = "atomics"))] + mod lock { + pub fn lock() {} // no atomics, no threads, that's easy! + } } diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 0255f7a0885..cf1c77041b9 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -867,8 +867,6 @@ pub fn take(&mut self) -> Option { /// # Examples /// /// ``` - /// #![feature(option_replace)] - /// /// let mut x = Some(2); /// let old = x.replace(5); /// assert_eq!(x, Some(5)); @@ -880,7 +878,7 @@ pub fn take(&mut self) -> Option { /// assert_eq!(old, None); /// ``` #[inline] - #[unstable(feature = "option_replace", issue = "51998")] + #[stable(feature = "option_replace", since = "1.31.0")] pub fn replace(&mut self, value: T) -> Option { mem::replace(self, Some(value)) } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index bd58dcf4ae0..b8d7fcffbcc 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2370,13 +2370,13 @@ fn mod_inv(x: usize, m: usize) -> usize { /// /// Note, that this table does not contain values where inverse does not exist (i.e. for /// `0⁻¹ mod 16`, `2⁻¹ mod 16`, etc.) - const INV_TABLE_MOD_16: [usize; 8] = [1, 11, 13, 7, 9, 3, 5, 15]; + const INV_TABLE_MOD_16: [u8; 8] = [1, 11, 13, 7, 9, 3, 5, 15]; /// Modulo for which the `INV_TABLE_MOD_16` is intended. const INV_TABLE_MOD: usize = 16; /// INV_TABLE_MOD² const INV_TABLE_MOD_SQUARED: usize = INV_TABLE_MOD * INV_TABLE_MOD; - let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1]; + let table_inverse = INV_TABLE_MOD_16[(x & (INV_TABLE_MOD - 1)) >> 1] as usize; if m <= INV_TABLE_MOD { table_inverse & (m - 1) } else { @@ -2429,36 +2429,23 @@ fn mod_inv(x: usize, m: usize) -> usize { let gcdpow = intrinsics::cttz_nonzero(stride).min(intrinsics::cttz_nonzero(a)); let gcd = 1usize << gcdpow; - if gcd == 1 { - // This branch solves for the variable $o$ in following linear congruence equation: - // - // ⎰ p + o ≡ 0 (mod a) # $p + o$ must be aligned to specified alignment $a$ - // ⎱ o ≡ 0 (mod s) # offset $o$ must be a multiple of stride $s$ - // - // where + if p as usize & (gcd - 1) == 0 { + // This branch solves for the following linear congruence equation: // - // * a, s are co-prime + // $$ p + so ≡ 0 mod a $$ // - // This gives us the formula below: + // $p$ here is the pointer value, $s$ – stride of `T`, $o$ offset in `T`s, and $a$ – the + // requested alignment. // - // o = (a - (p mod a)) * (s⁻¹ mod a) * s + // g = gcd(a, s) + // o = (a - (p mod a))/g * ((s/g)⁻¹ mod a) // // The first term is “the relative alignment of p to a”, the second term is “how does - // incrementing p by one s change the relative alignment of p”, the third term is - // translating change in units of s to a byte count. + // incrementing p by s bytes change the relative alignment of p”. Division by `g` is + // necessary to make this equation well formed if $a$ and $s$ are not co-prime. // // Furthermore, the result produced by this solution is not “minimal”, so it is necessary - // to take the result $o mod lcm(s, a)$. Since $s$ and $a$ are co-prime (i.e. $gcd(s, a) = - // 1$) and $lcm(s, a) = s * a / gcd(s, a)$, we can replace $lcm(s, a)$ with just a $s * a$. - // - // (Author note: we decided later on to express the offset in "elements" rather than bytes, - // which drops the multiplication by `s` on both sides of the modulo.) - return intrinsics::unchecked_rem(a.wrapping_sub(pmoda).wrapping_mul(mod_inv(smoda, a)), a); - } - - if p as usize & (gcd - 1) == 0 { - // This can be aligned, but `a` and `stride` are not co-prime, so a somewhat adapted - // formula is used. + // to take the result $o mod lcm(s, a)$. We can replace $lcm(s, a)$ with just a $a / g$. let j = a.wrapping_sub(pmoda) >> gcdpow; let k = smoda >> gcdpow; return intrinsics::unchecked_rem(j.wrapping_mul(mod_inv(k, a)), a >> gcdpow); diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 76dcca02578..c9013f589ed 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1932,7 +1932,7 @@ fn align_to_offsets(&self) -> (usize, usize) { fn gcd(a: usize, b: usize) -> usize { // iterative stein’s algorithm // We should still make this `const fn` (and revert to recursive algorithm if we do) - // because relying on llvm to consteval all this is… well, it makes me + // because relying on llvm to consteval all this is… well, it makes me uncomfortable. let (ctz_a, mut ctz_b) = unsafe { if a == 0 { return b; } if b == 0 { return a; } diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 651db6356ba..ab4ae50c443 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -12,7 +12,7 @@ reason = "futures in libcore are unstable", issue = "50547")] -use {fmt, mem}; +use fmt; use marker::Unpin; use ptr::NonNull; @@ -63,6 +63,20 @@ pub fn wake(&self) { pub fn will_wake(&self, other: &Waker) -> bool { self.inner == other.inner } + + /// Returns whether or not this `Waker` and `other` `LocalWaker` awaken + /// 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 + /// returns true, it is guaranteed that the `Waker`s will awaken the same + /// task. + /// + /// This function is primarily used for optimization purposes. + #[inline] + pub fn will_wake_local(&self, other: &LocalWaker) -> bool { + self.will_wake(&other.0) + } } impl Clone for Waker { @@ -97,9 +111,8 @@ fn drop(&mut self) { /// Task executors can use this type to implement more optimized singlethreaded wakeup /// behavior. #[repr(transparent)] -pub struct LocalWaker { - inner: NonNull, -} +#[derive(Clone)] +pub struct LocalWaker(Waker); impl Unpin for LocalWaker {} impl !Send for LocalWaker {} @@ -120,7 +133,16 @@ impl LocalWaker { /// on the current thread. #[inline] pub unsafe fn new(inner: NonNull) -> Self { - LocalWaker { inner } + LocalWaker(Waker::new(inner)) + } + + /// Borrows this `LocalWaker` as a `Waker`. + /// + /// `Waker` is nearly identical to `LocalWaker`, but is threadsafe + /// (implements `Send` and `Sync`). + #[inline] + pub fn as_waker(&self) -> &Waker { + &self.0 } /// Converts this `LocalWaker` into a `Waker`. @@ -129,13 +151,13 @@ pub unsafe fn new(inner: NonNull) -> Self { /// (implements `Send` and `Sync`). #[inline] pub fn into_waker(self) -> Waker { - self.into() + self.0 } /// Wake up the task associated with this `LocalWaker`. #[inline] pub fn wake(&self) { - unsafe { self.inner.as_ref().wake_local() } + unsafe { self.0.inner.as_ref().wake_local() } } /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task. @@ -148,7 +170,7 @@ pub fn wake(&self) { /// This function is primarily used for optimization purposes. #[inline] pub fn will_wake(&self, other: &LocalWaker) -> bool { - self.inner == other.inner + self.0.will_wake(&other.0) } /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task. @@ -161,45 +183,24 @@ pub fn will_wake(&self, other: &LocalWaker) -> bool { /// This function is primarily used for optimization purposes. #[inline] pub fn will_wake_nonlocal(&self, other: &Waker) -> bool { - self.inner == other.inner + self.0.will_wake(other) } } impl From for Waker { #[inline] fn from(local_waker: LocalWaker) -> Self { - let inner = local_waker.inner; - mem::forget(local_waker); - Waker { inner } - } -} - -impl Clone for LocalWaker { - #[inline] - fn clone(&self) -> Self { - let waker = unsafe { self.inner.as_ref().clone_raw() }; - let inner = waker.inner; - mem::forget(waker); - LocalWaker { inner } + local_waker.0 } } impl fmt::Debug for LocalWaker { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Waker") + f.debug_struct("LocalWaker") .finish() } } -impl Drop for LocalWaker { - #[inline] - fn drop(&mut self) { - unsafe { - self.inner.as_ref().drop_raw() - } - } -} - /// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`. /// /// A `Waker` conceptually is a cloneable trait object for `Wake`, and is diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index ada61d8dfd8..0beb60a1270 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -39,7 +39,6 @@ #![feature(reverse_bits)] #![feature(inner_deref)] #![feature(slice_internals)] -#![feature(option_replace)] #![feature(slice_partition_dedup)] #![feature(copy_within)] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 6c3b52196a3..d0ec8640ce9 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -31,7 +31,7 @@ syntax_pos = { path = "../libsyntax_pos" } backtrace = "0.3.3" parking_lot = "0.6" byteorder = { version = "1.1", features = ["i128"]} -chalk-engine = { version = "0.7.0", default-features=false } +chalk-engine = { version = "0.8.0", default-features=false } rustc_fs_util = { path = "../librustc_fs_util" } smallvec = { version = "0.6.5", features = ["union"] } diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e8c89cb3e0e..f51a3e71d07 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -1370,7 +1370,7 @@ impl<'a, 'tcx> HashStable> for traits::Goal<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - use traits::Goal::*; + use traits::GoalKind::*; mem::discriminant(self).hash_stable(hcx, hasher); match self { diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 87d33e473e7..950754a07ab 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -18,11 +18,10 @@ use lint::{self, Lint, LintId, Level, LintSource}; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; -use session::{config::nightly_options, Session}; +use session::Session; use syntax::ast; use syntax::attr; use syntax::source_map::MultiSpan; -use syntax::feature_gate; use syntax::symbol::Symbol; use util::nodemap::FxHashMap; @@ -228,18 +227,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { } }; let tool_name = if let Some(lint_tool) = word.is_scoped() { - let gate_feature = !self.sess.features_untracked().tool_lints; - let known_tool = attr::is_known_lint_tool(lint_tool); - if gate_feature { - feature_gate::emit_feature_err( - &sess.parse_sess, - "tool_lints", - word.span, - feature_gate::GateIssue::Language, - &format!("scoped lint `{}` is experimental", word.ident), - ); - } - if !known_tool { + if !attr::is_known_lint_tool(lint_tool) { span_err!( sess, lint_tool.span, @@ -247,9 +235,6 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { "an unknown tool name found in scoped lint: `{}`", word.ident ); - } - - if gate_feature || !known_tool { continue; } @@ -299,13 +284,7 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { "change it to", new_lint_name.to_string(), Applicability::MachineApplicable, - ); - - if nightly_options::is_nightly_build() { - err.emit(); - } else { - err.cancel(); - } + ).emit(); let src = LintSource::Node(Symbol::intern(&new_lint_name), li.span); for id in ids { diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs index 759ac1a7952..897e9cc2a38 100644 --- a/src/librustc/macros.rs +++ b/src/librustc/macros.rs @@ -62,6 +62,16 @@ macro_rules! span_bug { }) } +#[macro_export] +macro_rules! static_assert { + ($name:ident: $test:expr) => { + // Use the bool to access an array such that if the bool is false, the access + // is out-of-bounds. + #[allow(dead_code)] + static $name: () = [()][!$test as usize]; + } +} + #[macro_export] macro_rules! __impl_stable_hash_field { ($field:ident, $ctx:expr, $hasher:expr) => ($field.hash_stable($ctx, $hasher)); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index edb571da7db..a90f03f536a 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -167,8 +167,7 @@ pub struct FirstStatementIndex { .. } impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { private }); // compilation error if size of `ScopeData` is not the same as a `u32` -#[allow(dead_code)] -static ASSERT: () = [()][!(mem::size_of::() == 4) as usize]; +static_assert!(ASSERT_SCOPE_DATA: mem::size_of::() == 4); impl Scope { /// Returns a item-local id associated with this scope. diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index c532b5ee56f..d8c36f81da3 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1387,6 +1387,10 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool { "output a json file with profiler results"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emits a section containing stack size metadata"), + plt: Option = (None, parse_opt_bool, [TRACKED], + "whether to use the PLT when calling into shared libraries; + only has effect for PIC code on systems with ELF binaries + (default: PLT is disabled if full relro is enabled)"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3c209a43246..10a506da4ea 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -40,8 +40,7 @@ use syntax_pos::{MultiSpan, Span}; use util::profiling::SelfProfiler; -use rustc_target::spec::PanicStrategy; -use rustc_target::spec::{Target, TargetTriple}; +use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; use rustc_data_structures::flock; use jobserver::Client; @@ -984,6 +983,27 @@ pub fn rust_2018(&self) -> bool { pub fn edition(&self) -> Edition { self.opts.edition } + + /// True if we cannot skip the PLT for shared library calls. + pub fn needs_plt(&self) -> bool { + // Check if the current target usually needs PLT to be enabled. + // The user can use the command line flag to override it. + let needs_plt = self.target.target.options.needs_plt; + + let dbg_opts = &self.opts.debugging_opts; + + let relro_level = dbg_opts.relro_level + .unwrap_or(self.target.target.options.relro_level); + + // Only enable this optimization by default if full relro is also enabled. + // In this case, lazy binding was already unavailable, so nothing is lost. + // This also ensures `-Wl,-z,now` is supported by the linker. + let full_relro = RelroLevel::Full == relro_level; + + // If user didn't explicitly forced us to use / skip the PLT, + // then try to skip it where possible. + dbg_opts.plt.unwrap_or(needs_plt || !full_relro) + } } pub fn build_session( diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 286e35c5d4e..6e4abee32c0 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -318,31 +318,33 @@ pub enum QuantifierKind { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub enum Goal<'tcx> { - Implies(Clauses<'tcx>, &'tcx Goal<'tcx>), - And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>), - Not(&'tcx Goal<'tcx>), +pub enum GoalKind<'tcx> { + Implies(Clauses<'tcx>, Goal<'tcx>), + And(Goal<'tcx>, Goal<'tcx>), + Not(Goal<'tcx>), DomainGoal(DomainGoal<'tcx>), - Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>), + Quantified(QuantifierKind, ty::Binder>), CannotProve, } +pub type Goal<'tcx> = &'tcx GoalKind<'tcx>; + pub type Goals<'tcx> = &'tcx List>; impl<'tcx> DomainGoal<'tcx> { - pub fn into_goal(self) -> Goal<'tcx> { - Goal::DomainGoal(self) + pub fn into_goal(self) -> GoalKind<'tcx> { + GoalKind::DomainGoal(self) } } -impl<'tcx> Goal<'tcx> { +impl<'tcx> GoalKind<'tcx> { pub fn from_poly_domain_goal<'a>( domain_goal: PolyDomainGoal<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>, - ) -> Goal<'tcx> { + ) -> GoalKind<'tcx> { match domain_goal.no_late_bound_regions() { Some(p) => p.into_goal(), - None => Goal::Quantified( + None => GoalKind::Quantified( QuantifierKind::Universal, domain_goal.map_bound(|p| tcx.mk_goal(p.into_goal())) ), diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 22e79fc2638..1524f89af29 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -469,7 +469,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { impl<'tcx> fmt::Display for traits::Goal<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - use traits::Goal::*; + use traits::GoalKind::*; match self { Implies(hypotheses, goal) => { @@ -598,25 +598,25 @@ impl<'a, 'tcx> Lift<'tcx> for traits::DomainGoal<'a> { } EnumTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> { - (traits::Goal::Implies)(hypotheses, goal), - (traits::Goal::And)(goal1, goal2), - (traits::Goal::Not)(goal), - (traits::Goal::DomainGoal)(domain_goal), - (traits::Goal::Quantified)(qkind, goal), - (traits::Goal::CannotProve), + impl<'tcx> TypeFoldable<'tcx> for traits::GoalKind<'tcx> { + (traits::GoalKind::Implies)(hypotheses, goal), + (traits::GoalKind::And)(goal1, goal2), + (traits::GoalKind::Not)(goal), + (traits::GoalKind::DomainGoal)(domain_goal), + (traits::GoalKind::Quantified)(qkind, goal), + (traits::GoalKind::CannotProve), } } EnumLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for traits::Goal<'a> { - type Lifted = traits::Goal<'tcx>; - (traits::Goal::Implies)(hypotheses, goal), - (traits::Goal::And)(goal1, goal2), - (traits::Goal::Not)(goal), - (traits::Goal::DomainGoal)(domain_goal), - (traits::Goal::Quantified)(kind, goal), - (traits::Goal::CannotProve), + impl<'a, 'tcx> Lift<'tcx> for traits::GoalKind<'a> { + type Lifted = traits::GoalKind<'tcx>; + (traits::GoalKind::Implies)(hypotheses, goal), + (traits::GoalKind::And)(goal1, goal2), + (traits::GoalKind::Not)(goal), + (traits::GoalKind::DomainGoal)(domain_goal), + (traits::GoalKind::Quantified)(kind, goal), + (traits::GoalKind::CannotProve), } } @@ -633,7 +633,7 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { let v = (**self).fold_with(folder); folder.tcx().mk_goal(v) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 46ba5f5ef36..ab1df2d4c3b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -36,7 +36,7 @@ use ty::subst::{CanonicalSubsts, Kind, Substs, Subst}; use ty::ReprOptions; use traits; -use traits::{Clause, Clauses, Goal, Goals}; +use traits::{Clause, Clauses, GoalKind, Goal, Goals}; use ty::{self, Ty, TypeAndMut}; use ty::{TyS, TyKind, List}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const}; @@ -143,7 +143,8 @@ pub struct CtxtInterners<'tcx> { predicates: InternedSet<'tcx, List>>, const_: InternedSet<'tcx, Const<'tcx>>, clauses: InternedSet<'tcx, List>>, - goals: InternedSet<'tcx, List>>, + goal: InternedSet<'tcx, GoalKind<'tcx>>, + goal_list: InternedSet<'tcx, List>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { @@ -159,7 +160,8 @@ fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> { predicates: Default::default(), const_: Default::default(), clauses: Default::default(), - goals: Default::default(), + goal: Default::default(), + goal_list: Default::default(), } } @@ -827,12 +829,9 @@ impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { // Ensure our type representation does not grow #[cfg(target_pointer_width = "64")] - #[allow(dead_code)] - static ASSERT_TY_KIND: () = - [()][!(::std::mem::size_of::>() <= 24) as usize]; + static_assert!(ASSERT_TY_KIND: ::std::mem::size_of::>() <= 24); #[cfg(target_pointer_width = "64")] - #[allow(dead_code)] - static ASSERT_TYS: () = [()][!(::std::mem::size_of::>() <= 32) as usize]; + static_assert!(ASSERT_TYS: ::std::mem::size_of::>() <= 32); let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty); let mk_region = |r| { @@ -1731,9 +1730,9 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option Lift<'tcx> for &'a Goal<'a> { - type Lifted = &'tcx Goal<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Goal<'tcx>> { +impl<'a, 'tcx> Lift<'tcx> for Goal<'a> { + type Lifted = Goal<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { if tcx.interners.arena.in_arena(*self as *const _) { return Some(unsafe { mem::transmute(*self) }); } @@ -2304,6 +2303,12 @@ fn borrow<'a>(&'a self) -> &'a RegionKind { } } +impl<'tcx: 'lcx, 'lcx> Borrow> for Interned<'tcx, GoalKind<'tcx>> { + fn borrow<'a>(&'a self) -> &'a GoalKind<'lcx> { + &self.0 + } +} + impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] { @@ -2419,7 +2424,8 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { direct_interners!('tcx, region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind, - const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx> + const_: mk_const(|c: &Const<'_>| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx>, + goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx> ); macro_rules! slice_interners { @@ -2438,7 +2444,7 @@ macro_rules! slice_interners { type_list: _intern_type_list(Ty), substs: _intern_substs(Kind), clauses: _intern_clauses(Clause), - goals: _intern_goals(Goal) + goal_list: _intern_goals(Goal) ); // This isn't a perfect fit: CanonicalVarInfo slices are always @@ -2818,10 +2824,6 @@ pub fn mk_goals], Goals<'tcx>>>(self, iter: I) -> I::Out iter.intern_with(|xs| self.intern_goals(xs)) } - pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal<'_> { - &self.intern_goals(&[goal])[0] - } - pub fn lint_hir>(self, lint: &'static Lint, hir_id: HirId, diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index c3d41873009..10a90dfc8a8 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -148,7 +148,10 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) { self.add_projection_ty(data); } - &ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + &ty::UnnormalizedProjection(ref data) => { + self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_projection_ty(data); + }, &ty::Opaque(_, substs) => { self.add_flags(TypeFlags::HAS_PROJECTION); diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 684f2b35885..c8e8d0dc84e 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -150,7 +150,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { // Create list of fields in the main structure let mut args: Vec<_> = self.prefix.iter().flat_map(|option_kind| option_kind.map( - |kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx))) + |kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx))) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); @@ -259,8 +259,7 @@ fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceR } pub trait FnTypeExt<'tcx> { - fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) - -> Self; + fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self; fn new(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; @@ -283,8 +282,7 @@ fn adjust_for_abi(&mut self, } impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { - fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) - -> Self { + fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self { let fn_ty = instance.ty(cx.tcx); let sig = ty_fn_sig(cx, fn_ty); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); @@ -292,16 +290,16 @@ fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) } fn new(cx: &CodegenCx<'ll, 'tcx>, - sig: ty::FnSig<'tcx>, - extra_args: &[Ty<'tcx>]) -> Self { + sig: ty::FnSig<'tcx>, + extra_args: &[Ty<'tcx>]) -> Self { FnType::new_internal(cx, sig, extra_args, |ty, _| { ArgType::new(cx.layout_of(ty)) }) } fn new_vtable(cx: &CodegenCx<'ll, 'tcx>, - sig: ty::FnSig<'tcx>, - extra_args: &[Ty<'tcx>]) -> Self { + sig: ty::FnSig<'tcx>, + extra_args: &[Ty<'tcx>]) -> Self { FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| { let mut layout = cx.layout_of(ty); // Don't pass the vtable, it's not an argument of the virtual fn. @@ -338,7 +336,7 @@ fn new_internal( RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::C, - // It's the ABI's job to select this, not us. + // It's the ABI's job to select this, not ours. System => bug!("system abi should be selected elsewhere"), Stdcall => Conv::X86Stdcall, @@ -697,14 +695,13 @@ fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected // by the LLVM verifier. - match scalar.value { - layout::Int(..) if !scalar.is_bool() => { + if let layout::Int(..) = scalar.value { + if !scalar.is_bool() { let range = scalar.valid_range_exclusive(bx.cx); if range.start != range.end { bx.range_metadata(callsite, range); } } - _ => {} } } for arg in &self.args { diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 0beb8a8844c..7c237407c8f 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -33,7 +33,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind let void = llvm::LLVMVoidTypeInContext(llcx); for method in ALLOCATOR_METHODS { - let mut args = Vec::new(); + let mut args = Vec::with_capacity(method.inputs.len()); for ty in method.inputs.iter() { match *ty { AllocatorTy::Layout => { diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 51380db5b23..90ba103ca4c 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -94,9 +94,8 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Currently stack probes seem somewhat incompatible with the address // sanitizer. With asan we're already protected from stack overflow anyway // so we don't really need stack probes regardless. - match cx.sess().opts.debugging_opts.sanitizer { - Some(Sanitizer::Address) => return, - _ => {} + if let Some(Sanitizer::Address) = cx.sess().opts.debugging_opts.sanitizer { + return } // probestack doesn't play nice either with pgo-gen. @@ -138,6 +137,15 @@ pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { target_cpu.as_c_str()); } +/// Sets the `NonLazyBind` LLVM attribute on a given function, +/// assuming the codegen options allow skipping the PLT. +pub fn non_lazy_bind(sess: &Session, llfn: &'ll Value) { + // Don't generate calls through PLT if it's not necessary + if !sess.needs_plt() { + Attribute::NonLazyBind.apply_llfn(Function, llfn); + } +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs( @@ -280,12 +288,14 @@ pub fn provide_extern(providers: &mut Providers) { // `NativeLibrary` internally contains information about // `#[link(wasm_import_module = "...")]` for example. let native_libs = tcx.native_libraries(cnum); - let mut def_id_to_native_lib = FxHashMap(); - for lib in native_libs.iter() { + + let def_id_to_native_lib = native_libs.iter().filter_map(|lib| if let Some(id) = lib.foreign_module { - def_id_to_native_lib.insert(id, lib); + Some((id, lib)) + } else { + None } - } + ).collect::>(); let mut ret = FxHashMap(); for lib in tcx.foreign_modules(cnum).iter() { @@ -296,10 +306,10 @@ pub fn provide_extern(providers: &mut Providers) { Some(s) => s, None => continue, }; - for id in lib.foreign_items.iter() { + ret.extend(lib.foreign_items.iter().map(|id| { assert_eq!(id.krate, cnum); - ret.insert(*id, module.to_string()); - } + (*id, module.to_string()) + })); } Lrc::new(ret) diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 55dc43ec1fb..c814ab4ab67 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -213,8 +213,8 @@ pub fn unsized_info( vtable_ptr.llvm_type(cx)) } _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", - source, - target), + source, + target), } } @@ -340,11 +340,11 @@ pub fn cast_shift_expr_rhs( } fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind, - lhs: &'ll Value, - rhs: &'ll Value, - trunc: F, - zext: G) - -> &'ll Value + lhs: &'ll Value, + rhs: &'ll Value, + trunc: F, + zext: G) + -> &'ll Value where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value, G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value { @@ -363,8 +363,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind, if lhs_sz < rhs_sz { trunc(rhs, lhs_llty) } else if lhs_sz > rhs_sz { - // FIXME (#1877: If shifting by negative - // values becomes not undefined then this is wrong. + // FIXME (#1877: If in the future shifting by negative + // values is no longer undefined then this is wrong. zext(rhs, lhs_llty) } else { rhs @@ -495,10 +495,8 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<' let sig = common::ty_fn_sig(cx, fn_ty); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - let lldecl = match cx.instances.borrow().get(&instance) { - Some(&val) => val, - None => bug!("Instance `{:?}` not already declared", instance) - }; + let lldecl = cx.instances.borrow().get(&instance).cloned().unwrap_or_else(|| + bug!("Instance `{:?}` not already declared", instance)); cx.stats.borrow_mut().n_closures += 1; @@ -566,8 +564,8 @@ fn create_entry_fn( if declare::get_defined_value(cx, "main").is_some() { // FIXME: We should be smart and show a better diagnostic here. cx.sess().struct_span_err(sp, "entry symbol `main` defined multiple times") - .help("did you use #[no_mangle] on `fn main`? Use #[start] instead") - .emit(); + .help("did you use #[no_mangle] on `fn main`? Use #[start] instead") + .emit(); cx.sess().abort_if_errors(); bug!(); } @@ -736,9 +734,9 @@ fn determine_cgu_reuse<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - rx: mpsc::Receiver>) - -> OngoingCodegen { - + rx: mpsc::Receiver>) + -> OngoingCodegen +{ check_for_rustc_errors_attr(tcx); if let Some(true) = tcx.sess.opts.debugging_opts.thinlto { @@ -803,8 +801,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Run the monomorphization collector and partition the collected items into // codegen units. - let codegen_units = - tcx.collect_and_partition_mono_items(LOCAL_CRATE).1; + let codegen_units = tcx.collect_and_partition_mono_items(LOCAL_CRATE).1; let codegen_units = (*codegen_units).clone(); // Force all codegen_unit queries so they are already either red or green @@ -837,12 +834,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .iter() .any(|(_, list)| { use rustc::middle::dependency_format::Linkage; - list.iter().any(|linkage| { - match linkage { - Linkage::Dynamic => true, - _ => false, - } - }) + list.iter().any(|&linkage| linkage == Linkage::Dynamic) }); let allocator_module = if any_dynamic_crate { None @@ -988,7 +980,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>( if mode_string != "lazy" { let message = format!("Unknown codegen-item collection mode '{}'. \ Falling back to 'lazy' mode.", - mode_string); + mode_string); tcx.sess.warn(&message); } @@ -1123,7 +1115,15 @@ pub fn new(tcx: TyCtxt) -> CrateInfo { info.load_wasm_imports(tcx, LOCAL_CRATE); } - for &cnum in tcx.crates().iter() { + let crates = tcx.crates(); + + let n_crates = crates.len(); + info.native_libraries.reserve(n_crates); + info.crate_name.reserve(n_crates); + info.used_crate_source.reserve(n_crates); + info.missing_lang_items.reserve(n_crates); + + for &cnum in crates.iter() { info.native_libraries.insert(cnum, tcx.native_libraries(cnum)); info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string()); info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum)); @@ -1165,11 +1165,12 @@ pub fn new(tcx: TyCtxt) -> CrateInfo { } fn load_wasm_imports(&mut self, tcx: TyCtxt, cnum: CrateNum) { - for (&id, module) in tcx.wasm_import_module_map(cnum).iter() { + self.wasm_imports.extend(tcx.wasm_import_module_map(cnum).iter().map(|(&id, module)| { let instance = Instance::mono(tcx, id); let import_name = tcx.symbol_name(instance); - self.wasm_imports.insert(import_name.to_string(), module.clone()); - } + + (import_name.to_string(), module.clone()) + })); } } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 77de88997e4..df9c4e874bd 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -110,10 +110,10 @@ fn count_insn(&self, category: &str) { } if self.cx.sess().count_llvm_insns() { *self.cx.stats - .borrow_mut() - .llvm_insns - .entry(category.to_string()) - .or_insert(0) += 1; + .borrow_mut() + .llvm_insns + .entry(category.to_string()) + .or_insert(0) += 1; } } @@ -735,9 +735,9 @@ pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) - } pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, - inputs: &[&'ll Value], output: &'ll Type, - volatile: bool, alignstack: bool, - dia: AsmDialect) -> Option<&'ll Value> { + inputs: &[&'ll Value], output: &'ll Type, + volatile: bool, alignstack: bool, + dia: AsmDialect) -> Option<&'ll Value> { self.count_insn("inlineasm"); let volatile = if volatile { llvm::True } @@ -1093,7 +1093,7 @@ pub fn atomic_cmpxchg( ) -> &'ll Value { unsafe { llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src, - order, failure_order, weak) + order, failure_order, weak) } } pub fn atomic_rmw( @@ -1194,7 +1194,7 @@ fn check_call<'b>(&self, }) .collect(); - return Cow::Owned(casted_args); + Cow::Owned(casted_args) } pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) { diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 53bb02ddd99..c08937fa9b9 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -336,16 +336,13 @@ pub fn langcall(tcx: TyCtxt, msg: &str, li: LangItem) -> DefId { - match tcx.lang_items().require(li) { - Ok(id) => id, - Err(s) => { - let msg = format!("{} {}", msg, s); - match span { - Some(span) => tcx.sess.span_fatal(span, &msg[..]), - None => tcx.sess.fatal(&msg[..]), - } + tcx.lang_items().require(li).unwrap_or_else(|s| { + let msg = format!("{} {}", msg, s); + match span { + Some(span) => tcx.sess.span_fatal(span, &msg[..]), + None => tcx.sess.fatal(&msg[..]), } - } + }) } // To avoid UB from LLVM, these two functions mask RHS with an diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 522de2f15e0..9228870bf3a 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -124,7 +124,7 @@ pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value { assert!(!defined_in_current_codegen_unit, "consts::get_static() should always hit the cache for \ statics defined in the same CGU, but did not for `{:?}`", - def_id); + def_id); let ty = instance.ty(cx.tcx); let sym = cx.tcx.symbol_name(instance).as_str(); @@ -249,14 +249,13 @@ fn check_and_apply_linkage( // extern "C" fn() from being non-null, so we can't just declare a // static and call it a day. Some linkages (like weak) will make it such // that the static actually has a null value. - let llty2 = match ty.sty { - ty::RawPtr(ref mt) => cx.layout_of(mt.ty).llvm_type(cx), - _ => { - if span.is_some() { - cx.sess().span_fatal(span.unwrap(), "must have type `*const T` or `*mut T`") - } else { - bug!("must have type `*const T` or `*mut T`") - } + let llty2 = if let ty::RawPtr(ref mt) = ty.sty { + cx.layout_of(mt.ty).llvm_type(cx) + } else { + if let Some(span) = span { + cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`") + } else { + bug!("must have type `*const T` or `*mut T`") } }; unsafe { @@ -273,9 +272,9 @@ fn check_and_apply_linkage( let mut real_name = "_rust_extern_with_linkage_".to_string(); real_name.push_str(&sym); let g2 = declare::define_global(cx, &real_name, llty).unwrap_or_else(||{ - if span.is_some() { + if let Some(span) = span { cx.sess().span_fatal( - span.unwrap(), + span, &format!("symbol `{}` is already defined", &sym) ) } else { diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 9547f4a190e..578018c7adc 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -59,8 +59,8 @@ pub struct CodegenCx<'a, 'tcx: 'a> { /// Cache instances of monomorphic and polymorphic items pub instances: RefCell, &'a Value>>, /// Cache generated vtables - pub vtables: RefCell, - Option>), &'a Value>>, + pub vtables: RefCell, Option>), + &'a Value>>, /// Cache of constant strings, pub const_cstr_cache: RefCell>, @@ -208,14 +208,21 @@ pub unsafe fn create_module( llvm::LLVMRustSetModulePIELevel(llmod); } + // If skipping the PLT is enabled, we need to add some module metadata + // to ensure intrinsic calls don't use it. + if !sess.needs_plt() { + let avoid_plt = "RtLibUseGOT\0".as_ptr() as *const _; + llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1); + } + llmod } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - codegen_unit: Arc>, - llvm_module: &'a ::ModuleLlvm) - -> CodegenCx<'a, 'tcx> { + codegen_unit: Arc>, + llvm_module: &'a ::ModuleLlvm) + -> CodegenCx<'a, 'tcx> { // An interesting part of Windows which MSVC forces our hand on (and // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` // attributes in LLVM IR as well as native dependencies (in C these @@ -270,8 +277,8 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { let dbg_cx = if tcx.sess.opts.debuginfo != DebugInfo::None { let dctx = debuginfo::CrateDebugContext::new(llmod); debuginfo::metadata::compile_unit_metadata(tcx, - &codegen_unit.name().as_str(), - &dctx); + &codegen_unit.name().as_str(), + &dctx); Some(dctx) } else { None @@ -318,10 +325,8 @@ pub fn get_intrinsic(&self, key: &str) -> &'b Value { if let Some(v) = self.intrinsics.borrow().get(key).cloned() { return v; } - match declare_intrinsic(self, key) { - Some(v) => return v, - None => bug!("unknown intrinsic '{}'", key) - } + + declare_intrinsic(self, key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key)) } /// Generate a new symbol name with the given prefix. This symbol name must @@ -465,9 +470,10 @@ impl LayoutOf for &'a CodegenCx<'ll, 'tcx> { fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout { self.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)) - .unwrap_or_else(|e| match e { - LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()), - _ => bug!("failed to get layout for `{}`: {}", ty, e) + .unwrap_or_else(|e| if let LayoutError::SizeOverflow(_) = e { + self.sess().fatal(&e.to_string()) + } else { + bug!("failed to get layout for `{}`: {}", ty, e) }) } } @@ -772,5 +778,6 @@ macro_rules! mk_struct { ifn!("llvm.dbg.declare", fn(Type::metadata(cx), Type::metadata(cx)) -> void); ifn!("llvm.dbg.value", fn(Type::metadata(cx), t_i64, Type::metadata(cx)) -> void); } - return None; + + None } diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index 7141c9ece89..26969e24f08 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -104,6 +104,8 @@ fn declare_raw_fn( attributes::unwind(llfn, false); } + attributes::non_lazy_bind(cx.sess(), llfn); + llfn } diff --git a/src/librustc_codegen_llvm/diagnostics.rs b/src/librustc_codegen_llvm/diagnostics.rs index 242b7a1a119..5721938c9c0 100644 --- a/src/librustc_codegen_llvm/diagnostics.rs +++ b/src/librustc_codegen_llvm/diagnostics.rs @@ -69,4 +69,15 @@ fn main() { ``` "##, +E0669: r##" +Cannot convert inline assembly operand to a single LLVM value. + +This error usually happens when trying to pass in a value to an input inline +assembly operand that is actually a pair of values. In particular, this can +happen when trying to pass in a slice, for instance a `&str`. In Rust, these +values are represented internally as a pair of values, the pointer and its +length. When passed as an input operand, this pair of values can not be +coerced into a register and thus we must fail with an error. +"##, + } diff --git a/src/librustc_codegen_llvm/glue.rs b/src/librustc_codegen_llvm/glue.rs index ff33cec0437..842bdf3cb49 100644 --- a/src/librustc_codegen_llvm/glue.rs +++ b/src/librustc_codegen_llvm/glue.rs @@ -97,8 +97,8 @@ pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Opt C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64) } _ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align), - sized_align, - unsized_align) + sized_align, + unsized_align) }; // Issue #27023: must add any necessary padding to `size` diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 5ec934ebd06..272196afa6f 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -115,8 +115,8 @@ pub fn codegen_intrinsic_call( let llval = match name { _ if simple.is_some() => { bx.call(simple.unwrap(), - &args.iter().map(|arg| arg.immediate()).collect::>(), - None) + &args.iter().map(|arg| arg.immediate()).collect::>(), + None) } "unreachable" => { return; @@ -373,7 +373,6 @@ pub fn codegen_intrinsic_call( return; } } - }, "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { let sty = &arg_tys[0].sty; @@ -540,10 +539,9 @@ pub fn codegen_intrinsic_call( } _ => { - let intr = match Intrinsic::find(&name) { - Some(intr) => intr, - None => bug!("unknown intrinsic '{}'", name), - }; + let intr = Intrinsic::find(&name).unwrap_or_else(|| + bug!("unknown intrinsic '{}'", name)); + fn one(x: Vec) -> T { assert_eq!(x.len(), 1); x.into_iter().next().unwrap() @@ -822,8 +820,7 @@ fn codegen_msvc_try( let i64p = Type::i64(cx).ptr_to(); let ptr_align = bx.tcx().data_layout.pointer_align; let slot = bx.alloca(i64p, "slot", ptr_align); - bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), - None); + bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); normal.ret(C_i32(cx, 0)); @@ -911,8 +908,7 @@ fn codegen_gnu_try( // being thrown. The second value is a "selector" indicating which of // the landing pad clauses the exception's type had been matched to. // rust_try ignores the selector. - let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], - false); + let lpad_ty = Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false); let vals = catch.landing_pad(lpad_ty, bx.cx.eh_personality(), 1); catch.add_clause(vals, C_null(Type::i8p(cx))); let ptr = catch.extract_value(vals, 0); @@ -976,7 +972,7 @@ fn get_rust_try_fn<'ll, 'tcx>( let output = tcx.types.i32; let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen); cx.rust_try_fn.set(Some(rust_try)); - return rust_try + rust_try } fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { @@ -1000,11 +996,11 @@ macro_rules! emit_error { ($msg: tt, $($fmt: tt)*) => { span_invalid_monomorphization_error( bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", - $msg), + &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), name, $($fmt)*)); } } + macro_rules! return_error { ($($fmt: tt)*) => { { @@ -1021,14 +1017,13 @@ macro_rules! require { } }; } + macro_rules! require_simd { ($ty: expr, $position: expr) => { require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) } } - - let tcx = bx.tcx(); let sig = tcx.normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), @@ -1075,11 +1070,8 @@ macro_rules! require_simd { } if name.starts_with("simd_shuffle") { - let n: usize = match name["simd_shuffle".len()..].parse() { - Ok(n) => n, - Err(_) => span_bug!(span, - "bad `simd_shuffle` instruction only caught in codegen?") - }; + let n: usize = name["simd_shuffle".len()..].parse().unwrap_or_else(|_| + span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")); require_simd!(ret_ty, "return"); @@ -1121,8 +1113,8 @@ macro_rules! require_simd { }; return Ok(bx.shuffle_vector(args[0].immediate(), - args[1].immediate(), - C_vector(&indices))) + args[1].immediate(), + C_vector(&indices))) } if name == "simd_insert" { @@ -1130,8 +1122,8 @@ macro_rules! require_simd { "expected inserted type `{}` (element of input `{}`), found `{}`", in_elem, in_ty, arg_tys[2]); return Ok(bx.insert_element(args[0].immediate(), - args[2].immediate(), - args[1].immediate())) + args[2].immediate(), + args[1].immediate())) } if name == "simd_extract" { require!(ret_ty == in_elem, @@ -1150,9 +1142,7 @@ macro_rules! require_simd { ); match m_elem_ty.sty { ty::Int(_) => {}, - _ => { - return_error!("mask element type is `{}`, expected `i_`", m_elem_ty); - } + _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty) } // truncate the mask to a vector of i1s let i1 = Type::i1(bx.cx); @@ -1177,8 +1167,7 @@ macro_rules! emit_error { ($msg: tt, $($fmt: tt)*) => { span_invalid_monomorphization_error( bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", - $msg), + &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), name, $($fmt)*)); } } @@ -1223,63 +1212,53 @@ macro_rules! return_error { &args.iter().map(|arg| arg.immediate()).collect::>(), None); unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) }; - return Ok(c); - } - - if name == "simd_fsqrt" { - return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fsin" { - return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fcos" { - return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fabs" { - return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_floor" { - return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_ceil" { - return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fexp" { - return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fexp2" { - return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_flog10" { - return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_flog2" { - return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_flog" { - return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args); + Ok(c) } - if name == "simd_fpowi" { - return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fpow" { - return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args); - } - - if name == "simd_fma" { - return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args); + match name { + "simd_fsqrt" => { + return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fsin" => { + return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fcos" => { + return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fabs" => { + return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args); + } + "simd_floor" => { + return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args); + } + "simd_ceil" => { + return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fexp" => { + return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fexp2" => { + return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args); + } + "simd_flog10" => { + return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args); + } + "simd_flog2" => { + return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args); + } + "simd_flog" => { + return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fpowi" => { + return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fpow" => { + return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args); + } + "simd_fma" => { + return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args); + } + _ => { /* fallthrough */ } } // FIXME: use: @@ -1312,7 +1291,7 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize, } - if name == "simd_gather" { + if name == "simd_gather" { // simd_gather(values: , pointers: , // mask: ) -> // * N: number of elements in the input vectors @@ -1360,7 +1339,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { // to the element type of the first argument let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty { ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)), - non_ptr(arg_tys[1].simd_type(tcx))), + non_ptr(arg_tys[1].simd_type(tcx))), _ => { require!(false, "expected element type `{}` of second argument `{}` \ to be a pointer to the element type `{}` of the first \ @@ -1371,7 +1350,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { } }; assert!(pointer_count > 0); - assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx))); + assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx))); assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); // The element type of the third argument must be a signed integer type of any width: @@ -1414,7 +1393,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { return Ok(v); } - if name == "simd_scatter" { + if name == "simd_scatter" { // simd_scatter(values: , pointers: , // mask: ) -> () // * N: number of elements in the input vectors @@ -1468,7 +1447,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { } }; assert!(pointer_count > 0); - assert!(pointer_count - 1 == ptr_count(arg_tys[0].simd_type(tcx))); + assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx))); assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); // The element type of the third argument must be a signed integer type of any width: @@ -1570,7 +1549,6 @@ macro_rules! arith_red { ) } } - }; Ok(bx.$float_reduce(acc, args[0].immediate())) } @@ -1750,9 +1728,9 @@ macro_rules! arith { _ => {}, } require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + "unsupported operation on `{}` with element `{}`", + in_ty, + in_elem) })* } } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 71d739222b6..63a8ab077e5 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -306,7 +306,7 @@ fn into_compiled_module(self, }; let bytecode_compressed = if emit_bc_compressed { Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)) - .with_extension(RLIB_BYTECODE_EXTENSION)) + .with_extension(RLIB_BYTECODE_EXTENSION)) } else { None }; diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 8485db4210c..c9f51efdc50 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -122,6 +122,7 @@ pub enum Attribute { SanitizeThread = 20, SanitizeAddress = 21, SanitizeMemory = 22, + NonLazyBind = 23, } /// LLVMIntPredicate diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 9e8ff204703..8456cf2f480 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -52,8 +52,9 @@ fn require_inited() { } unsafe fn configure_llvm(sess: &Session) { - let mut llvm_c_strs = Vec::new(); - let mut llvm_args = Vec::new(); + let n_args = sess.opts.cg.llvm_args.len(); + let mut llvm_c_strs = Vec::with_capacity(n_args + 1); + let mut llvm_args = Vec::with_capacity(n_args + 1); { let mut add = |arg: &str| { diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index a4526a53769..7752465d885 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -63,7 +63,7 @@ fn get_dylib_metadata(&self, let of = ObjectFile::new(mb) .map(|of| OwningRef::new(box of)) .ok_or_else(|| format!("provided path not an object file: '{}'", - filename.display()))?; + filename.display()))?; let buf = of.try_map(|of| search_meta_section(of, target, filename))?; Ok(rustc_erase_owner!(buf)) } diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index c3e3785a724..a0d6cc46295 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -151,9 +151,9 @@ fn visit_terminator_kind(&mut self, } fn visit_place(&mut self, - place: &mir::Place<'tcx>, - context: PlaceContext<'tcx>, - location: Location) { + place: &mir::Place<'tcx>, + context: PlaceContext<'tcx>, + location: Location) { debug!("visit_place(place={:?}, context={:?})", place, context); let cx = self.fx.cx; diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index db95b46c38e..5be176f75c9 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -49,9 +49,9 @@ pub fn codegen_block(&mut self, bb: mir::BasicBlock) { } fn codegen_terminator(&mut self, - mut bx: Builder<'a, 'll, 'tcx>, - bb: mir::BasicBlock, - terminator: &mir::Terminator<'tcx>) + mut bx: Builder<'a, 'll, 'tcx>, + bb: mir::BasicBlock, + terminator: &mir::Terminator<'tcx>) { debug!("codegen_terminator: {:?}", terminator); diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index 6bd41bfe16f..93be0074f6e 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -15,6 +15,7 @@ use super::FunctionCx; use super::LocalRef; +use super::OperandValue; impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_statement(&mut self, @@ -82,14 +83,27 @@ pub fn codegen_statement(&mut self, self.codegen_place(&bx, output) }).collect(); - let input_vals = inputs.iter().map(|input| { - self.codegen_operand(&bx, input).immediate() - }).collect(); + let input_vals = inputs.iter() + .try_fold(Vec::with_capacity(inputs.len()), |mut acc, input| { + let op = self.codegen_operand(&bx, input); + if let OperandValue::Immediate(_) = op.val { + acc.push(op.immediate()); + Ok(acc) + } else { + Err(op) + } + }); - let res = asm::codegen_inline_asm(&bx, asm, outputs, input_vals); - if !res { - span_err!(bx.sess(), statement.source_info.span, E0668, - "malformed inline assembly"); + if input_vals.is_err() { + span_err!(bx.sess(), statement.source_info.span, E0669, + "invalid value for constraint in inline assembly"); + } else { + let input_vals = input_vals.unwrap(); + let res = asm::codegen_inline_asm(&bx, asm, outputs, input_vals); + if !res { + span_err!(bx.sess(), statement.source_info.span, E0668, + "malformed inline assembly"); + } } bx } diff --git a/src/librustc_codegen_llvm/mono_item.rs b/src/librustc_codegen_llvm/mono_item.rs index a8502e92447..dab9b147cc0 100644 --- a/src/librustc_codegen_llvm/mono_item.rs +++ b/src/librustc_codegen_llvm/mono_item.rs @@ -108,8 +108,8 @@ fn to_raw_string(&self) -> String { match *self.as_mono_item() { MonoItem::Fn(instance) => { format!("Fn({:?}, {})", - instance.def, - instance.substs.as_ptr() as usize) + instance.def, + instance.substs.as_ptr() as usize) } MonoItem::Static(id) => { format!("Static({:?})", id) diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 765708aeafd..03ded64e642 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -65,13 +65,12 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let mut name = String::with_capacity(32); let printer = DefPathBasedNames::new(cx.tcx, true, true); printer.push_type_name(layout.ty, &mut name); - match (&layout.ty.sty, &layout.variants) { - (&ty::Adt(def, _), &layout::Variants::Single { index }) => { - if def.is_enum() && !def.variants.is_empty() { - write!(&mut name, "::{}", def.variants[index].name).unwrap(); - } + if let (&ty::Adt(def, _), &layout::Variants::Single { index }) + = (&layout.ty.sty, &layout.variants) + { + if def.is_enum() && !def.variants.is_empty() { + write!(&mut name, "::{}", def.variants[index].name).unwrap(); } - _ => {} } Some(name) } @@ -132,7 +131,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \ effective_field_align: {}", - i, field, offset, target_offset, effective_field_align.abi()); + i, field, offset, target_offset, effective_field_align.abi()); assert!(target_offset >= offset); let padding = target_offset - offset; let padding_align = prev_effective_align.min(effective_field_align); @@ -155,7 +154,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}", padding, offset, layout.size); result.push(Type::padding_filler(cx, padding, padding_align)); - assert!(result.len() == 1 + field_count * 2); + assert_eq!(result.len(), 1 + field_count * 2); } else { debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size); diff --git a/src/librustc_codegen_llvm/value.rs b/src/librustc_codegen_llvm/value.rs index 3328948c295..4bf5b09baa6 100644 --- a/src/librustc_codegen_llvm/value.rs +++ b/src/librustc_codegen_llvm/value.rs @@ -34,6 +34,6 @@ impl fmt::Debug for Value { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&llvm::build_string(|s| unsafe { llvm::LLVMRustWriteValueToString(self, s); - }).expect("nun-UTF8 value description from LLVM")) + }).expect("non-UTF8 value description from LLVM")) } } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 4405c0aef90..0514bd20c98 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -21,7 +21,6 @@ #![feature(box_syntax)] #![cfg_attr(unix, feature(libc))] #![feature(nll)] -#![feature(option_replace)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 2799f2cc81f..870eeadc081 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -76,9 +76,9 @@ pub enum StringPart { } impl StringPart { - pub fn content(&self) -> String { + pub fn content(&self) -> &str { match self { - &StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s.to_owned() + &StringPart::Normal(ref s) | & StringPart::Highlighted(ref s) => s } } } @@ -398,7 +398,7 @@ pub fn get_code(&self) -> Option { } pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.to_owned()).collect::() + self.message.iter().map(|i| i.0.as_str()).collect::() } pub fn styled_message(&self) -> &Vec<(String, Style)> { @@ -448,7 +448,7 @@ fn sub_with_highlights(&mut self, impl SubDiagnostic { pub fn message(&self) -> String { - self.message.iter().map(|i| i.0.to_owned()).collect::() + self.message.iter().map(|i| i.0.as_str()).collect::() } pub fn styled_message(&self) -> &Vec<(String, Style)> { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index ae178888b6a..ec3c310c63c 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -59,15 +59,17 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { } let t = cx.tables.expr_ty(&expr); - let ty_warned = match t.sty { - ty::Tuple(ref tys) if tys.is_empty() => return, - ty::Never => return, + // FIXME(varkor): replace with `t.is_unit() || t.conservative_is_uninhabited()`. + let type_permits_no_use = match t.sty { + ty::Tuple(ref tys) if tys.is_empty() => true, + ty::Never => true, ty::Adt(def, _) => { if def.variants.is_empty() { - return; + true + } else { + check_must_use(cx, def.did, s.span, "") } - check_must_use(cx, def.did, s.span, "") - }, + } _ => false, }; @@ -95,7 +97,12 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { if let Some(def) = maybe_def { let def_id = def.def_id(); fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + } else if type_permits_no_use { + // We don't warn about unused unit or uninhabited types. + // (See https://github.com/rust-lang/rust/issues/43806 for details.) + return; } + let must_use_op = match expr.node { // Hardcoding operators here seemed more expedient than the // refactoring that would be needed to look up the `#[must_use]` @@ -139,7 +146,7 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { op_warned = true; } - if !(ty_warned || fn_warned || op_warned) { + if !(type_permits_no_use || fn_warned || op_warned) { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } @@ -233,7 +240,7 @@ fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) { .find(|&&(builtin, ty, _)| name == builtin && ty == AttributeType::CrateLevel) .is_some(); - // Has a plugin registered this attribute as one which must be used at + // Has a plugin registered this attribute as one that must be used at // the crate level? let plugin_crate = plugin_attributes.iter() .find(|&&(ref x, t)| name == &**x && AttributeType::CrateLevel == t) diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 693cfea3c95..ea62694f8be 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -68,6 +68,7 @@ enum GroupedMoveError<'tcx> { enum BorrowedContentSource { Arc, Rc, + DerefRawPointer, Other, } @@ -76,6 +77,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { BorrowedContentSource::Arc => write!(f, "an `Arc`"), BorrowedContentSource::Rc => write!(f, "an `Rc`"), + BorrowedContentSource::DerefRawPointer => write!(f, "dereference of raw pointer"), BorrowedContentSource::Other => write!(f, "borrowed content"), } } @@ -279,6 +281,7 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) { self.prefixes(&original_path, PrefixSet::All) .any(|p| p.is_upvar_field_projection(self.mir, &self.infcx.tcx) .is_some()); + debug!("report: ty={:?}", ty); match ty.sty { ty::Array(..) | ty::Slice(..) => self.infcx.tcx.cannot_move_out_of_interior_noncopy( @@ -582,6 +585,18 @@ fn borrowed_content_source(&self, place: &Place<'tcx>) -> BorrowedContentSource } } + // If we didn't find an `Arc` or an `Rc`, then check specifically for + // a dereference of a place that has the type of a raw pointer. + // We can't use `place.ty(..).to_ty(..)` here as that strips away the raw pointer. + if let Place::Projection(box Projection { + base, + elem: ProjectionElem::Deref, + }) = place { + if base.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx).is_unsafe_ptr() { + return BorrowedContentSource::DerefRawPointer; + } + } + BorrowedContentSource::Other } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index e55469436ab..307112f8ba1 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -13,8 +13,10 @@ use borrow_check::nll::region_infer::Cause; use borrow_check::{Context, MirBorrowckCtxt, WriteKind}; use rustc::ty::{self, Region, TyCtxt}; -use rustc::mir::{FakeReadCause, Local, Location, Mir, Operand}; -use rustc::mir::{Place, StatementKind, TerminatorKind}; +use rustc::mir::{ + CastKind, FakeReadCause, Local, Location, Mir, Operand, Place, Projection, ProjectionElem, + Rvalue, Statement, StatementKind, TerminatorKind +}; use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; @@ -34,6 +36,7 @@ pub(in borrow_check) enum BorrowExplanation<'tcx> { #[derive(Clone, Copy)] pub(in borrow_check) enum LaterUseKind { + TraitCapture, ClosureCapture, Call, FakeLetRead, @@ -51,6 +54,7 @@ pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx>( match *self { BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => { let message = match later_use_kind { + LaterUseKind::TraitCapture => "borrow later captured here by trait object", LaterUseKind::ClosureCapture => "borrow later captured here by closure", LaterUseKind::Call => "borrow later used by call", LaterUseKind::FakeLetRead => "borrow later stored here", @@ -60,9 +64,10 @@ pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx>( }, BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => { let message = match later_use_kind { - LaterUseKind::ClosureCapture => { - "borrow captured here by closure, in later iteration of loop" - }, + LaterUseKind::TraitCapture => + "borrow captured here by trait object, in later iteration of loop", + LaterUseKind::ClosureCapture => + "borrow captured here by closure, in later iteration of loop", LaterUseKind::Call => "borrow used by call, in later iteration of loop", LaterUseKind::FakeLetRead => "borrow later stored here", LaterUseKind::Other => "borrow used here, in later iteration of loop", @@ -200,13 +205,13 @@ pub(in borrow_check) fn explain_why_borrow_contains_point( .or_else(|| self.borrow_spans(span, location)); if self.is_borrow_location_in_loop(context.loc) { - let later_use = self.later_use_kind(spans, location); + let later_use = self.later_use_kind(borrow, spans, location); BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1) } else { // Check if the location represents a `FakeRead`, and adapt the error // message to the `FakeReadCause` it is from: in particular, // the ones inserted in optimized `let var = ` patterns. - let later_use = self.later_use_kind(spans, location); + let later_use = self.later_use_kind(borrow, spans, location); BorrowExplanation::UsedLater(later_use.0, later_use.1) } } @@ -316,42 +321,184 @@ fn is_borrow_location_in_loop( false } - fn later_use_kind(&self, use_spans: UseSpans, location: Location) -> (LaterUseKind, Span) { - use self::LaterUseKind::*; - - let block = &self.mir.basic_blocks()[location.block]; + /// Determine how the borrow was later used. + fn later_use_kind( + &self, + borrow: &BorrowData<'tcx>, + use_spans: UseSpans, + location: Location + ) -> (LaterUseKind, Span) { match use_spans { - UseSpans::ClosureUse { var_span, .. } => (LaterUseKind::ClosureCapture, var_span), + UseSpans::ClosureUse { var_span, .. } => { + // Used in a closure. + (LaterUseKind::ClosureCapture, var_span) + }, UseSpans::OtherUse(span) => { - (if let Some(stmt) = block.statements.get(location.statement_index) { - match stmt.kind { - StatementKind::FakeRead(FakeReadCause::ForLet, _) => FakeLetRead, - _ => Other, + let block = &self.mir.basic_blocks()[location.block]; + + let kind = if let Some(&Statement { + kind: StatementKind::FakeRead(FakeReadCause::ForLet, _), + .. + }) = block.statements.get(location.statement_index) { + LaterUseKind::FakeLetRead + } else if self.was_captured_by_trait_object(borrow) { + LaterUseKind::TraitCapture + } else if location.statement_index == block.statements.len() { + if let TerminatorKind::Call { + ref func, from_hir_call: true, .. + } = block.terminator().kind { + // Just point to the function, to reduce the chance of overlapping spans. + let function_span = match func { + Operand::Constant(c) => c.span, + Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => { + let local_decl = &self.mir.local_decls[*l]; + if local_decl.name.is_none() { + local_decl.source_info.span + } else { + span + } + }, + _ => span, + }; + return (LaterUseKind::Call, function_span); + } else { + LaterUseKind::Other } } else { - assert_eq!(location.statement_index, block.statements.len()); - match block.terminator().kind { - TerminatorKind::Call { ref func, from_hir_call: true, .. } => { - // Just point to the function, to reduce the chance - // of overlapping spans. - let function_span = match func { - Operand::Constant(c) => c.span, - Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => { - let local_decl = &self.mir.local_decls[*l]; - if local_decl.name.is_none() { - local_decl.source_info.span - } else { - span - } - }, - _ => span, - }; - return (Call, function_span); + LaterUseKind::Other + }; + + (kind, span) + } + } + } + + /// Check if a borrowed value was captured by a trait object. We do this by + /// looking forward in the MIR from the reserve location and checking if we see + /// a unsized cast to a trait object on our data. + fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool { + // Start at the reserve location, find the place that we want to see cast to a trait object. + let location = borrow.reserve_location; + let block = &self.mir[location.block]; + let stmt = block.statements.get(location.statement_index); + debug!("was_captured_by_trait_object: location={:?} stmt={:?}", location, stmt); + + // We make a `queue` vector that has the locations we want to visit. As of writing, this + // will only ever have one item at any given time, but by using a vector, we can pop from + // it which simplifies the termination logic. + let mut queue = vec![location]; + let mut target = if let Some(&Statement { + kind: StatementKind::Assign(Place::Local(local), _), + .. + }) = stmt { + local + } else { + return false; + }; + + debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue); + while let Some(current_location) = queue.pop() { + debug!("was_captured_by_trait: target={:?}", target); + let block = &self.mir[current_location.block]; + // We need to check the current location to find out if it is a terminator. + let is_terminator = current_location.statement_index == block.statements.len(); + if !is_terminator { + let stmt = &block.statements[current_location.statement_index]; + debug!("was_captured_by_trait_object: stmt={:?}", stmt); + + // The only kind of statement that we care about is assignments... + if let StatementKind::Assign( + place, + box rvalue, + ) = &stmt.kind { + let into = match place { + Place::Local(into) => into, + Place::Projection(box Projection { + base: Place::Local(into), + elem: ProjectionElem::Deref, + }) => into, + _ => { + // Continue at the next location. + queue.push(current_location.successor_within_block()); + continue; }, - _ => Other, + }; + + match rvalue { + // If we see a use, we should check whether it is our data, and if so + // update the place that we're looking for to that new place. + Rvalue::Use(operand) => match operand { + Operand::Copy(Place::Local(from)) | + Operand::Move(Place::Local(from)) if *from == target => { + target = *into; + }, + _ => {}, + }, + // If we see a unsized cast, then if it is our data we should check + // whether it is being cast to a trait object. + Rvalue::Cast(CastKind::Unsize, operand, ty) => match operand { + Operand::Copy(Place::Local(from)) | + Operand::Move(Place::Local(from)) if *from == target => { + debug!("was_captured_by_trait_object: ty={:?}", ty); + // Check the type for a trait object. + match ty.sty { + // `&dyn Trait` + ty::TyKind::Ref(_, ty, _) if ty.is_trait() => return true, + // `Box` + _ if ty.is_box() && ty.boxed_ty().is_trait() => + return true, + // `dyn Trait` + _ if ty.is_trait() => return true, + // Anything else. + _ => return false, + } + }, + _ => return false, + }, + _ => {}, } - }, span) + } + + // Continue at the next location. + queue.push(current_location.successor_within_block()); + } else { + // The only thing we need to do for terminators is progress to the next block. + let terminator = block.terminator(); + debug!("was_captured_by_trait_object: terminator={:?}", terminator); + + match &terminator.kind { + TerminatorKind::Call { + destination: Some((Place::Local(dest), block)), + args, + .. + } => { + debug!( + "was_captured_by_trait_object: target={:?} dest={:?} args={:?}", + target, dest, args + ); + // Check if one of the arguments to this function is the target place. + let found_target = args.iter().any(|arg| { + if let Operand::Move(Place::Local(potential)) = arg { + *potential == target + } else { + false + } + }); + + // If it is, follow this to the next block and update the target. + if found_target { + target = *dest; + queue.push(block.start_location()); + } + }, + _ => {}, + } } + + debug!("was_captured_by_trait: queue={:?}", queue); } + + // We didn't find anything and ran out of locations to check. + false } } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 039a92cee2c..c72a5894b6a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -11,7 +11,6 @@ //! Functions concerning immediate values and operands, and reading from operands. //! All high-level functions to read from memory work on operands as sources. -use std::hash::{Hash, Hasher}; use std::convert::TryInto; use rustc::{mir, ty}; @@ -290,7 +289,7 @@ pub fn to_immediate(self) -> Value } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct OpTy<'tcx, Tag=()> { crate op: Operand, // ideally we'd make this private, but const_prop needs this pub layout: TyLayout<'tcx>, @@ -324,26 +323,6 @@ fn from(val: ValTy<'tcx, Tag>) -> Self { } } -// Validation needs to hash OpTy, but we cannot hash Layout -- so we just hash the type -impl<'tcx, Tag> Hash for OpTy<'tcx, Tag> - where Tag: Hash -{ - fn hash(&self, state: &mut H) { - self.op.hash(state); - self.layout.ty.hash(state); - } -} -impl<'tcx, Tag> PartialEq for OpTy<'tcx, Tag> - where Tag: PartialEq -{ - fn eq(&self, other: &Self) -> bool { - self.op == other.op && self.layout.ty == other.layout.ty - } -} -impl<'tcx, Tag> Eq for OpTy<'tcx, Tag> - where Tag: Eq -{} - impl<'tcx, Tag> OpTy<'tcx, Tag> { #[inline] diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 96eb6916322..6b28fd09174 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -874,7 +874,7 @@ pub fn scalar(cx: C, scalar: Scalar) -> Self { /// to those obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e. discriminants) and fat pointers. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct TyLayout<'a, Ty> { pub ty: Ty, pub details: &'a LayoutDetails diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 3f1e8ee5528..9c0f945326d 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -576,6 +576,9 @@ pub struct TargetOptions { /// the functions in the executable are not randomized and can be used /// during an exploit of a vulnerability in any code. pub position_independent_executables: bool, + /// Determines if the target always requires using the PLT for indirect + /// library calls or not. This controls the default value of the `-Z plt` flag. + pub needs_plt: bool, /// Either partial, full, or off. Full RELRO makes the dynamic linker /// resolve all symbols at startup and marks the GOT read-only before /// starting the program, preventing overwriting the GOT. @@ -720,6 +723,7 @@ fn default() -> TargetOptions { has_rpath: false, no_default_libraries: true, position_independent_executables: false, + needs_plt: false, relro_level: RelroLevel::None, pre_link_objects_exe: Vec::new(), pre_link_objects_exe_crt: Vec::new(), @@ -1009,6 +1013,7 @@ macro_rules! key { key!(has_rpath, bool); key!(no_default_libraries, bool); key!(position_independent_executables, bool); + key!(needs_plt, bool); try!(key!(relro_level, RelroLevel)); key!(archive_format); key!(allow_asm, bool); @@ -1217,6 +1222,7 @@ macro_rules! target_option_val { target_option_val!(has_rpath); target_option_val!(no_default_libraries); target_option_val!(position_independent_executables); + target_option_val!(needs_plt); target_option_val!(relro_level); target_option_val!(archive_format); target_option_val!(allow_asm); diff --git a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs index 72b5bd27c7d..fd61067ba51 100644 --- a/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs +++ b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs @@ -17,6 +17,9 @@ pub fn target() -> TargetResult { base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string()); base.stack_probes = true; base.has_elf_tls = false; + // BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI + // breaks code gen. See LLVM bug 36743 + base.needs_plt = true; Ok(Target { llvm_target: "x86_64-unknown-linux-gnux32".to_string(), diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index cd21ee601a7..16f0f11757a 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -16,5 +16,5 @@ rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -chalk-engine = { version = "0.7.0", default-features=false } +chalk-engine = { version = "0.8.0", default-features=false } smallvec = { version = "0.6.5", features = ["union"] } diff --git a/src/librustc_traits/chalk_context.rs b/src/librustc_traits/chalk_context.rs index 4c28df97bdf..dea3aa4372a 100644 --- a/src/librustc_traits/chalk_context.rs +++ b/src/librustc_traits/chalk_context.rs @@ -19,6 +19,7 @@ ExClauseFold, ExClauseLift, Goal, + GoalKind, ProgramClause, QuantifierKind }; @@ -92,7 +93,7 @@ impl context::Context for ChalkArenas<'tcx> { type DomainGoal = DomainGoal<'tcx>; - type BindersGoal = ty::Binder<&'tcx Goal<'tcx>>; + type BindersGoal = ty::Binder>; type Parameter = Kind<'tcx>; @@ -102,14 +103,6 @@ impl context::Context for ChalkArenas<'tcx> { type UnificationResult = InferOk<'tcx, ()>; - fn into_goal(domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> { - Goal::DomainGoal(domain_goal) - } - - fn cannot_prove() -> Goal<'tcx> { - Goal::CannotProve - } - fn goal_in_environment( env: &ty::ParamEnv<'tcx>, goal: Goal<'tcx>, @@ -251,15 +244,23 @@ fn map_subst_from_canonical( impl context::InferenceTable, ChalkArenas<'tcx>> for ChalkInferenceContext<'cx, 'gcx, 'tcx> { + fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> { + self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal)) + } + + fn cannot_prove(&self) -> Goal<'tcx> { + self.infcx.tcx.mk_goal(GoalKind::CannotProve) + } + fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> { - match goal { - Goal::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"), - Goal::And(left, right) => HhGoal::And(*left, *right), - Goal::Not(subgoal) => HhGoal::Not(*subgoal), - Goal::DomainGoal(d) => HhGoal::DomainGoal(d), - Goal::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder), - Goal::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder), - Goal::CannotProve => HhGoal::CannotProve, + match *goal { + GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"), + GoalKind::And(left, right) => HhGoal::And(left, right), + GoalKind::Not(subgoal) => HhGoal::Not(subgoal), + GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d), + GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder), + GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder), + GoalKind::CannotProve => HhGoal::CannotProve, } } @@ -363,21 +364,21 @@ fn program_clauses( fn instantiate_binders_universally( &mut self, - _arg: &ty::Binder<&'tcx Goal<'tcx>>, + _arg: &ty::Binder>, ) -> Goal<'tcx> { panic!("FIXME -- universal instantiation needs sgrif's branch") } fn instantiate_binders_existentially( &mut self, - arg: &ty::Binder<&'tcx Goal<'tcx>>, + arg: &ty::Binder>, ) -> Goal<'tcx> { let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var( DUMMY_SP, LateBoundRegionConversionTime::HigherRankedType, arg, ); - *value + value } fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box { diff --git a/src/librustc_traits/lowering.rs b/src/librustc_traits/lowering.rs index ad724babe49..181106d3f84 100644 --- a/src/librustc_traits/lowering.rs +++ b/src/librustc_traits/lowering.rs @@ -13,7 +13,14 @@ use rustc::hir::map::definitions::DefPathData; use rustc::hir::{self, ImplPolarity}; use rustc::traits::{ - Clause, Clauses, DomainGoal, FromEnv, Goal, PolyDomainGoal, ProgramClause, WellFormed, + Clause, + Clauses, + DomainGoal, + FromEnv, + GoalKind, + PolyDomainGoal, + ProgramClause, + WellFormed, WhereClause, }; use rustc::ty::query::Providers; @@ -249,7 +256,7 @@ fn program_clauses_for_trait<'a, 'tcx>( let impl_trait: DomainGoal = trait_pred.lower(); // `FromEnv(Self: Trait)` - let from_env_goal = impl_trait.into_from_env_goal().into_goal(); + let from_env_goal = tcx.mk_goal(impl_trait.into_from_env_goal().into_goal()); let hypotheses = tcx.intern_goals(&[from_env_goal]); // `Implemented(Self: Trait) :- FromEnv(Self: Trait)` @@ -308,7 +315,7 @@ fn program_clauses_for_trait<'a, 'tcx>( let wf_clause = ProgramClause { goal: DomainGoal::WellFormed(WellFormed::Trait(trait_pred)), hypotheses: tcx.mk_goals( - wf_conditions.map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), }; let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause))); @@ -352,10 +359,10 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId hypotheses: tcx.mk_goals( where_clauses .into_iter() - .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), }; - tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))]) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn program_clauses_for_type_def<'a, 'tcx>( @@ -388,7 +395,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( where_clauses .iter() .cloned() - .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), }; @@ -404,7 +411,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( // ``` // `FromEnv(Ty<...>)` - let from_env_goal = DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal(); + let from_env_goal = tcx.mk_goal(DomainGoal::FromEnv(FromEnv::Ty(ty)).into_goal()); let hypotheses = tcx.intern_goals(&[from_env_goal]); // For each where clause `WC`: @@ -423,10 +430,86 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( } pub fn program_clauses_for_associated_type_def<'a, 'tcx>( - _tcx: TyCtxt<'a, 'tcx, 'tcx>, - _item_id: DefId, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: DefId, ) -> Clauses<'tcx> { - unimplemented!() + // Rule ProjectionEq-Skolemize + // + // ``` + // trait Trait { + // type AssocType; + // } + // ``` + // + // `ProjectionEq` can succeed by skolemizing, see "associated type" + // chapter for more: + // ``` + // forall { + // ProjectionEq( + // >::AssocType = + // (Trait::AssocType) + // ) + // } + // ``` + + let item = tcx.associated_item(item_id); + debug_assert_eq!(item.kind, ty::AssociatedKind::Type); + let trait_id = match item.container { + ty::AssociatedItemContainer::TraitContainer(trait_id) => trait_id, + _ => bug!("not an trait container"), + }; + let trait_ref = ty::TraitRef::identity(tcx, trait_id); + + let projection_ty = ty::ProjectionTy::from_ref_and_name(tcx, trait_ref, item.ident); + let placeholder_ty = tcx.mk_ty(ty::UnnormalizedProjection(projection_ty)); + let projection_eq = WhereClause::ProjectionEq(ty::ProjectionPredicate { + projection_ty, + ty: placeholder_ty, + }); + + let projection_eq_clause = ProgramClause { + goal: DomainGoal::Holds(projection_eq), + hypotheses: &ty::List::empty(), + }; + + // Rule WellFormed-AssocTy + // ``` + // forall { + // WellFormed((Trait::AssocType)) + // :- Implemented(Self: Trait) + // } + // ``` + + let trait_predicate = ty::TraitPredicate { trait_ref }; + let hypothesis = tcx.mk_goal( + DomainGoal::Holds(WhereClause::Implemented(trait_predicate)).into_goal() + ); + let wf_clause = ProgramClause { + goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)), + hypotheses: tcx.mk_goals(iter::once(hypothesis)), + }; + + // Rule Implied-Trait-From-AssocTy + // ``` + // forall { + // FromEnv(Self: Trait) + // :- FromEnv((Trait::AssocType)) + // } + // ``` + + let hypothesis = tcx.mk_goal( + DomainGoal::FromEnv(FromEnv::Ty(placeholder_ty)).into_goal() + ); + let from_env_clause = ProgramClause { + goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)), + hypotheses: tcx.mk_goals(iter::once(hypothesis)), + }; + + let clauses = iter::once(projection_eq_clause) + .chain(iter::once(wf_clause)) + .chain(iter::once(from_env_clause)); + let clauses = clauses.map(|clause| Clause::ForAll(ty::Binder::dummy(clause))); + tcx.mk_clauses(clauses) } pub fn program_clauses_for_associated_type_value<'a, 'tcx>( @@ -435,10 +518,11 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( ) -> Clauses<'tcx> { // Rule Normalize-From-Impl (see rustc guide) // - // ```impl Trait for A0 - // { + // ``` + // impl Trait for A0 { // type AssocType = T; - // }``` + // } + // ``` // // FIXME: For the moment, we don't account for where clauses written on the associated // ty definition (i.e. in the trait def, as in `type AssocType where T: Sized`). @@ -482,10 +566,10 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>( hypotheses: tcx.mk_goals( hypotheses .into_iter() - .map(|wc| Goal::from_poly_domain_goal(wc, tcx)), + .map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))), ), }; - tcx.intern_clauses(&[Clause::ForAll(ty::Binder::dummy(clause))]) + tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause)))) } pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 845bfad7807..8bac007b748 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,6 +9,6 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } -minifier = "0.0.19" +minifier = "0.0.20" tempfile = "3" parking_lot = "0.6.4" diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 5df4862290e..87b4527a2a7 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -44,9 +44,21 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, } write_header(class, &mut out).unwrap(); - let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm, None), - sess.source_map()); + let lexer = match lexer::StringReader::new_without_err(&sess, fm, None, "Output from rustc:") { + Ok(l) => l, + Err(_) => { + let first_line = src.lines().next().unwrap_or_else(|| ""); + let mut err = sess.span_diagnostic + .struct_warn(&format!("Invalid doc comment starting with: `{}`\n\ + (Ignoring this codeblock)", + first_line)); + err.emit(); + return String::new(); + } + }; + let mut classifier = Classifier::new(lexer, sess.source_map()); if classifier.write_source(&mut out).is_err() { + classifier.lexer.emit_fatal_errors(); return format!("
{}
", src); } @@ -162,11 +174,10 @@ fn try_next_token(&mut self) -> io::Result { match self.lexer.try_next_token() { Ok(tas) => Ok(tas), Err(_) => { - self.lexer.emit_fatal_errors(); - self.lexer.sess.span_diagnostic - .struct_warn("Backing out of syntax highlighting") - .note("You probably did not intend to render this as a rust code-block") - .emit(); + let mut err = self.lexer.sess.span_diagnostic + .struct_warn("Backing out of syntax highlighting"); + err.note("You probably did not intend to render this as a rust code-block"); + err.emit(); Err(io::Error::new(io::ErrorKind::Other, "")) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1c61e73fae0..23f1e15de3c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -4098,12 +4098,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { ", version)?; } + } + write!(fmt, "
")?; + if it.is_crate() { write!(fmt, "

See all {}'s items

", it.name.as_ref().expect("crates always have a name"))?; } - - write!(fmt, "
")?; match it.inner { clean::StructItem(ref s) => sidebar_struct(fmt, it, s)?, clean::TraitItem(ref t) => sidebar_trait(fmt, it, t)?, diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 58ac46d2271..91ff03a327d 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -908,10 +908,9 @@ span.since { padding-top: 0px; } - .sidebar { + body > .sidebar { height: 45px; min-height: 40px; - width: calc(100% + 30px); margin: 0; margin-left: -15px; padding: 0 15px; @@ -1013,6 +1012,10 @@ span.since { .anchor { display: none !important; } + + h1.fqn { + overflow: initial; + } } @media print { @@ -1112,6 +1115,18 @@ h4 > .important-traits { top: 2px; } +#all-types { + text-align: center; + border: 1px solid; + margin: 0 10px; + margin-bottom: 10px; + display: block; + border-radius: 7px; +} +#all-types > p { + margin: 5px 0; +} + @media (max-width: 700px) { h4 > .important-traits { position: absolute; @@ -1135,6 +1150,9 @@ h4 > .important-traits { background-color: rgba(0,0,0,0); height: 100%; } + .sidebar { + width: calc(100% + 30px); + } .show-it { display: block; @@ -1180,6 +1198,10 @@ h4 > .important-traits { .impl > .collapse-toggle { left: -10px; } + + #all-types { + margin: 10px; + } } @@ -1383,17 +1405,6 @@ kbd { #main > ul > li { list-style: none; } -#all-types { - text-align: center; - border: 1px solid; - margin: 0 10px; - margin-bottom: 10px; - display: block; - border-radius: 7px; -} -#all-types > p { - margin: 5px 0; -} .non-exhaustive { margin-bottom: 1em; diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index f14d55cb2d3..017949291bc 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -726,7 +726,7 @@ pub fn write(&mut self, write: bool) -> &mut OpenOptions { /// If a file is opened with both read and append access, beware that after /// opening, and after every write, the position for reading may be set at the /// end of the file. So, before writing, save the current position (using - /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`, and restore it before the next read. + /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`), and restore it before the next read. /// /// ## Note /// diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 48a9b2f4a93..5c87035d8e9 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -79,7 +79,7 @@ /// /// Simply put, a type `T` implements `UnwindSafe` if it cannot easily allow /// witnessing a broken invariant through the use of `catch_unwind` (catching a -/// panic). This trait is a marker trait, so it is automatically implemented for +/// panic). This trait is an auto trait, so it is automatically implemented for /// many types, and it is also structurally composed (e.g. a struct is unwind /// safe if all of its components are unwind safe). /// diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 8d54728a75f..3b432d05132 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -908,11 +908,36 @@ mod prim_usize { } /// `&mut T` references can be freely coerced into `&T` references with the same referent type, and /// references with longer lifetimes can be freely coerced into references with shorter ones. /// +/// Reference equality by address, instead of comparing the values pointed to, is accomplished via +/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while +/// [`PartialEq`] compares values. +/// +/// [`ptr::eq`]: ptr/fn.eq.html +/// [`PartialEq`]: cmp/trait.PartialEq.html +/// +/// ``` +/// use std::ptr; +/// +/// let five = 5; +/// let other_five = 5; +/// let five_ref = &five; +/// let same_five_ref = &five; +/// let other_five_ref = &other_five; +/// +/// assert!(five_ref == same_five_ref); +/// assert!(five_ref == other_five_ref); +/// +/// assert!(ptr::eq(five_ref, same_five_ref)); +/// assert!(!ptr::eq(five_ref, other_five_ref)); +/// ``` +/// /// For more information on how to use references, see [the book's section on "References and /// Borrowing"][book-refs]. /// /// [book-refs]: ../book/second-edition/ch04-02-references-and-borrowing.html /// +/// # Trait implementations +/// /// The following traits are implemented for all `&T`, regardless of the type of its referent: /// /// * [`Copy`] diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 17cb614ba11..98845e457b2 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -329,7 +329,7 @@ pub fn call_once_force(&self, f: F) where F: FnOnce(&OnceState) { /// assert!(handle.join().is_err()); /// assert_eq!(INIT.is_completed(), false); /// ``` - #[unstable(feature = "once_is_completed", issue = "42")] + #[unstable(feature = "once_is_completed", issue = "54890")] #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index a9ce2365577..e611eb86dc1 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -9,7 +9,14 @@ // except according to those terms. use attr::HasAttrs; -use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features, GateIssue}; +use feature_gate::{ + feature_err, + EXPLAIN_STMT_ATTR_SYNTAX, + Features, + get_features, + GateIssue, + emit_feature_err, +}; use {fold, attr}; use ast; use source_map::Spanned; @@ -73,49 +80,103 @@ pub fn configure(&mut self, node: T) -> Option { if self.in_cfg(node.attrs()) { Some(node) } else { None } } + /// Parse and expand all `cfg_attr` attributes into a list of attributes + /// that are within each `cfg_attr` that has a true configuration predicate. + /// + /// Gives compiler warnigns if any `cfg_attr` does not contain any + /// attributes and is in the original source code. Gives compiler errors if + /// the syntax of any `cfg_attr` is incorrect. pub fn process_cfg_attrs(&mut self, node: T) -> T { node.map_attrs(|attrs| { - attrs.into_iter().filter_map(|attr| self.process_cfg_attr(attr)).collect() + attrs.into_iter().flat_map(|attr| self.process_cfg_attr(attr)).collect() }) } - fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option { + /// Parse and expand a single `cfg_attr` attribute into a list of attributes + /// when the configuration predicate is true, or otherwise expand into an + /// empty list of attributes. + /// + /// Gives a compiler warning when the `cfg_attr` contains no attribtes and + /// is in the original source file. Gives a compiler error if the syntax of + /// the attribute is incorrect + fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { if !attr.check_name("cfg_attr") { - return Some(attr); + return vec![attr]; } - let (cfg, path, tokens, span) = match attr.parse(self.sess, |parser| { + let gate_cfg_attr_multi = if let Some(ref features) = self.features { + !features.cfg_attr_multi + } else { + false + }; + let cfg_attr_span = attr.span; + + let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| { parser.expect(&token::OpenDelim(token::Paren))?; - let cfg = parser.parse_meta_item()?; + + let cfg_predicate = parser.parse_meta_item()?; parser.expect(&token::Comma)?; - let lo = parser.span.lo(); - let (path, tokens) = parser.parse_meta_item_unrestricted()?; - parser.eat(&token::Comma); // Optional trailing comma + + // Presumably, the majority of the time there will only be one attr. + let mut expanded_attrs = Vec::with_capacity(1); + + while !parser.check(&token::CloseDelim(token::Paren)) { + let lo = parser.span.lo(); + let (path, tokens) = parser.parse_meta_item_unrestricted()?; + expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo))); + parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?; + } + parser.expect(&token::CloseDelim(token::Paren))?; - Ok((cfg, path, tokens, parser.prev_span.with_lo(lo))) + Ok((cfg_predicate, expanded_attrs)) }) { Ok(result) => result, Err(mut e) => { e.emit(); - return None; + return Vec::new(); } }; - if attr::cfg_matches(&cfg, self.sess, self.features) { - self.process_cfg_attr(ast::Attribute { + // Check feature gate and lint on zero attributes in source. Even if the feature is gated, + // we still compute as if it wasn't, since the emitted error will stop compilation futher + // along the compilation. + match (expanded_attrs.len(), gate_cfg_attr_multi) { + (0, false) => { + // FIXME: Emit unused attribute lint here. + }, + (1, _) => {}, + (_, true) => { + emit_feature_err( + self.sess, + "cfg_attr_multi", + cfg_attr_span, + GateIssue::Language, + "cfg_attr with zero or more than one attributes is experimental", + ); + }, + (_, false) => {} + } + + if attr::cfg_matches(&cfg_predicate, self.sess, self.features) { + // We call `process_cfg_attr` recursively in case there's a + // `cfg_attr` inside of another `cfg_attr`. E.g. + // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. + expanded_attrs.into_iter() + .flat_map(|(path, tokens, span)| self.process_cfg_attr(ast::Attribute { id: attr::mk_attr_id(), style: attr.style, path, tokens, is_sugared_doc: false, span, - }) + })) + .collect() } else { - None + Vec::new() } } - // Determine if a node with the given attributes should be included in this configuration. + /// Determine if a node with the given attributes should be included in this configuration. pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { attrs.iter().all(|attr| { if !is_cfg(attr) { @@ -165,7 +226,7 @@ pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool { }) } - // Visit attributes on expression and statements (but not attributes on items in blocks). + /// Visit attributes on expression and statements (but not attributes on items in blocks). fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) { // flag the offending attributes for attr in attrs.iter() { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 24ee2464055..b86b92fb29e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -433,9 +433,6 @@ pub fn walk_feature_fields(&self, mut f: F) // #[doc(alias = "...")] (active, doc_alias, "1.27.0", Some(50146), None), - // Scoped lints - (active, tool_lints, "1.28.0", Some(44690), None), - // Allows irrefutable patterns in if-let and while-let statements (RFC 2086) (active, irrefutable_let_patterns, "1.27.0", Some(44495), None), @@ -499,6 +496,9 @@ pub fn walk_feature_fields(&self, mut f: F) // Allows `impl Trait` in bindings (`let`, `const`, `static`) (active, impl_trait_in_bindings, "1.30.0", Some(34511), None), + + // #[cfg_attr(predicate, multiple, attributes, here)] + (active, cfg_attr_multi, "1.31.0", Some(54881), None), ); declare_features! ( @@ -679,6 +679,8 @@ pub fn walk_feature_fields(&self, mut f: F) (accepted, pattern_parentheses, "1.31.0", Some(51087), None), // Allows the definition of `const fn` functions. (accepted, min_const_fn, "1.31.0", Some(53555), None), + // Scoped lints + (accepted, tool_lints, "1.31.0", Some(44690), None), ); // If you change this, please modify src/doc/unstable-book as well. You must diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index aa47d5bf669..a814c88ee78 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -238,6 +238,19 @@ pub fn new(sess: &'a ParseSess, sr } + pub fn new_without_err(sess: &'a ParseSess, + source_file: Lrc, + override_span: Option, + prepend_error_text: &str) -> Result { + let mut sr = StringReader::new_raw(sess, source_file, override_span); + if sr.advance_token().is_err() { + eprintln!("{}", prepend_error_text); + sr.emit_fatal_errors(); + return Err(()); + } + Ok(sr) + } + pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self { let begin = sess.source_map().lookup_byte_offset(span.lo()); let end = sess.source_map().lookup_byte_offset(span.hi()); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 08349084aa6..b5896f37c00 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -678,7 +678,7 @@ pub fn expect(&mut self, t: &token::Token) -> PResult<'a, ()> { /// Expect next token to be edible or inedible token. If edible, /// then consume it; if inedible, then return without consuming /// anything. Signal a fatal error if next token is unexpected. - fn expect_one_of(&mut self, + pub fn expect_one_of(&mut self, edible: &[token::Token], inedible: &[token::Token]) -> PResult<'a, ()>{ fn tokens_to_string(tokens: &[TokenType]) -> String { @@ -1435,6 +1435,23 @@ fn parse_trait_item_(&mut self, attrs.extend(inner_attrs.iter().cloned()); Some(body) } + token::Interpolated(ref nt) => { + match &nt.0 { + token::NtBlock(..) => { + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + attrs.extend(inner_attrs.iter().cloned()); + Some(body) + } + _ => { + let token_str = self.this_token_to_string(); + let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`", + token_str)); + err.span_label(self.span, "expected `;` or `{`"); + return Err(err); + } + } + } _ => { let token_str = self.this_token_to_string(); let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`", @@ -3871,6 +3888,9 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec isize { 0 } -// CHECK: Function Attrs: naked uwtable +// CHECK: Function Attrs: naked // CHECK-NEXT: define i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}}) #[no_mangle] #[naked] @@ -57,7 +57,7 @@ pub fn naked_with_args_and_return(a: isize) -> isize { a } -// CHECK: Function Attrs: naked uwtable +// CHECK: Function Attrs: naked // CHECK-NEXT: define void @naked_recursive() #[no_mangle] #[naked] diff --git a/src/test/codegen/no-plt.rs b/src/test/codegen/no-plt.rs new file mode 100644 index 00000000000..8f302e57902 --- /dev/null +++ b/src/test/codegen/no-plt.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C relocation-model=pic -Z plt=no + +#![crate_type = "lib"] + +// We need a function which is normally called through the PLT. +extern "C" { + // CHECK: Function Attrs: nounwind nonlazybind + fn getenv(name: *const u8) -> *mut u8; +} + +// Ensure the function gets referenced. +pub unsafe fn call_through_plt() -> *mut u8 { + getenv(b"\0".as_ptr()) +} + +// Ensure intrinsics also skip the PLT +// CHECK: !"RtLibUseGOT" diff --git a/src/test/run-pass/macros/macro-as-fn-body.rs b/src/test/run-pass/macros/macro-as-fn-body.rs new file mode 100644 index 00000000000..8c3c9fdc66d --- /dev/null +++ b/src/test/run-pass/macros/macro-as-fn-body.rs @@ -0,0 +1,42 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// run-pass +// +// Description - ensure Interpolated blocks can act as valid function bodies +// Covered cases: free functions, struct methods, and default trait functions + +macro_rules! def_fn { + ($body:block) => { + fn bar() $body + } +} + +trait Foo { + def_fn!({ println!("foo"); }); +} + +struct Baz {} + +impl Foo for Baz {} + +struct Qux {} + +impl Qux { + def_fn!({ println!("qux"); }); +} + +def_fn!({ println!("quux"); }); + +pub fn main() { + Baz::bar(); + Qux::bar(); + bar(); +} diff --git a/src/test/run-pass/tool_lints.rs b/src/test/run-pass/tool_lints.rs index 24ec43b12f6..2705c03598a 100644 --- a/src/test/run-pass/tool_lints.rs +++ b/src/test/run-pass/tool_lints.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_lints)] + #![deny(unknown_lints)] #[allow(clippy::almost_swapped)] diff --git a/src/test/run-pass/tool_lints_2018_preview.rs b/src/test/run-pass/tool_lints_2018_preview.rs index 6cd57eaa195..57df3e072a8 100644 --- a/src/test/run-pass/tool_lints_2018_preview.rs +++ b/src/test/run-pass/tool_lints_2018_preview.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_lints)] + #![feature(rust_2018_preview)] #![deny(unknown_lints)] diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs new file mode 100644 index 00000000000..8c790d7d07e --- /dev/null +++ b/src/test/rustdoc-ui/invalid-syntax.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// compile-flags: --error-format=human + +/// ``` +/// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ +/// ``` +pub fn foo() {} diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr new file mode 100644 index 00000000000..b5661332e8d --- /dev/null +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -0,0 +1,10 @@ +Output from rustc: +error: unknown start of token: / + --> :1:1 + | +1 | /__________pkt->size___________/ /_result->size_/ /__pkt->size__/ + | ^ + +warning: Invalid doc comment starting with: `/__________pkt->size___________/ /_result->size_/ /__pkt->size__/` +(Ignoring this codeblock) + diff --git a/src/test/ui-fulldeps/lint_tool_test.rs b/src/test/ui-fulldeps/lint_tool_test.rs index ebe10b3714f..11b70d1d780 100644 --- a/src/test/ui-fulldeps/lint_tool_test.rs +++ b/src/test/ui-fulldeps/lint_tool_test.rs @@ -11,8 +11,8 @@ // aux-build:lint_tool_test.rs // ignore-stage1 // compile-flags: --cfg foo + #![feature(plugin)] -#![feature(tool_lints)] #![plugin(lint_tool_test)] #![allow(dead_code)] #![cfg_attr(foo, warn(test_lint))] diff --git a/src/test/ui/auxiliary/namespaced_enums.rs b/src/test/ui/auxiliary/namespaced_enums.rs deleted file mode 100644 index 3bf39b788db..00000000000 --- a/src/test/ui/auxiliary/namespaced_enums.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub enum Foo { - A, - B(isize), - C { a: isize }, -} - -impl Foo { - pub fn foo() {} - pub fn bar(&self) {} -} diff --git a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr index f823a6f08d7..c3a2180b9f0 100644 --- a/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr +++ b/src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr @@ -1,10 +1,10 @@ -error[E0507]: cannot move out of borrowed content +error[E0507]: cannot move out of dereference of raw pointer --> $DIR/borrowck-move-from-unsafe-ptr.rs:13:13 | LL | let y = *x; //~ ERROR cannot move out of dereference of raw pointer | ^^ | | - | cannot move out of borrowed content + | cannot move out of dereference of raw pointer | help: consider removing the `*`: `x` error: aborting due to previous error diff --git a/src/test/ui/cfg-arg-invalid-1.rs b/src/test/ui/cfg-arg-invalid-1.rs deleted file mode 100644 index 36dd78dd2b1..00000000000 --- a/src/test/ui/cfg-arg-invalid-1.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags: --cfg a(b=c) -// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`) -fn main() {} diff --git a/src/test/ui/cfg-arg-invalid-2.rs b/src/test/ui/cfg-arg-invalid-2.rs deleted file mode 100644 index 48d656a4a28..00000000000 --- a/src/test/ui/cfg-arg-invalid-2.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags: --cfg a{b} -// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) -fn main() {} diff --git a/src/test/ui/cfg-arg-invalid-3.rs b/src/test/ui/cfg-arg-invalid-3.rs deleted file mode 100644 index 96ac7828c5c..00000000000 --- a/src/test/ui/cfg-arg-invalid-3.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags: --cfg a::b -// error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier) -fn main() {} diff --git a/src/test/ui/cfg-arg-invalid-4.rs b/src/test/ui/cfg-arg-invalid-4.rs deleted file mode 100644 index e7dfa17b4b6..00000000000 --- a/src/test/ui/cfg-arg-invalid-4.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags: --cfg a(b) -// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) -fn main() {} diff --git a/src/test/ui/cfg-arg-invalid-5.rs b/src/test/ui/cfg-arg-invalid-5.rs deleted file mode 100644 index a939f451038..00000000000 --- a/src/test/ui/cfg-arg-invalid-5.rs +++ /dev/null @@ -1,3 +0,0 @@ -// compile-flags: --cfg a=10 -// error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string) -fn main() {} diff --git a/src/test/ui/cfg-attr-cfg-2.rs b/src/test/ui/cfg-attr-cfg-2.rs deleted file mode 100644 index 58a62d45ea5..00000000000 --- a/src/test/ui/cfg-attr-cfg-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// error-pattern: `main` function not found -// compile-flags: --cfg foo - -// main is conditionally compiled, but the conditional compilation -// is conditional too! - -#[cfg_attr(foo, cfg(bar))] -fn main() { } diff --git a/src/test/ui/cfg-attr-cfg-2.stderr b/src/test/ui/cfg-attr-cfg-2.stderr deleted file mode 100644 index db3c7acff15..00000000000 --- a/src/test/ui/cfg-attr-cfg-2.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` - | - = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/cfg-attr-crate-2.rs b/src/test/ui/cfg-attr-crate-2.rs deleted file mode 100644 index a79c7663861..00000000000 --- a/src/test/ui/cfg-attr-crate-2.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// compile-flags: --cfg broken - -// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 - -#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental - -fn main() { } diff --git a/src/test/ui/cfg-attr-crate-2.stderr b/src/test/ui/cfg-attr-crate-2.stderr deleted file mode 100644 index 7b66c8f5e40..00000000000 --- a/src/test/ui/cfg-attr-crate-2.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: no_core is experimental (see issue #29639) - --> $DIR/cfg-attr-crate-2.rs:15:21 - | -LL | #![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental - | ^^^^^^^^ - | - = help: add #![feature(no_core)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/cfg-attr-invalid-predicate.rs b/src/test/ui/cfg-attr-invalid-predicate.rs deleted file mode 100644 index 09fe6cec49c..00000000000 --- a/src/test/ui/cfg-attr-invalid-predicate.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[cfg(foo(bar))] //~ ERROR invalid predicate `foo` -fn main() {} diff --git a/src/test/ui/cfg-attr-invalid-predicate.stderr b/src/test/ui/cfg-attr-invalid-predicate.stderr deleted file mode 100644 index 5a89f9766d1..00000000000 --- a/src/test/ui/cfg-attr-invalid-predicate.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0537]: invalid predicate `foo` - --> $DIR/cfg-attr-invalid-predicate.rs:11:7 - | -LL | #[cfg(foo(bar))] //~ ERROR invalid predicate `foo` - | ^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0537`. diff --git a/src/test/ui/cfg-attr-syntax-validation.rs b/src/test/ui/cfg-attr-syntax-validation.rs deleted file mode 100644 index 06a22eff25c..00000000000 --- a/src/test/ui/cfg-attr-syntax-validation.rs +++ /dev/null @@ -1,32 +0,0 @@ -#[cfg] //~ ERROR `cfg` is not followed by parentheses -struct S1; - -#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses -struct S2; - -#[cfg()] //~ ERROR `cfg` predicate is not specified -struct S3; - -#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified -struct S4; - -#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal -struct S5; - -#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier -struct S6; - -#[cfg(a())] //~ ERROR invalid predicate `a` -struct S7; - -#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string -struct S8; - -macro_rules! generate_s9 { - ($expr: expr) => { - #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item - struct S9; - } -} - -generate_s9!(concat!("nonexistent")); diff --git a/src/test/ui/cfg-attr-syntax-validation.stderr b/src/test/ui/cfg-attr-syntax-validation.stderr deleted file mode 100644 index 7773fdb8cf9..00000000000 --- a/src/test/ui/cfg-attr-syntax-validation.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: `cfg` is not followed by parentheses - --> $DIR/cfg-attr-syntax-validation.rs:1:1 - | -LL | #[cfg] //~ ERROR `cfg` is not followed by parentheses - | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)` - -error: `cfg` is not followed by parentheses - --> $DIR/cfg-attr-syntax-validation.rs:4:1 - | -LL | #[cfg = 10] //~ ERROR `cfg` is not followed by parentheses - | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` - -error: `cfg` predicate is not specified - --> $DIR/cfg-attr-syntax-validation.rs:7:1 - | -LL | #[cfg()] //~ ERROR `cfg` predicate is not specified - | ^^^^^^^^ - -error: multiple `cfg` predicates are specified - --> $DIR/cfg-attr-syntax-validation.rs:10:10 - | -LL | #[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified - | ^ - -error: `cfg` predicate key cannot be a literal - --> $DIR/cfg-attr-syntax-validation.rs:13:7 - | -LL | #[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal - | ^^^^^ - -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-attr-syntax-validation.rs:16:7 - | -LL | #[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier - | ^^^^ - -error[E0537]: invalid predicate `a` - --> $DIR/cfg-attr-syntax-validation.rs:19:7 - | -LL | #[cfg(a())] //~ ERROR invalid predicate `a` - | ^^^ - -error: literal in `cfg` predicate value must be a string - --> $DIR/cfg-attr-syntax-validation.rs:22:11 - | -LL | #[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string - | ^^ - -error: `cfg` is not a well-formed meta-item - --> $DIR/cfg-attr-syntax-validation.rs:27:9 - | -LL | #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item - | ^^^^^^^^^^^^^^^^^^^^^^^ help: expected syntax is: `#[cfg(/* predicate */)]` -... -LL | generate_s9!(concat!("nonexistent")); - | ------------------------------------- in this macro invocation - -error: aborting due to 9 previous errors - -For more information about this error, try `rustc --explain E0537`. diff --git a/src/test/ui/cfg-attr-trailing-comma.rs b/src/test/ui/cfg-attr-trailing-comma.rs deleted file mode 100644 index 21e00544ca0..00000000000 --- a/src/test/ui/cfg-attr-trailing-comma.rs +++ /dev/null @@ -1,13 +0,0 @@ -// compile-flags: --cfg TRUE - -#[cfg_attr(TRUE, inline,)] // OK -fn f() {} - -#[cfg_attr(FALSE, inline,)] // OK -fn g() {} - -#[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,` -fn h() {} - -#[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,` -fn i() {} diff --git a/src/test/ui/cfg-attr-trailing-comma.stderr b/src/test/ui/cfg-attr-trailing-comma.stderr deleted file mode 100644 index 76a470417e9..00000000000 --- a/src/test/ui/cfg-attr-trailing-comma.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: expected `)`, found `,` - --> $DIR/cfg-attr-trailing-comma.rs:9:25 - | -LL | #[cfg_attr(TRUE, inline,,)] //~ ERROR expected `)`, found `,` - | ^ expected `)` - -error: expected `)`, found `,` - --> $DIR/cfg-attr-trailing-comma.rs:12:26 - | -LL | #[cfg_attr(FALSE, inline,,)] //~ ERROR expected `)`, found `,` - | ^ expected `)` - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.rs deleted file mode 100644 index afcb896b43c..00000000000 --- a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -macro_rules! foo { - () => { - #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown - fn foo() {} - } -} - -foo!(); - -fn main() {} diff --git a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr deleted file mode 100644 index 0f51c7d68c6..00000000000 --- a/src/test/ui/cfg-attr-unknown-attribute-macro-expansion.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) - --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:13:27 - | -LL | #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown - | ^^^^^^^ -... -LL | foo!(); - | ------- in this macro invocation - | - = help: add #![feature(custom_attribute)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/cfg-empty-codemap.rs b/src/test/ui/cfg-empty-codemap.rs deleted file mode 100644 index 5cf8135ca6b..00000000000 --- a/src/test/ui/cfg-empty-codemap.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that empty source_maps don't ICE (#23301) - -// compile-flags: --cfg "" - -// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) - -pub fn main() { -} diff --git a/src/test/ui/cfg-in-crate-1.rs b/src/test/ui/cfg-in-crate-1.rs deleted file mode 100644 index bbccf2bcd0f..00000000000 --- a/src/test/ui/cfg-in-crate-1.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern: `main` function not found - -#![cfg(bar)] diff --git a/src/test/ui/cfg-in-crate-1.stderr b/src/test/ui/cfg-in-crate-1.stderr deleted file mode 100644 index c6d42c732c9..00000000000 --- a/src/test/ui/cfg-in-crate-1.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error[E0601]: `main` function not found in crate `cfg_in_crate_1` - | - = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/cfg-non-opt-expr.rs b/src/test/ui/cfg-non-opt-expr.rs deleted file mode 100644 index 55eca7f45a5..00000000000 --- a/src/test/ui/cfg-non-opt-expr.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(stmt_expr_attributes)] -#![feature(custom_test_frameworks)] - -fn main() { - let _ = #[cfg(unset)] (); - //~^ ERROR removing an expression is not supported in this position - let _ = 1 + 2 + #[cfg(unset)] 3; - //~^ ERROR removing an expression is not supported in this position - let _ = [1, 2, 3][#[cfg(unset)] 1]; - //~^ ERROR removing an expression is not supported in this position -} diff --git a/src/test/ui/cfg-non-opt-expr.stderr b/src/test/ui/cfg-non-opt-expr.stderr deleted file mode 100644 index 1892cee113e..00000000000 --- a/src/test/ui/cfg-non-opt-expr.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: removing an expression is not supported in this position - --> $DIR/cfg-non-opt-expr.rs:15:13 - | -LL | let _ = #[cfg(unset)] (); - | ^^^^^^^^^^^^^ - -error: removing an expression is not supported in this position - --> $DIR/cfg-non-opt-expr.rs:17:21 - | -LL | let _ = 1 + 2 + #[cfg(unset)] 3; - | ^^^^^^^^^^^^^ - -error: removing an expression is not supported in this position - --> $DIR/cfg-non-opt-expr.rs:19:23 - | -LL | let _ = [1, 2, 3][#[cfg(unset)] 1]; - | ^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/cfg_attr_path.rs b/src/test/ui/cfg_attr_path.rs deleted file mode 100644 index 7d799850a65..00000000000 --- a/src/test/ui/cfg_attr_path.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(rustc_attrs)] -#![allow(dead_code)] -#![deny(unused_attributes)] // c.f #35584 - -mod auxiliary { - #[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums; - #[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file; -} - -#[rustc_error] -fn main() { //~ ERROR compilation successful - let _ = auxiliary::namespaced_enums::Foo::A; - let _ = auxiliary::nonexistent_file::Foo::A; -} diff --git a/src/test/ui/cfg_attr_path.stderr b/src/test/ui/cfg_attr_path.stderr deleted file mode 100644 index 67e59d054d5..00000000000 --- a/src/test/ui/cfg_attr_path.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: compilation successful - --> $DIR/cfg_attr_path.rs:21:1 - | -LL | / fn main() { //~ ERROR compilation successful -LL | | let _ = auxiliary::namespaced_enums::Foo::A; -LL | | let _ = auxiliary::nonexistent_file::Foo::A; -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs index c5ba5beeca7..ba7d4ff0d9b 100644 --- a/src/test/ui/chalkify/lower_trait.rs +++ b/src/test/ui/chalkify/lower_trait.rs @@ -10,11 +10,12 @@ #![feature(rustc_attrs)] +trait Bar { } + #[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo { - fn s(_: S) -> S; - fn t(_: T) -> T; - fn u(_: U) -> U; +trait Foo { + #[rustc_dump_program_clauses] //~ ERROR program clause dump + type Assoc: Bar + ?Sized; } fn main() { diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr index c4e768415d6..dc2375277e7 100644 --- a/src/test/ui/chalkify/lower_trait.stderr +++ b/src/test/ui/chalkify/lower_trait.stderr @@ -1,14 +1,23 @@ error: program clause dump - --> $DIR/lower_trait.rs:13:1 + --> $DIR/lower_trait.rs:15:1 | LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo). - = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo). - = note: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo). - = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). - = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(U: std::marker::Sized). + = note: FromEnv(>::Assoc: Bar) :- FromEnv(Self: Foo). + = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo). + = note: Implemented(Self: Foo) :- FromEnv(Self: Foo). + = note: WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(S: std::marker::Sized), WellFormed(>::Assoc: Bar). -error: aborting due to previous error +error: program clause dump + --> $DIR/lower_trait.rs:17:5 + | +LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: FromEnv(Self: Foo) :- FromEnv(Unnormalized(>::Assoc)). + = note: ProjectionEq(>::Assoc == Unnormalized(>::Assoc)). + = note: WellFormed(Unnormalized(>::Assoc)) :- Implemented(Self: Foo). + +error: aborting due to 2 previous errors diff --git a/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs b/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs new file mode 100644 index 00000000000..3bf39b788db --- /dev/null +++ b/src/test/ui/conditional-compilation/auxiliary/namespaced_enums.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub enum Foo { + A, + B(isize), + C { a: isize }, +} + +impl Foo { + pub fn foo() {} + pub fn bar(&self) {} +} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs new file mode 100644 index 00000000000..36dd78dd2b1 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-1.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a(b=c) +// error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`) +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs new file mode 100644 index 00000000000..48d656a4a28 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a{b} +// error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs new file mode 100644 index 00000000000..96ac7828c5c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-3.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a::b +// error-pattern: invalid `--cfg` argument: `a::b` (argument key must be an identifier) +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs new file mode 100644 index 00000000000..e7dfa17b4b6 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a(b) +// error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs new file mode 100644 index 00000000000..a939f451038 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-arg-invalid-5.rs @@ -0,0 +1,3 @@ +// compile-flags: --cfg a=10 +// error-pattern: invalid `--cfg` argument: `a=10` (argument value must be a string) +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs new file mode 100644 index 00000000000..58a62d45ea5 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// error-pattern: `main` function not found +// compile-flags: --cfg foo + +// main is conditionally compiled, but the conditional compilation +// is conditional too! + +#[cfg_attr(foo, cfg(bar))] +fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr new file mode 100644 index 00000000000..db3c7acff15 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-cfg-2.stderr @@ -0,0 +1,7 @@ +error[E0601]: `main` function not found in crate `cfg_attr_cfg_2` + | + = note: consider adding a `main` function to `$DIR/cfg-attr-cfg-2.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs new file mode 100644 index 00000000000..a79c7663861 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.rs @@ -0,0 +1,17 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: --cfg broken + +// https://github.com/rust-lang/rust/issues/21833#issuecomment-72353044 + +#![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental + +fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr new file mode 100644 index 00000000000..a730473f663 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-crate-2.stderr @@ -0,0 +1,11 @@ +error[E0658]: no_core is experimental (see issue #29639) + --> $DIR/cfg-attr-crate-2.rs:15:21 + | +LL | #![cfg_attr(broken, no_core)] //~ ERROR no_core is experimental + | ^^^^^^^ + | + = help: add #![feature(no_core)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs new file mode 100644 index 00000000000..09fe6cec49c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs @@ -0,0 +1,12 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[cfg(foo(bar))] //~ ERROR invalid predicate `foo` +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr new file mode 100644 index 00000000000..5a89f9766d1 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.stderr @@ -0,0 +1,9 @@ +error[E0537]: invalid predicate `foo` + --> $DIR/cfg-attr-invalid-predicate.rs:11:7 + | +LL | #[cfg(foo(bar))] //~ ERROR invalid predicate `foo` + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0537`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs new file mode 100644 index 00000000000..84bd33fc0e7 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-false.rs @@ -0,0 +1,20 @@ +// Test that cfg_attr doesn't emit any attributes when the +// configuation variable is false. This mirrors `cfg-attr-multi-true.rs` + +// compile-pass + +#![warn(unused_must_use)] +#![feature(cfg_attr_multi)] + +#[cfg_attr(any(), deprecated, must_use)] +struct Struct {} + +impl Struct { + fn new() -> Struct { + Struct {} + } +} + +fn main() { + Struct::new(); +} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs new file mode 100644 index 00000000000..d4c3186a6eb --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: --cfg broken + +#![feature(cfg_attr_multi)] +#![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental + +fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr new file mode 100644 index 00000000000..bf68d92cc0b --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-1.stderr @@ -0,0 +1,11 @@ +error[E0658]: no_core is experimental (see issue #29639) + --> $DIR/cfg-attr-multi-invalid-1.rs:14:21 + | +LL | #![cfg_attr(broken, no_core, no_std)] //~ ERROR no_core is experimental + | ^^^^^^^ + | + = help: add #![feature(no_core)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs new file mode 100644 index 00000000000..bee6b7d4886 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: --cfg broken + +#![feature(cfg_attr_multi)] +#![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental + +fn main() { } diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr new file mode 100644 index 00000000000..5c72a400e0b --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-invalid-2.stderr @@ -0,0 +1,11 @@ +error[E0658]: no_core is experimental (see issue #29639) + --> $DIR/cfg-attr-multi-invalid-2.rs:14:29 + | +LL | #![cfg_attr(broken, no_std, no_core)] //~ ERROR no_core is experimental + | ^^^^^^^ + | + = help: add #![feature(no_core)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs new file mode 100644 index 00000000000..a31dde00c7c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.rs @@ -0,0 +1,22 @@ +// Test that cfg_attr with multiple attributes actually emits both attributes. +// This is done by emitting two attributes that cause new warnings, and then +// triggering those warnings. + +// compile-pass + +#![warn(unused_must_use)] +#![feature(cfg_attr_multi)] + +#[cfg_attr(all(), deprecated, must_use)] +struct MustUseDeprecated {} + +impl MustUseDeprecated { //~ warning: use of deprecated item + fn new() -> MustUseDeprecated { //~ warning: use of deprecated item + MustUseDeprecated {} //~ warning: use of deprecated item + } +} + +fn main() { + MustUseDeprecated::new(); //~ warning: use of deprecated item + //| warning: unused `MustUseDeprecated` which must be used +} diff --git a/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr new file mode 100644 index 00000000000..37cb3de06c0 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-multi-true.stderr @@ -0,0 +1,38 @@ +warning: use of deprecated item 'MustUseDeprecated' + --> $DIR/cfg-attr-multi-true.rs:13:6 + | +LL | impl MustUseDeprecated { //~ warning: use of deprecated item + | ^^^^^^^^^^^^^^^^^ + | + = note: #[warn(deprecated)] on by default + +warning: use of deprecated item 'MustUseDeprecated' + --> $DIR/cfg-attr-multi-true.rs:20:5 + | +LL | MustUseDeprecated::new(); //~ warning: use of deprecated item + | ^^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated item 'MustUseDeprecated' + --> $DIR/cfg-attr-multi-true.rs:14:17 + | +LL | fn new() -> MustUseDeprecated { //~ warning: use of deprecated item + | ^^^^^^^^^^^^^^^^^ + +warning: use of deprecated item 'MustUseDeprecated' + --> $DIR/cfg-attr-multi-true.rs:15:9 + | +LL | MustUseDeprecated {} //~ warning: use of deprecated item + | ^^^^^^^^^^^^^^^^^ + +warning: unused `MustUseDeprecated` which must be used + --> $DIR/cfg-attr-multi-true.rs:20:5 + | +LL | MustUseDeprecated::new(); //~ warning: use of deprecated item + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/cfg-attr-multi-true.rs:7:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.rs b/src/test/ui/conditional-compilation/cfg-attr-parse.rs new file mode 100644 index 00000000000..eec0e8faca8 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-parse.rs @@ -0,0 +1,45 @@ +// Parse `cfg_attr` with varying numbers of attributes and trailing commas + +#![feature(cfg_attr_multi)] + +// Completely empty `cfg_attr` input +#[cfg_attr()] //~ error: expected identifier, found `)` +struct NoConfigurationPredicate; + +// Zero attributes, zero trailing comma (comma manatory here) +#[cfg_attr(all())] //~ error: expected `,`, found `)` +struct A0C0; + +// Zero attributes, one trailing comma +#[cfg_attr(all(),)] // Ok +struct A0C1; + +// Zero attributes, two trailing commas +#[cfg_attr(all(),,)] //~ ERROR expected identifier +struct A0C2; + +// One attribute, no trailing comma +#[cfg_attr(all(), must_use)] // Ok +struct A1C0; + +// One attribute, one trailing comma +#[cfg_attr(all(), must_use,)] // Ok +struct A1C1; + +// One attribute, two trailing commas +#[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier +struct A1C2; + +// Two attributes, no trailing comma +#[cfg_attr(all(), must_use, deprecated)] // Ok +struct A2C0; + +// Two attributes, one trailing comma +#[cfg_attr(all(), must_use, deprecated,)] // Ok +struct A2C1; + +// Two attributes, two trailing commas +#[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier +struct A2C2; + +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-parse.stderr b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr new file mode 100644 index 00000000000..553406b6dd8 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-parse.stderr @@ -0,0 +1,32 @@ +error: expected identifier, found `)` + --> $DIR/cfg-attr-parse.rs:6:12 + | +LL | #[cfg_attr()] //~ error: expected identifier, found `)` + | ^ expected identifier + +error: expected `,`, found `)` + --> $DIR/cfg-attr-parse.rs:10:17 + | +LL | #[cfg_attr(all())] //~ error: expected `,`, found `)` + | ^ expected `,` + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:18:18 + | +LL | #[cfg_attr(all(),,)] //~ ERROR expected identifier + | ^ expected identifier + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:30:28 + | +LL | #[cfg_attr(all(), must_use,,)] //~ ERROR expected identifier + | ^ expected identifier + +error: expected identifier, found `,` + --> $DIR/cfg-attr-parse.rs:42:40 + | +LL | #[cfg_attr(all(), must_use, deprecated,,)] //~ ERROR expected identifier + | ^ expected identifier + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs new file mode 100644 index 00000000000..06a22eff25c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -0,0 +1,32 @@ +#[cfg] //~ ERROR `cfg` is not followed by parentheses +struct S1; + +#[cfg = 10] //~ ERROR `cfg` is not followed by parentheses +struct S2; + +#[cfg()] //~ ERROR `cfg` predicate is not specified +struct S3; + +#[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified +struct S4; + +#[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal +struct S5; + +#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier +struct S6; + +#[cfg(a())] //~ ERROR invalid predicate `a` +struct S7; + +#[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string +struct S8; + +macro_rules! generate_s9 { + ($expr: expr) => { + #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item + struct S9; + } +} + +generate_s9!(concat!("nonexistent")); diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr new file mode 100644 index 00000000000..7773fdb8cf9 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -0,0 +1,60 @@ +error: `cfg` is not followed by parentheses + --> $DIR/cfg-attr-syntax-validation.rs:1:1 + | +LL | #[cfg] //~ ERROR `cfg` is not followed by parentheses + | ^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + +error: `cfg` is not followed by parentheses + --> $DIR/cfg-attr-syntax-validation.rs:4:1 + | +LL | #[cfg = 10] //~ ERROR `cfg` is not followed by parentheses + | ^^^^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)` + +error: `cfg` predicate is not specified + --> $DIR/cfg-attr-syntax-validation.rs:7:1 + | +LL | #[cfg()] //~ ERROR `cfg` predicate is not specified + | ^^^^^^^^ + +error: multiple `cfg` predicates are specified + --> $DIR/cfg-attr-syntax-validation.rs:10:10 + | +LL | #[cfg(a, b)] //~ ERROR multiple `cfg` predicates are specified + | ^ + +error: `cfg` predicate key cannot be a literal + --> $DIR/cfg-attr-syntax-validation.rs:13:7 + | +LL | #[cfg("str")] //~ ERROR `cfg` predicate key cannot be a literal + | ^^^^^ + +error: `cfg` predicate key must be an identifier + --> $DIR/cfg-attr-syntax-validation.rs:16:7 + | +LL | #[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier + | ^^^^ + +error[E0537]: invalid predicate `a` + --> $DIR/cfg-attr-syntax-validation.rs:19:7 + | +LL | #[cfg(a())] //~ ERROR invalid predicate `a` + | ^^^ + +error: literal in `cfg` predicate value must be a string + --> $DIR/cfg-attr-syntax-validation.rs:22:11 + | +LL | #[cfg(a = 10)] //~ ERROR literal in `cfg` predicate value must be a string + | ^^ + +error: `cfg` is not a well-formed meta-item + --> $DIR/cfg-attr-syntax-validation.rs:27:9 + | +LL | #[cfg(feature = $expr)] //~ ERROR `cfg` is not a well-formed meta-item + | ^^^^^^^^^^^^^^^^^^^^^^^ help: expected syntax is: `#[cfg(/* predicate */)]` +... +LL | generate_s9!(concat!("nonexistent")); + | ------------------------------------- in this macro invocation + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0537`. diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs new file mode 100644 index 00000000000..afcb896b43c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.rs @@ -0,0 +1,20 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! foo { + () => { + #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown + fn foo() {} + } +} + +foo!(); + +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr new file mode 100644 index 00000000000..0f51c7d68c6 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -0,0 +1,14 @@ +error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:13:27 + | +LL | #[cfg_attr(all(), unknown)] //~ ERROR `unknown` is currently unknown + | ^^^^^^^ +... +LL | foo!(); + | ------- in this macro invocation + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/conditional-compilation/cfg-empty-codemap.rs b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs new file mode 100644 index 00000000000..5cf8135ca6b --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-empty-codemap.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that empty source_maps don't ICE (#23301) + +// compile-flags: --cfg "" + +// error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) + +pub fn main() { +} diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.rs b/src/test/ui/conditional-compilation/cfg-in-crate-1.rs new file mode 100644 index 00000000000..bbccf2bcd0f --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: `main` function not found + +#![cfg(bar)] diff --git a/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr new file mode 100644 index 00000000000..c6d42c732c9 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-in-crate-1.stderr @@ -0,0 +1,7 @@ +error[E0601]: `main` function not found in crate `cfg_in_crate_1` + | + = note: consider adding a `main` function to `$DIR/cfg-in-crate-1.rs` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs b/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs new file mode 100644 index 00000000000..55eca7f45a5 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-non-opt-expr.rs @@ -0,0 +1,21 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(stmt_expr_attributes)] +#![feature(custom_test_frameworks)] + +fn main() { + let _ = #[cfg(unset)] (); + //~^ ERROR removing an expression is not supported in this position + let _ = 1 + 2 + #[cfg(unset)] 3; + //~^ ERROR removing an expression is not supported in this position + let _ = [1, 2, 3][#[cfg(unset)] 1]; + //~^ ERROR removing an expression is not supported in this position +} diff --git a/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr b/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr new file mode 100644 index 00000000000..1892cee113e --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-non-opt-expr.stderr @@ -0,0 +1,20 @@ +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:15:13 + | +LL | let _ = #[cfg(unset)] (); + | ^^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:17:21 + | +LL | let _ = 1 + 2 + #[cfg(unset)] 3; + | ^^^^^^^^^^^^^ + +error: removing an expression is not supported in this position + --> $DIR/cfg-non-opt-expr.rs:19:23 + | +LL | let _ = [1, 2, 3][#[cfg(unset)] 1]; + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/conditional-compilation/cfg_attr_path.rs b/src/test/ui/conditional-compilation/cfg_attr_path.rs new file mode 100644 index 00000000000..7d799850a65 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_attr_path.rs @@ -0,0 +1,24 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![deny(unused_attributes)] // c.f #35584 + +mod auxiliary { + #[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums; + #[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file; +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful + let _ = auxiliary::namespaced_enums::Foo::A; + let _ = auxiliary::nonexistent_file::Foo::A; +} diff --git a/src/test/ui/conditional-compilation/cfg_attr_path.stderr b/src/test/ui/conditional-compilation/cfg_attr_path.stderr new file mode 100644 index 00000000000..67e59d054d5 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_attr_path.stderr @@ -0,0 +1,11 @@ +error: compilation successful + --> $DIR/cfg_attr_path.rs:21:1 + | +LL | / fn main() { //~ ERROR compilation successful +LL | | let _ = auxiliary::namespaced_enums::Foo::A; +LL | | let _ = auxiliary::nonexistent_file::Foo::A; +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs new file mode 100644 index 00000000000..9515380bc28 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.rs @@ -0,0 +1,5 @@ +// gate-test-cfg_attr_multi + +#![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))] +//~^ ERROR cfg_attr with zero or more than one attributes is experimental +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr new file mode 100644 index 00000000000..088e6df1a1a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-1.stderr @@ -0,0 +1,11 @@ +error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881) + --> $DIR/feature-gate-cfg-attr-multi-1.rs:3:1 + | +LL | #![cfg_attr(all(), warn(nonstandard_style), allow(unused_attributes))] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_attr_multi)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs new file mode 100644 index 00000000000..cf02432274b --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.rs @@ -0,0 +1,3 @@ +#![cfg_attr(all(),)] +//~^ ERROR cfg_attr with zero or more than one attributes is experimental +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr new file mode 100644 index 00000000000..a01876114dd --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-2.stderr @@ -0,0 +1,11 @@ +error[E0658]: cfg_attr with zero or more than one attributes is experimental (see issue #54881) + --> $DIR/feature-gate-cfg-attr-multi-2.rs:1:1 + | +LL | #![cfg_attr(all(),)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(cfg_attr_multi)] to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs new file mode 100644 index 00000000000..e4737926e7a --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-1.rs @@ -0,0 +1,7 @@ +// Test that settingt the featute gate while using its functionality doesn't error. + +// compile-pass + +#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")] + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs new file mode 100644 index 00000000000..df740541f55 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-cfg-attr-multi-bootstrap-2.rs @@ -0,0 +1,9 @@ +// Test that settingt the featute gate while using its functionality doesn't error. +// Specifically, if there's a cfg-attr *before* the feature gate. + +// compile-pass + +#![cfg_attr(all(),)] +#![cfg_attr(all(), feature(cfg_attr_multi), crate_type="bin")] + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-tool_lints-fail.rs b/src/test/ui/feature-gates/feature-gate-tool_lints-fail.rs deleted file mode 100644 index c311eb7ed7a..00000000000 --- a/src/test/ui/feature-gates/feature-gate-tool_lints-fail.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr b/src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr deleted file mode 100644 index 33ee79cd201..00000000000 --- a/src/test/ui/feature-gates/feature-gate-tool_lints-fail.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: scoped lint `clippy::assign_ops` is experimental (see issue #44690) - --> $DIR/feature-gate-tool_lints-fail.rs:11:8 - | -LL | #[warn(clippy::assign_ops)] //~ ERROR scoped lint `clippy::assign_ops` is experimental - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(tool_lints)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-tool_lints.rs b/src/test/ui/feature-gates/feature-gate-tool_lints.rs deleted file mode 100644 index 3ef67982be9..00000000000 --- a/src/test/ui/feature-gates/feature-gate-tool_lints.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[warn(clippy::decimal_literal_representation)] -//~^ ERROR scoped lint `clippy::decimal_literal_representation` is experimental -fn main() { - let a = 65_535; -} diff --git a/src/test/ui/feature-gates/feature-gate-tool_lints.stderr b/src/test/ui/feature-gates/feature-gate-tool_lints.stderr deleted file mode 100644 index 8019b1e6a28..00000000000 --- a/src/test/ui/feature-gates/feature-gate-tool_lints.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: scoped lint `clippy::decimal_literal_representation` is experimental (see issue #44690) - --> $DIR/feature-gate-tool_lints.rs:11:8 - | -LL | #[warn(clippy::decimal_literal_representation)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(tool_lints)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/inline-asm-bad-operand.rs b/src/test/ui/inline-asm-bad-operand.rs new file mode 100644 index 00000000000..37021f38cac --- /dev/null +++ b/src/test/ui/inline-asm-bad-operand.rs @@ -0,0 +1,57 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the compiler will catch passing invalid values to inline assembly +// operands. + +#![feature(asm)] + +#[repr(C)] +struct MyPtr(usize); + +fn main() { + issue_37433(); + issue_37437(); + issue_40187(); + issue_54067(); +} + +fn issue_37433() { + unsafe { + asm!("" :: "r"("")); //~ ERROR E0669 + } + + unsafe { + let target = MyPtr(0); + asm!("ret" : : "{rdi}"(target)); //~ ERROR E0669 + } +} + +fn issue_37437() { + let hello: &str = "hello"; + // this should fail... + unsafe { asm!("" :: "i"(hello)) }; //~ ERROR E0669 + // but this should succeed. + unsafe { asm!("" :: "r"(hello.as_ptr())) }; +} + +fn issue_40187() { + let arr: [u8; 1] = [0; 1]; + unsafe { + asm!("movups $1, %xmm0"::"m"(arr)); //~ ERROR E0669 + } +} + +fn issue_54067() { + let addr: Option = Some(123); + unsafe { + asm!("mov sp, $0"::"r"(addr)); //~ ERROR E0669 + } +} diff --git a/src/test/ui/inline-asm-bad-operand.stderr b/src/test/ui/inline-asm-bad-operand.stderr new file mode 100644 index 00000000000..6971215a95f --- /dev/null +++ b/src/test/ui/inline-asm-bad-operand.stderr @@ -0,0 +1,33 @@ +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/inline-asm-bad-operand.rs:28:9 + | +LL | asm!("" :: "r"("")); //~ ERROR E0669 + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/inline-asm-bad-operand.rs:33:9 + | +LL | asm!("ret" : : "{rdi}"(target)); //~ ERROR E0669 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/inline-asm-bad-operand.rs:40:14 + | +LL | unsafe { asm!("" :: "i"(hello)) }; //~ ERROR E0669 + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/inline-asm-bad-operand.rs:48:9 + | +LL | asm!("movups $1, %xmm0"::"m"(arr)); //~ ERROR E0669 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/inline-asm-bad-operand.rs:55:9 + | +LL | asm!("mov sp, $0"::"r"(addr)); //~ ERROR E0669 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0669`. diff --git a/src/test/ui/issues/issue-20801.nll.stderr b/src/test/ui/issues/issue-20801.nll.stderr index 3a6784eed67..362778b26c8 100644 --- a/src/test/ui/issues/issue-20801.nll.stderr +++ b/src/test/ui/issues/issue-20801.nll.stderr @@ -16,22 +16,22 @@ LL | let b = unsafe { *imm_ref() }; | cannot move out of borrowed content | help: consider removing the `*`: `imm_ref()` -error[E0507]: cannot move out of borrowed content +error[E0507]: cannot move out of dereference of raw pointer --> $DIR/issue-20801.rs:42:22 | LL | let c = unsafe { *mut_ptr() }; | ^^^^^^^^^^ | | - | cannot move out of borrowed content + | cannot move out of dereference of raw pointer | help: consider removing the `*`: `mut_ptr()` -error[E0507]: cannot move out of borrowed content +error[E0507]: cannot move out of dereference of raw pointer --> $DIR/issue-20801.rs:45:22 | LL | let d = unsafe { *const_ptr() }; | ^^^^^^^^^^^^ | | - | cannot move out of borrowed content + | cannot move out of dereference of raw pointer | help: consider removing the `*`: `const_ptr()` error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/must_use-unit.rs b/src/test/ui/lint/must_use-unit.rs new file mode 100644 index 00000000000..92568252164 --- /dev/null +++ b/src/test/ui/lint/must_use-unit.rs @@ -0,0 +1,17 @@ +#![feature(never_type)] + +#![deny(unused_must_use)] + +#[must_use] +fn foo() {} + +#[must_use] +fn bar() -> ! { + unimplemented!() +} + +fn main() { + foo(); //~ unused return value of `foo` + + bar(); //~ unused return value of `bar` +} diff --git a/src/test/ui/lint/must_use-unit.stderr b/src/test/ui/lint/must_use-unit.stderr new file mode 100644 index 00000000000..0a956f74611 --- /dev/null +++ b/src/test/ui/lint/must_use-unit.stderr @@ -0,0 +1,20 @@ +error: unused return value of `foo` which must be used + --> $DIR/must_use-unit.rs:14:5 + | +LL | foo(); //~ unused return value of `foo` + | ^^^^^^ + | +note: lint level defined here + --> $DIR/must_use-unit.rs:3:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +error: unused return value of `bar` which must be used + --> $DIR/must_use-unit.rs:16:5 + | +LL | bar(); //~ unused return value of `bar` + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/nll/issue-52663-trait-object.rs b/src/test/ui/nll/issue-52663-trait-object.rs new file mode 100644 index 00000000000..65d73eeae67 --- /dev/null +++ b/src/test/ui/nll/issue-52663-trait-object.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![feature(nll)] + +trait Foo { fn get(&self); } + +impl Foo for A { + fn get(&self) { } +} + +fn main() { + let _ = { + let tmp0 = 3; + let tmp1 = &tmp0; + box tmp1 as Box + }; + //~^^^ ERROR `tmp0` does not live long enough +} diff --git a/src/test/ui/nll/issue-52663-trait-object.stderr b/src/test/ui/nll/issue-52663-trait-object.stderr new file mode 100644 index 00000000000..035422f2458 --- /dev/null +++ b/src/test/ui/nll/issue-52663-trait-object.stderr @@ -0,0 +1,13 @@ +error[E0597]: `tmp0` does not live long enough + --> $DIR/issue-52663-trait-object.rs:23:20 + | +LL | let tmp1 = &tmp0; + | ^^^^^ borrowed value does not live long enough +LL | box tmp1 as Box + | ------------------------- borrow later captured here by trait object +LL | }; + | - `tmp0` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/resolve/issue-54379.rs b/src/test/ui/resolve/issue-54379.rs new file mode 100644 index 00000000000..24aa758ea6c --- /dev/null +++ b/src/test/ui/resolve/issue-54379.rs @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +struct MyStruct { + pub s1: Option, +} + +fn main() { + let thing = MyStruct { s1: None }; + + match thing { + MyStruct { .., Some(_) } => {}, + _ => {} + } +} diff --git a/src/test/ui/resolve/issue-54379.stderr b/src/test/ui/resolve/issue-54379.stderr new file mode 100644 index 00000000000..d1d693a3817 --- /dev/null +++ b/src/test/ui/resolve/issue-54379.stderr @@ -0,0 +1,24 @@ +error: expected `}`, found `,` + --> $DIR/issue-54379.rs:18:22 + | +LL | MyStruct { .., Some(_) } => {}, + | --^ + | | | + | | expected `}` + | `..` must be at the end and cannot have a trailing comma + +error: expected `,` + --> $DIR/issue-54379.rs:18:24 + | +LL | MyStruct { .., Some(_) } => {}, + | ^^^^ + +error[E0027]: pattern does not mention field `s1` + --> $DIR/issue-54379.rs:18:9 + | +LL | MyStruct { .., Some(_) } => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^ missing field `s1` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr index f8e5e3914eb..11fa447b548 100644 --- a/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr +++ b/src/test/ui/span/regions-close-over-type-parameter-2.nll.stderr @@ -4,7 +4,7 @@ error[E0597]: `tmp0` does not live long enough LL | let tmp1 = &tmp0; | ^^^^^ borrowed value does not live long enough LL | repeater3(tmp1) - | --------------- borrow later used here + | --------------- borrow later captured here by trait object LL | }; | - `tmp0` dropped here while still borrowed diff --git a/src/test/ui/tool_lints-fail.rs b/src/test/ui/tool_lints-fail.rs index ea1efab4cb6..4134fca1ce6 100644 --- a/src/test/ui/tool_lints-fail.rs +++ b/src/test/ui/tool_lints-fail.rs @@ -10,7 +10,7 @@ // Don't allow tool_lints, which aren't scoped -#![feature(tool_lints)] + #![deny(unknown_lints)] #![deny(clippy)] //~ ERROR: unknown lint: `clippy` diff --git a/src/test/ui/tool_lints.rs b/src/test/ui/tool_lints.rs index 71f90b17c18..001f2f11e5c 100644 --- a/src/test/ui/tool_lints.rs +++ b/src/test/ui/tool_lints.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_lints)] + #[warn(foo::bar)] //~^ ERROR an unknown tool name found in scoped lint: `foo::bar` diff --git a/src/test/ui/unknown-lint-tool-name.rs b/src/test/ui/unknown-lint-tool-name.rs index 78b736edceb..a1d6c27e518 100644 --- a/src/test/ui/unknown-lint-tool-name.rs +++ b/src/test/ui/unknown-lint-tool-name.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_lints)] + #![deny(foo::bar)] //~ ERROR an unknown tool name found in scoped lint: `foo::bar`