]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #60950 - taiki-e:arbitrary_self_types-tests, r=Centril
authorbors <bors@rust-lang.org>
Tue, 21 May 2019 03:44:09 +0000 (03:44 +0000)
committerbors <bors@rust-lang.org>
Tue, 21 May 2019 03:44:09 +0000 (03:44 +0000)
Move arbitrary self types's tests into ui/self

https://github.com/rust-lang/rust/pull/60944#discussion_r285362006

r? @Centril

233 files changed:
src/bootstrap/test.rs
src/ci/docker/x86_64-gnu-tools/checkregression.py
src/liballoc/alloc.rs
src/liballoc/collections/binary_heap.rs
src/liballoc/collections/vec_deque.rs
src/liballoc/lib.rs
src/liballoc/tests/btree/set.rs
src/liballoc/tests/lib.rs
src/libcore/alloc.rs
src/libcore/fmt/mod.rs
src/libcore/iter/traits/iterator.rs
src/libcore/lib.rs
src/libcore/mem.rs
src/libcore/ptr.rs
src/libcore/task/wake.rs
src/libcore/tests/alloc.rs [new file with mode: 0644]
src/libcore/tests/lib.rs
src/librustc/hir/def_id.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/definitions.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/nice_region_error/util.rs
src/librustc/infer/lexical_region_resolve/graphviz.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/region.rs
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/mono.rs
src/librustc/mir/tcx.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/object_safety.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/mod.rs
src/librustc/ty/print/pretty.rs
src/librustc/ty/query/values.rs
src/librustc/ty/sty.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_ssa/back/write.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustc_data_structures/macros.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_driver/pretty.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/index.rs
src/librustc_metadata/locator.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/util/graphviz.rs
src/librustc_resolve/macros.rs
src/librustc_save_analysis/lib.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/mod.rs
src/librustdoc/config.rs
src/librustdoc/core.rs
src/librustdoc/externalfiles.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/passes/collect_intra_doc_links.rs
src/librustdoc/passes/mod.rs
src/librustdoc/test.rs
src/libstd/alloc.rs
src/libstd/collections/hash/map.rs
src/libstd/error.rs
src/libstd/ffi/os_str.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/addr.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.rs [deleted file]
src/libstd/sync/mpsc/select_tests.rs [deleted file]
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/unix/rand.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/token.rs
src/libsyntax/tokenstream.rs
src/libsyntax_pos/symbol.rs
src/libtest/lib.rs
src/libunwind/build.rs
src/llvm-project
src/test/codegen/box-maybe-uninit.rs
src/test/codegen/dllimports/main.rs
src/test/codegen/panic-abort-windows.rs
src/test/incremental/foreign.rs
src/test/incremental/no_mangle.rs [new file with mode: 0644]
src/test/mir-opt/const_prop/array_index.rs
src/test/mir-opt/const_prop/checked_add.rs
src/test/mir-opt/const_prop/switch_int.rs [new file with mode: 0644]
src/test/mir-opt/simplify_if.rs
src/test/run-pass-valgrind/exit-flushes.rs
src/test/run-pass/abort-on-c-abi.rs
src/test/run-pass/atomic-print.rs
src/test/run-pass/backtrace-debuginfo.rs
src/test/run-pass/backtrace.rs
src/test/run-pass/c-stack-returning-int64.rs
src/test/run-pass/cfg/cfg-family.rs
src/test/run-pass/cfg/cfg-target-family.rs
src/test/run-pass/command-exec.rs
src/test/run-pass/command-pre-exec.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/default-alloc-error-hook.rs
src/test/run-pass/env-args-reverse-iterator.rs
src/test/run-pass/env-funky-keys.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/exec-env.rs
src/test/run-pass/fds-are-cloexec.rs
src/test/run-pass/foreign/foreign-fn-linkname.rs
src/test/run-pass/inherit-env.rs
src/test/run-pass/intrinsics/intrinsic-alignment.rs
src/test/run-pass/invalid_const_promotion.rs
src/test/run-pass/issue-59020.rs
src/test/run-pass/issues/issue-10626.rs
src/test/run-pass/issues/issue-12133-3.rs
src/test/run-pass/issues/issue-12699.rs
src/test/run-pass/issues/issue-13304.rs
src/test/run-pass/issues/issue-13494.rs [deleted file]
src/test/run-pass/issues/issue-14456.rs
src/test/run-pass/issues/issue-14940.rs
src/test/run-pass/issues/issue-16272.rs
src/test/run-pass/issues/issue-2214.rs
src/test/run-pass/issues/issue-24313.rs
src/test/run-pass/issues/issue-30490.rs
src/test/run-pass/issues/issue-33770.rs
src/test/run-pass/issues/issue-9396.rs
src/test/run-pass/linkage1.rs
src/test/run-pass/macros/macro-comma-support.rs
src/test/run-pass/mpsc_stress.rs
src/test/run-pass/multi-panic.rs
src/test/run-pass/no-stdio.rs
src/test/run-pass/out-of-stack.rs
src/test/run-pass/panic-runtime/abort-link-to-unwinding-crates.rs
src/test/run-pass/panic-runtime/abort.rs
src/test/run-pass/panic-runtime/lto-abort.rs
src/test/run-pass/panic-runtime/lto-unwind.rs
src/test/run-pass/panic-uninitialized-zeroed.rs
src/test/run-pass/paths-containing-nul.rs
src/test/run-pass/print-stdout-eprint-stderr.rs
src/test/run-pass/process/process-envs.rs
src/test/run-pass/process/process-exit.rs
src/test/run-pass/process/process-remove-from-env.rs
src/test/run-pass/process/process-spawn-nonexistent.rs
src/test/run-pass/process/process-spawn-with-unicode-params.rs
src/test/run-pass/process/process-status-inherits-stdin.rs
src/test/run-pass/rfcs/rfc-1014.rs
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/segfault-no-out-of-stack.rs
src/test/run-pass/signal-alternate-stack-cleanup.rs
src/test/run-pass/signal-exit-status.rs
src/test/run-pass/sigpipe-should-be-ignored.rs
src/test/run-pass/simd/simd-target-feature-mixup.rs
src/test/run-pass/sleep.rs
src/test/run-pass/stack-probes-lto.rs
src/test/run-pass/stack-probes.rs
src/test/run-pass/stdio-is-blocking.rs
src/test/run-pass/structs-enums/rec-align-u64.rs
src/test/run-pass/tcp-stress.rs
src/test/run-pass/threads-sendsync/sync-send-in-std.rs
src/test/run-pass/try-wait.rs
src/test/run-pass/union/union-nonzero.rs [new file with mode: 0644]
src/test/run-pass/wait-forked-but-failed-child.rs
src/test/run-pass/x86stdcall.rs
src/test/rustdoc-ui/doc-without-codeblock.rs
src/test/rustdoc-ui/doc-without-codeblock.stderr
src/test/rustdoc-ui/lint-missing-doc-code-example.rs [new file with mode: 0644]
src/test/rustdoc-ui/lint-missing-doc-code-example.stderr [new file with mode: 0644]
src/test/rustdoc/async-move-doctest.rs [new file with mode: 0644]
src/test/rustdoc/attributes.rs
src/test/rustdoc/generic-const.rs [new file with mode: 0644]
src/test/rustdoc/intra-link-libstd-re-export.rs [new file with mode: 0644]
src/test/rustdoc/playground-arg.rs
src/test/rustdoc/playground.rs
src/test/ui/cdylib-deps-must-be-static.rs
src/test/ui/consts/std/alloc.rs [new file with mode: 0644]
src/test/ui/consts/std/alloc.stderr [new file with mode: 0644]
src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
src/test/ui/imports/extern-crate-used.rs
src/test/ui/imports/extern-crate-used.stderr
src/test/ui/issues/issue-20091.rs
src/test/ui/issues/issue-32709.stderr
src/test/ui/issues/issue-39175.rs
src/test/ui/issues/issue-39175.stderr
src/test/ui/linkage2.rs
src/test/ui/linkage2.stderr
src/test/ui/panic-runtime/abort-link-to-unwind-dylib.rs
src/test/ui/print_type_sizes/niche-filling.rs
src/test/ui/print_type_sizes/niche-filling.stdout
src/test/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.fixed
src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.rs
src/test/ui/rust-2018/extern-crate-idiomatic-in-2018.stderr
src/test/ui/rust-2018/remove-extern-crate.fixed
src/test/ui/rust-2018/remove-extern-crate.rs
src/test/ui/rust-2018/remove-extern-crate.stderr
src/test/ui/suggestions/issue-57672.rs [new file with mode: 0644]
src/test/ui/try-block/try-block-bad-type.stderr
src/test/ui/try-on-option.stderr
src/tools/clippy
src/tools/error_index_generator/main.rs
src/tools/miri
src/tools/rls

index 7826ac9471806043c1b00505e13cbe9ffab424c6..be0af8be7b272bc615aab84985faa07db286c449 100644 (file)
@@ -683,7 +683,7 @@ fn run(self, builder: &Builder<'_>) {
             target: self.target,
             mode: "ui",
             suite: "rustdoc-ui",
-            path: None,
+            path: Some("src/test/rustdoc-ui"),
             compare_mode: None,
         })
     }
index 8aa90319d661520bbe1657a8cce2cec6b697b8b9..0cc0a6329e5bf779060a19762329296fd935c8dd 100755 (executable)
@@ -21,12 +21,7 @@ if __name__ == '__main__':
         state = cur[os_name]
         new_state = toolstate.get(tool, '')
         if verb == 'regressed':
-            if tool == 'rls':
-                # Temporary override until
-                # https://github.com/rust-lang/rust/issues/60848 is fixed.
-                updated = False
-            else:
-                updated = new_state < state
+            updated = new_state < state
         elif verb == 'changed':
             updated = new_state != state
         else:
index ddc6481eec78e9d703b4a26499cd60cac93b8cca..41ff06d70ff09eb7897af0f71c5385e42807483d 100644 (file)
@@ -37,6 +37,8 @@ fn __rust_realloc(ptr: *mut u8,
 ///
 /// Note: while this type is unstable, the functionality it provides can be
 /// accessed through the [free functions in `alloc`](index.html#functions).
+///
+/// [`Alloc`]: trait.Alloc.html
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[derive(Copy, Clone, Default, Debug)]
 pub struct Global;
@@ -54,6 +56,10 @@ fn __rust_realloc(ptr: *mut u8,
 ///
 /// See [`GlobalAlloc::alloc`].
 ///
+/// [`Global`]: struct.Global.html
+/// [`Alloc`]: trait.Alloc.html
+/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc
+///
 /// # Examples
 ///
 /// ```
@@ -87,6 +93,10 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
 /// # Safety
 ///
 /// See [`GlobalAlloc::dealloc`].
+///
+/// [`Global`]: struct.Global.html
+/// [`Alloc`]: trait.Alloc.html
+/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[inline]
 pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
@@ -105,6 +115,10 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
 /// # Safety
 ///
 /// See [`GlobalAlloc::realloc`].
+///
+/// [`Global`]: struct.Global.html
+/// [`Alloc`]: trait.Alloc.html
+/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[inline]
 pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
@@ -124,6 +138,10 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
 ///
 /// See [`GlobalAlloc::alloc_zeroed`].
 ///
+/// [`Global`]: struct.Global.html
+/// [`Alloc`]: trait.Alloc.html
+/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed
+///
 /// # Examples
 ///
 /// ```
index 39fcfaa789377bb575fabda5be8fccc790468885..c5a0b6e877b65f124f61e925ab8989c5e02547e1 100644 (file)
 /// assert_eq!(heap.pop(), Some(Reverse(5)));
 /// assert_eq!(heap.pop(), None);
 /// ```
+///
+/// # Time complexity
+///
+/// | [push] | [pop]    | [peek]/[peek\_mut] |
+/// |--------|----------|--------------------|
+/// | O(1)~  | O(log n) | O(1)               |
+///
+/// The value for `push` is an expected cost; the method documentation gives a
+/// more detailed analysis.
+///
+/// [push]: #method.push
+/// [pop]: #method.pop
+/// [peek]: #method.peek
+/// [peek\_mut]: #method.peek_mut
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BinaryHeap<T> {
     data: Vec<T>,
@@ -384,6 +398,10 @@ pub fn with_capacity(capacity: usize) -> BinaryHeap<T> {
     /// }
     /// assert_eq!(heap.peek(), Some(&2));
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// Cost is O(1) in the worst case.
     #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
     pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
         if self.is_empty() {
@@ -411,6 +429,11 @@ pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
     /// assert_eq!(heap.pop(), Some(1));
     /// assert_eq!(heap.pop(), None);
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// The worst case cost of `pop` on a heap containing *n* elements is O(log
+    /// n).
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop(&mut self) -> Option<T> {
         self.data.pop().map(|mut item| {
@@ -438,6 +461,22 @@ pub fn pop(&mut self) -> Option<T> {
     /// assert_eq!(heap.len(), 3);
     /// assert_eq!(heap.peek(), Some(&5));
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// The expected cost of `push`, averaged over every possible ordering of
+    /// the elements being pushed, and over a sufficiently large number of
+    /// pushes, is O(1). This is the most meaningful cost metric when pushing
+    /// elements that are *not* already in any sorted pattern.
+    ///
+    /// The time complexity degrades if elements are pushed in predominantly
+    /// ascending order. In the worst case, elements are pushed in ascending
+    /// sorted order and the amortized cost per push is O(log n) against a heap
+    /// containing *n* elements.
+    ///
+    /// The worst case cost of a *single* call to `push` is O(n). The worst case
+    /// occurs when capacity is exhausted and needs a resize. The resize cost
+    /// has been amortized in the previous figures.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, item: T) {
         let old_len = self.len();
@@ -650,6 +689,10 @@ pub fn iter(&self) -> Iter<'_, T> {
     /// assert_eq!(heap.peek(), Some(&5));
     ///
     /// ```
+    ///
+    /// # Time complexity
+    ///
+    /// Cost is O(1) in the worst case.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn peek(&self) -> Option<&T> {
         self.data.get(0)
index 9a8d48083e67c676e2fffbfc7f32f9ef53e461ef..31e49d06a7b5a963d3701ed6123ea50f8c792bf8 100644 (file)
@@ -1948,8 +1948,6 @@ pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) {
     /// # Examples
     ///
     /// ```
-    /// #![feature(vecdeque_rotate)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<_> = (0..10).collect();
@@ -1963,7 +1961,7 @@ pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) {
     /// }
     /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     /// ```
-    #[unstable(feature = "vecdeque_rotate", issue = "56686")]
+    #[stable(feature = "vecdeque_rotate", since = "1.36.0")]
     pub fn rotate_left(&mut self, mid: usize) {
         assert!(mid <= self.len());
         let k = self.len() - mid;
@@ -1993,8 +1991,6 @@ pub fn rotate_left(&mut self, mid: usize) {
     /// # Examples
     ///
     /// ```
-    /// #![feature(vecdeque_rotate)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<_> = (0..10).collect();
@@ -2008,7 +2004,7 @@ pub fn rotate_left(&mut self, mid: usize) {
     /// }
     /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     /// ```
-    #[unstable(feature = "vecdeque_rotate", issue = "56686")]
+    #[stable(feature = "vecdeque_rotate", since = "1.36.0")]
     pub fn rotate_right(&mut self, k: usize) {
         assert!(k <= self.len());
         let mid = self.len() - k;
index 2edd946ff11cfa91ce2c397ec2edd85df0a81582..d90036eaf49b8f3da6389d23e8f978f69fe5984e 100644 (file)
 #![feature(rustc_const_unstable)]
 #![feature(const_vec_new)]
 #![feature(slice_partition_dedup)]
-#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)]
+#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
 #![feature(iter_nth_back)]
index d52814118b3c7de7c74c47f1d8700a6299be55f6..989beb3b1bfd90afbfd55626953080d31016bb39 100644 (file)
@@ -143,8 +143,8 @@ fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
 #[test]
 // Only tests the simple function definition with respect to intersection
 fn test_is_disjoint() {
-    let one = [1].into_iter().collect::<BTreeSet<_>>();
-    let two = [2].into_iter().collect::<BTreeSet<_>>();
+    let one = [1].iter().collect::<BTreeSet<_>>();
+    let two = [2].iter().collect::<BTreeSet<_>>();
     assert!(one.is_disjoint(&two));
 }
 
index b736750c57601e5b1798d871837b90910f1bad40..ddb3120e89d781635645c424a9eba34d803e85d2 100644 (file)
@@ -6,7 +6,6 @@
 #![feature(repeat_generic_slice)]
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
-#![feature(vecdeque_rotate)]
 #![deny(rust_2018_idioms)]
 
 use std::hash::{Hash, Hasher};
index c124457118cb97768a98b181f70be07ad85e7dd9..f25631e028eecb15506ddf803c80482fb4b411c4 100644 (file)
@@ -99,7 +99,7 @@ pub fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
     /// [`Layout::from_size_align`](#method.from_size_align).
     #[stable(feature = "alloc_layout", since = "1.28.0")]
     #[inline]
-    pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
+    pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
         Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) }
     }
 
@@ -480,7 +480,7 @@ pub unsafe trait GlobalAlloc {
     ///   this allocator,
     ///
     /// * `layout` must be the same layout that was used
-    ///   to allocated that block of memory,
+    ///   to allocate that block of memory,
     #[stable(feature = "global_alloc", since = "1.28.0")]
     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
 
@@ -535,7 +535,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
     /// * `ptr` must be currently allocated via this allocator,
     ///
     /// * `layout` must be the same layout that was used
-    ///   to allocated that block of memory,
+    ///   to allocate that block of memory,
     ///
     /// * `new_size` must be greater than zero.
     ///
index 43c1a3b7767ab647838c9f4f3702e0a29271a881..2f6d745d146d647d3fd5716e57db7dc020964b39 100644 (file)
@@ -886,7 +886,7 @@ pub trait Pointer {
 ///
 /// # Examples
 ///
-/// Basic usage with `i32`:
+/// Basic usage with `f64`:
 ///
 /// ```
 /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation
@@ -929,7 +929,7 @@ pub trait LowerExp {
 ///
 /// # Examples
 ///
-/// Basic usage with `f32`:
+/// Basic usage with `f64`:
 ///
 /// ```
 /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation
index 403f3358105325c917fae4fa0277f4dc7be5700e..38c7c9bc4d086c53e9e27eed48168dff5670b4ef 100644 (file)
@@ -356,7 +356,7 @@ fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
     ///
     /// ```
     /// let a = [0, 1, 2, 3, 4, 5];
-    /// let mut iter = a.into_iter().step_by(2);
+    /// let mut iter = a.iter().step_by(2);
     ///
     /// assert_eq!(iter.next(), Some(&0));
     /// assert_eq!(iter.next(), Some(&2));
@@ -531,7 +531,7 @@ fn zip<U>(self, other: U) -> Zip<Self, U::IntoIter> where
     /// ```
     /// let a = [1, 2, 3];
     ///
-    /// let mut iter = a.into_iter().map(|x| 2 * x);
+    /// let mut iter = a.iter().map(|x| 2 * x);
     ///
     /// assert_eq!(iter.next(), Some(2));
     /// assert_eq!(iter.next(), Some(4));
@@ -620,7 +620,7 @@ fn for_each<F>(self, mut f: F) where
     /// ```
     /// let a = [0i32, 1, 2];
     ///
-    /// let mut iter = a.into_iter().filter(|x| x.is_positive());
+    /// let mut iter = a.iter().filter(|x| x.is_positive());
     ///
     /// assert_eq!(iter.next(), Some(&1));
     /// assert_eq!(iter.next(), Some(&2));
@@ -634,7 +634,7 @@ fn for_each<F>(self, mut f: F) where
     /// ```
     /// let a = [0, 1, 2];
     ///
-    /// let mut iter = a.into_iter().filter(|x| **x > 1); // need two *s!
+    /// let mut iter = a.iter().filter(|x| **x > 1); // need two *s!
     ///
     /// assert_eq!(iter.next(), Some(&2));
     /// assert_eq!(iter.next(), None);
@@ -646,7 +646,7 @@ fn for_each<F>(self, mut f: F) where
     /// ```
     /// let a = [0, 1, 2];
     ///
-    /// let mut iter = a.into_iter().filter(|&x| *x > 1); // both & and *
+    /// let mut iter = a.iter().filter(|&x| *x > 1); // both & and *
     ///
     /// assert_eq!(iter.next(), Some(&2));
     /// assert_eq!(iter.next(), None);
@@ -657,7 +657,7 @@ fn for_each<F>(self, mut f: F) where
     /// ```
     /// let a = [0, 1, 2];
     ///
-    /// let mut iter = a.into_iter().filter(|&&x| x > 1); // two &s
+    /// let mut iter = a.iter().filter(|&&x| x > 1); // two &s
     ///
     /// assert_eq!(iter.next(), Some(&2));
     /// assert_eq!(iter.next(), None);
@@ -837,7 +837,7 @@ fn peekable(self) -> Peekable<Self> where Self: Sized {
     /// ```
     /// let a = [-1i32, 0, 1];
     ///
-    /// let mut iter = a.into_iter().skip_while(|x| x.is_negative());
+    /// let mut iter = a.iter().skip_while(|x| x.is_negative());
     ///
     /// assert_eq!(iter.next(), Some(&0));
     /// assert_eq!(iter.next(), Some(&1));
@@ -851,7 +851,7 @@ fn peekable(self) -> Peekable<Self> where Self: Sized {
     /// ```
     /// let a = [-1, 0, 1];
     ///
-    /// let mut iter = a.into_iter().skip_while(|x| **x < 0); // need two *s!
+    /// let mut iter = a.iter().skip_while(|x| **x < 0); // need two *s!
     ///
     /// assert_eq!(iter.next(), Some(&0));
     /// assert_eq!(iter.next(), Some(&1));
@@ -863,7 +863,7 @@ fn peekable(self) -> Peekable<Self> where Self: Sized {
     /// ```
     /// let a = [-1, 0, 1, -2];
     ///
-    /// let mut iter = a.into_iter().skip_while(|x| **x < 0);
+    /// let mut iter = a.iter().skip_while(|x| **x < 0);
     ///
     /// assert_eq!(iter.next(), Some(&0));
     /// assert_eq!(iter.next(), Some(&1));
@@ -898,7 +898,7 @@ fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
     /// ```
     /// let a = [-1i32, 0, 1];
     ///
-    /// let mut iter = a.into_iter().take_while(|x| x.is_negative());
+    /// let mut iter = a.iter().take_while(|x| x.is_negative());
     ///
     /// assert_eq!(iter.next(), Some(&-1));
     /// assert_eq!(iter.next(), None);
@@ -911,7 +911,7 @@ fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
     /// ```
     /// let a = [-1, 0, 1];
     ///
-    /// let mut iter = a.into_iter().take_while(|x| **x < 0); // need two *s!
+    /// let mut iter = a.iter().take_while(|x| **x < 0); // need two *s!
     ///
     /// assert_eq!(iter.next(), Some(&-1));
     /// assert_eq!(iter.next(), None);
@@ -922,7 +922,7 @@ fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
     /// ```
     /// let a = [-1, 0, 1, -2];
     ///
-    /// let mut iter = a.into_iter().take_while(|x| **x < 0);
+    /// let mut iter = a.iter().take_while(|x| **x < 0);
     ///
     /// assert_eq!(iter.next(), Some(&-1));
     ///
@@ -937,7 +937,7 @@ fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P> where
     ///
     /// ```
     /// let a = [1, 2, 3, 4];
-    /// let mut iter = a.into_iter();
+    /// let mut iter = a.iter();
     ///
     /// let result: Vec<i32> = iter.by_ref()
     ///                            .take_while(|n| **n != 3)
@@ -1321,7 +1321,7 @@ fn inspect<F>(self, f: F) -> Inspect<Self, F> where
     /// ```
     /// let a = [1, 2, 3];
     ///
-    /// let iter = a.into_iter();
+    /// let iter = a.iter();
     ///
     /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i );
     ///
@@ -1334,7 +1334,7 @@ fn inspect<F>(self, f: F) -> Inspect<Self, F> where
     /// // let's try that again
     /// let a = [1, 2, 3];
     ///
-    /// let mut iter = a.into_iter();
+    /// let mut iter = a.iter();
     ///
     /// // instead, we add in a .by_ref()
     /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i );
@@ -1479,7 +1479,7 @@ fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized {
     /// let a = [1, 2, 3];
     ///
     /// let (even, odd): (Vec<i32>, Vec<i32>) = a
-    ///     .into_iter()
+    ///     .iter()
     ///     .partition(|&n| n % 2 == 0);
     ///
     /// assert_eq!(even, vec![2]);
index 28db55578c3de7972a2d19b1795a337675e925b3..4a70329b64bc983a7d43b0b4214be77d892c8447 100644 (file)
 #![feature(structural_match)]
 #![feature(abi_unadjusted)]
 #![feature(adx_target_feature)]
-#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)]
+#![feature(maybe_uninit_slice, maybe_uninit_array)]
 #![feature(external_doc)]
 
 #[prelude_import]
index 9fb071d29524bee5abfc0694c77f155da4a1b405..24bee6355a7ccfe41f9e868b32a71718b52a2fcb 100644 (file)
 /// The practical use cases for `forget` are rather specialized and mainly come
 /// up in unsafe or FFI code.
 ///
-/// ## Use case 1
-///
-/// You have created an uninitialized value using [`mem::uninitialized`][uninit].
-/// You must either initialize or `forget` it on every computation path before
-/// Rust drops it automatically, like at the end of a scope or after a panic.
-/// Running the destructor on an uninitialized value would be [undefined behavior][ub].
-///
-/// ```
-/// use std::mem;
-/// use std::ptr;
-///
-/// # let some_condition = false;
-/// unsafe {
-///     let mut uninit_vec: Vec<u32> = mem::uninitialized();
-///
-///     if some_condition {
-///         // Initialize the variable.
-///         ptr::write(&mut uninit_vec, Vec::new());
-///     } else {
-///         // Forget the uninitialized value so its destructor doesn't run.
-///         mem::forget(uninit_vec);
-///     }
-/// }
-/// ```
-///
-/// ## Use case 2
-///
-/// You have duplicated the bytes making up a value, without doing a proper
-/// [`Clone`][clone]. You need the value's destructor to run only once,
-/// because a double `free` is undefined behavior.
-///
-/// An example is a possible implementation of [`mem::swap`][swap]:
-///
-/// ```
-/// use std::mem;
-/// use std::ptr;
-///
-/// # #[allow(dead_code)]
-/// fn swap<T>(x: &mut T, y: &mut T) {
-///     unsafe {
-///         // Give ourselves some scratch space to work with
-///         let mut t: T = mem::uninitialized();
-///
-///         // Perform the swap, `&mut` pointers never alias
-///         ptr::copy_nonoverlapping(&*x, &mut t, 1);
-///         ptr::copy_nonoverlapping(&*y, x, 1);
-///         ptr::copy_nonoverlapping(&t, y, 1);
-///
-///         // y and t now point to the same thing, but we need to completely
-///         // forget `t` because we do not want to run the destructor for `T`
-///         // on its value, which is still owned somewhere outside this function.
-///         mem::forget(t);
-///     }
-/// }
-/// ```
-///
 /// [drop]: fn.drop.html
 /// [uninit]: fn.uninitialized.html
 /// [clone]: ../clone/trait.Clone.html
@@ -465,29 +409,37 @@ pub const fn needs_drop<T>() -> bool {
 
 /// Creates a value whose bytes are all zero.
 ///
-/// This has the same effect as allocating space with
-/// [`mem::uninitialized`][uninit] and then zeroing it out. It is useful for
-/// FFI sometimes, but should generally be avoided.
+/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
+/// It is useful for FFI sometimes, but should generally be avoided.
 ///
 /// There is no guarantee that an all-zero byte-pattern represents a valid value of
-/// some type `T`. If `T` has a destructor and the value is destroyed (due to
-/// a panic or the end of a scope) before being initialized, then the destructor
-/// will run on zeroed data, likely leading to [undefined behavior][ub].
-///
-/// See also the documentation for [`mem::uninitialized`][uninit], which has
-/// many of the same caveats.
+/// some type `T`. For example, the all-zero byte-pattern is not a valid value
+/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types
+/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv]
+/// that there always is a valid value in a variable it considers initialized.
 ///
-/// [uninit]: fn.uninitialized.html
+/// [zeroed]: union.MaybeUninit.html#method.zeroed
 /// [ub]: ../../reference/behavior-considered-undefined.html
+/// [inv]: union.MaybeUninit.html#initialization-invariant
 ///
 /// # Examples
 ///
+/// Correct usage of this function: initializing an integer with zero.
+///
 /// ```
 /// use std::mem;
 ///
 /// let x: i32 = unsafe { mem::zeroed() };
 /// assert_eq!(0, x);
 /// ```
+///
+/// *Incorrect* usage of this function: initializing a reference with zero.
+///
+/// ```no_run
+/// use std::mem;
+///
+/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
+/// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn zeroed<T>() -> T {
@@ -498,130 +450,23 @@ pub unsafe fn zeroed<T>() -> T {
 /// Bypasses Rust's normal memory-initialization checks by pretending to
 /// produce a value of type `T`, while doing nothing at all.
 ///
-/// **This is incredibly dangerous and should not be done lightly. Deeply
-/// consider initializing your memory with a default value instead.**
-///
-/// This is useful for FFI functions and initializing arrays sometimes,
-/// but should generally be avoided.
-///
-/// # Undefined behavior
-///
-/// It is [undefined behavior][ub] to read uninitialized memory, even just an
-/// uninitialized boolean. For instance, if you branch on the value of such
-/// a boolean, your program may take one, both, or neither of the branches.
-///
-/// Writing to the uninitialized value is similarly dangerous. Rust believes the
-/// value is initialized, and will therefore try to [`Drop`] the uninitialized
-/// value and its fields if you try to overwrite it in a normal manner. The only way
-/// to safely initialize an uninitialized value is with [`ptr::write`][write],
-/// [`ptr::copy`][copy], or [`ptr::copy_nonoverlapping`][copy_no].
-///
-/// If the value does implement [`Drop`], it must be initialized before
-/// it goes out of scope (and therefore would be dropped). Note that this
-/// includes a `panic` occurring and unwinding the stack suddenly.
+/// **This functon is deprecated.** Use [`MaybeUninit<T>`] instead.
 ///
-/// If you partially initialize an array, you may need to use
-/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully
-/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running
-/// on the array. If a partially allocated array is dropped this will lead to
-/// undefined behaviour.
-///
-/// # Examples
-///
-/// Here's how to safely initialize an array of [`Vec`]s.
-///
-/// ```
-/// use std::mem;
-/// use std::ptr;
-///
-/// // Only declare the array. This safely leaves it
-/// // uninitialized in a way that Rust will track for us.
-/// // However we can't initialize it element-by-element
-/// // safely, and we can't use the `[value; 1000]`
-/// // constructor because it only works with `Copy` data.
-/// let mut data: [Vec<u32>; 1000];
-///
-/// unsafe {
-///     // So we need to do this to initialize it.
-///     data = mem::uninitialized();
-///
-///     // DANGER ZONE: if anything panics or otherwise
-///     // incorrectly reads the array here, we will have
-///     // Undefined Behavior.
-///
-///     // It's ok to mutably iterate the data, since this
-///     // doesn't involve reading it at all.
-///     // (ptr and len are statically known for arrays)
-///     for elem in &mut data[..] {
-///         // *elem = Vec::new() would try to drop the
-///         // uninitialized memory at `elem` -- bad!
-///         //
-///         // Vec::new doesn't allocate or do really
-///         // anything. It's only safe to call here
-///         // because we know it won't panic.
-///         ptr::write(elem, Vec::new());
-///     }
-///
-///     // SAFE ZONE: everything is initialized.
-/// }
-///
-/// println!("{:?}", &data[0]);
-/// ```
-///
-/// This example emphasizes exactly how delicate and dangerous using `mem::uninitialized`
-/// can be. Note that the [`vec!`] macro *does* let you initialize every element with a
-/// value that is only [`Clone`], so the following is semantically equivalent and
-/// vastly less dangerous, as long as you can live with an extra heap
-/// allocation:
-///
-/// ```
-/// let data: Vec<Vec<u32>> = vec![Vec::new(); 1000];
-/// println!("{:?}", &data[0]);
-/// ```
-///
-/// This example shows how to handle partially initialized arrays, which could
-/// be found in low-level datastructures.
-///
-/// ```
-/// use std::mem;
-/// use std::ptr;
-///
-/// // Count the number of elements we have assigned.
-/// let mut data_len: usize = 0;
-/// let mut data: [String; 1000];
-///
-/// unsafe {
-///     data = mem::uninitialized();
-///
-///     for elem in &mut data[0..500] {
-///         ptr::write(elem, String::from("hello"));
-///         data_len += 1;
-///     }
-///
-///     // For each item in the array, drop if we allocated it.
-///     for i in &mut data[0..data_len] {
-///         ptr::drop_in_place(i);
-///     }
-/// }
-/// // Forget the data. If this is allowed to drop, you may see a crash such as:
-/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object
-/// // 0x7ff3b8402920: pointer being freed was not allocated'
-/// mem::forget(data);
-/// ```
+/// The reason for deprecation is that the function basically cannot be used
+/// correctly: [the Rust compiler assumes][inv] that values are properly initialized.
+/// As a consequence, calling e.g. `mem::uninitialized::<bool>()` causes immediate
+/// undefined behavior for returning a `bool` that is not definitely either `true`
+/// or `false`. Worse, truly uninitialized memory like what gets returned here
+/// is special in that the compiler knows that it does not have a fixed value.
+/// This makes it undefined behavior to have uninitialized data in a variable even
+/// if that variable has an integer type.
+/// (Notice that the rules around uninitialized integers are not finalized yet, but
+/// until they are, it is advisable to avoid them.)
 ///
-/// [`Vec`]: ../../std/vec/struct.Vec.html
-/// [`vec!`]: ../../std/macro.vec.html
-/// [`Clone`]: ../../std/clone/trait.Clone.html
-/// [ub]: ../../reference/behavior-considered-undefined.html
-/// [write]: ../ptr/fn.write.html
-/// [drop_in_place]: ../ptr/fn.drop_in_place.html
-/// [mem_zeroed]: fn.zeroed.html
-/// [mem_forget]: fn.forget.html
-/// [copy]: ../intrinsics/fn.copy.html
-/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
-/// [`Drop`]: ../ops/trait.Drop.html
+/// [`MaybeUninit<T>`]: union.MaybeUninit.html
+/// [inv]: union.MaybeUninit.html#initialization-invariant
 #[inline]
-#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninit` instead")]
+#[rustc_deprecated(since = "1.40.0", reason = "use `mem::MaybeUninit` instead")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn uninitialized<T>() -> T {
     intrinsics::panic_if_uninhabited::<T>();
@@ -899,7 +744,6 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
     }
 }
 
-// FIXME: Reference `MaybeUninit` from these docs, once that is stable.
 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
 ///
 /// This wrapper is 0-cost.
@@ -908,6 +752,7 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
 /// As a consequence, it has *no effect* on the assumptions that the compiler makes
 /// about all values being initialized at their type.  In particular, initializing
 /// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
+/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
 ///
 /// # Examples
 ///
@@ -942,6 +787,7 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
 /// ```
 ///
 /// [`mem::zeroed`]: fn.zeroed.html
+/// [`MaybeUninit<T>`]: union.MaybeUninit.html
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -1042,17 +888,18 @@ fn deref_mut(&mut self) -> &mut T {
     }
 }
 
-/// A wrapper to construct uninitialized instances of `T`.
+/// A wrapper type to construct uninitialized instances of `T`.
+///
+/// # Initialization invariant
 ///
 /// The compiler, in general, assumes that variables are properly initialized
 /// at their respective type. For example, a variable of reference type must
 /// be aligned and non-NULL. This is an invariant that must *always* be upheld,
 /// even in unsafe code. As a consequence, zero-initializing a variable of reference
-/// type causes instantaneous undefined behavior, no matter whether that reference
+/// type causes instantaneous [undefined behavior][ub], no matter whether that reference
 /// ever gets used to access memory:
 ///
 /// ```rust,no_run
-/// #![feature(maybe_uninit)]
 /// use std::mem::{self, MaybeUninit};
 ///
 /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
@@ -1067,7 +914,6 @@ fn deref_mut(&mut self) -> &mut T {
 /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
 ///
 /// ```rust,no_run
-/// #![feature(maybe_uninit)]
 /// use std::mem::{self, MaybeUninit};
 ///
 /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
@@ -1078,10 +924,9 @@ fn deref_mut(&mut self) -> &mut T {
 /// Moreover, uninitialized memory is special in that the compiler knows that
 /// it does not have a fixed value. This makes it undefined behavior to have
 /// uninitialized data in a variable even if that variable has an integer type,
-/// which otherwise can hold any bit pattern:
+/// which otherwise can hold any *fixed* bit pattern:
 ///
 /// ```rust,no_run
-/// #![feature(maybe_uninit)]
 /// use std::mem::{self, MaybeUninit};
 ///
 /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
@@ -1091,37 +936,154 @@ fn deref_mut(&mut self) -> &mut T {
 /// (Notice that the rules around uninitialized integers are not finalized yet, but
 /// until they are, it is advisable to avoid them.)
 ///
+/// On top of that, remember that most types have additional invariants beyond merely
+/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
+/// is considered initialized because the only requirement the compiler knows about it
+/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause
+/// *immediate* undefined behavior, but will cause undefined behavior with most
+/// safe operations (including dropping it).
+///
+/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
+///
+/// # Examples
+///
 /// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data.
 /// It is a signal to the compiler indicating that the data here might *not*
 /// be initialized:
 ///
 /// ```rust
-/// #![feature(maybe_uninit)]
 /// use std::mem::MaybeUninit;
 ///
 /// // Create an explicitly uninitialized reference. The compiler knows that data inside
 /// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
 /// let mut x = MaybeUninit::<&i32>::uninit();
 /// // Set it to a valid value.
-/// x.write(&0);
+/// unsafe { x.as_mut_ptr().write(&0); }
 /// // Extract the initialized data -- this is only allowed *after* properly
 /// // initializing `x`!
 /// let x = unsafe { x.assume_init() };
 /// ```
 ///
 /// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
-//
-// FIXME before stabilizing, explain how to initialize a struct field-by-field.
+///
+/// ## out-pointers
+///
+/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data
+/// from a function, pass it a pointer to some (uninitialized) memory to put the
+/// result into. This can be useful when it is important for the caller to control
+/// how the memory the result is stored in gets allocated, and you want to avoid
+/// unnecessary moves.
+///
+/// ```
+/// use std::mem::MaybeUninit;
+///
+/// unsafe fn make_vec(out: *mut Vec<i32>) {
+///     // `write` does not drop the old contents, which is important.
+///     out.write(vec![1, 2, 3]);
+/// }
+///
+/// let mut v: MaybeUninit<Vec<i32>> = MaybeUninit::uninit();
+/// unsafe { make_vec(v.as_mut_ptr()); }
+/// // Now we know `v` is initialized! This also makes sure the vector gets
+/// // properly dropped.
+/// let v = unsafe { v.assume_init() };
+/// assert_eq!(&v, &[1, 2, 3]);
+/// ```
+///
+/// ## Initializing an array element-by-element
+///
+/// `MaybeUninit<T>` can be used to initialize a large array element-by-element:
+///
+/// ```
+/// use std::mem::{self, MaybeUninit};
+/// use std::ptr;
+///
+/// let data = {
+///     // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
+///     // safe because the type we are claiming to have initialized here is a
+///     // bunch of `MaybeUninit`s, which do not require initialization.
+///     let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
+///         MaybeUninit::uninit().assume_init()
+///     };
+///
+///     // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop,
+///     // we have a memory leak, but there is no memory safety issue.
+///     for elem in &mut data[..] {
+///         unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); }
+///     }
+///
+///     // Everything is initialized. Transmute the array to the
+///     // initialized type.
+///     unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
+/// };
+///
+/// assert_eq!(&data[0], &[42]);
+/// ```
+///
+/// You can also work with partially initialized arrays, which could
+/// be found in low-level datastructures.
+///
+/// ```
+/// use std::mem::MaybeUninit;
+/// use std::ptr;
+///
+/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
+/// // safe because the type we are claiming to have initialized here is a
+/// // bunch of `MaybeUninit`s, which do not require initialization.
+/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
+/// // Count the number of elements we have assigned.
+/// let mut data_len: usize = 0;
+///
+/// for elem in &mut data[0..500] {
+///     unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); }
+///     data_len += 1;
+/// }
+///
+/// // For each item in the array, drop if we allocated it.
+/// for elem in &mut data[0..data_len] {
+///     unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
+/// }
+/// ```
+///
+/// ## Initializing a struct field-by-field
+///
+/// There is currently no supported way to create a raw pointer or reference
+/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
+/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
+/// to its fields.
+///
+/// [ub]: ../../reference/behavior-considered-undefined.html
+///
+/// # Layout
+///
+/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
+///
+/// ```rust
+/// use std::mem::{MaybeUninit, size_of, align_of};
+/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>());
+/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>());
+/// ```
+///
+/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same
+/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as
+/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit
+/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling
+/// optimizations, potentially resulting in a larger size:
+///
+/// ```rust
+/// # use std::mem::{MaybeUninit, size_of, align_of};
+/// assert_eq!(size_of::<Option<bool>>(), 1);
+/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
+/// ```
 #[allow(missing_debug_implementations)]
-#[unstable(feature = "maybe_uninit", issue = "53491")]
+#[stable(feature = "maybe_uninit", since = "1.36.0")]
 #[derive(Copy)]
-// NOTE: after stabilizing `MaybeUninit`, proceed to deprecate `mem::uninitialized`.
 pub union MaybeUninit<T> {
     uninit: (),
     value: ManuallyDrop<T>,
 }
 
-#[unstable(feature = "maybe_uninit", issue = "53491")]
+#[stable(feature = "maybe_uninit", since = "1.36.0")]
 impl<T: Copy> Clone for MaybeUninit<T> {
     #[inline(always)]
     fn clone(&self) -> Self {
@@ -1132,10 +1094,13 @@ fn clone(&self) -> Self {
 
 impl<T> MaybeUninit<T> {
     /// Creates a new `MaybeUninit<T>` initialized with the given value.
+    /// It is safe to call [`assume_init`] on the return value of this function.
     ///
     /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
     /// It is your responsibility to make sure `T` gets dropped if it got initialized.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    ///
+    /// [`assume_init`]: #method.assume_init
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline(always)]
     pub const fn new(val: T) -> MaybeUninit<T> {
         MaybeUninit { value: ManuallyDrop::new(val) }
@@ -1145,7 +1110,11 @@ pub const fn new(val: T) -> MaybeUninit<T> {
     ///
     /// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
     /// It is your responsibility to make sure `T` gets dropped if it got initialized.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    ///
+    /// See the [type-level documentation][type] for some examples.
+    ///
+    /// [type]: union.MaybeUninit.html
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline(always)]
     pub const fn uninit() -> MaybeUninit<T> {
         MaybeUninit { uninit: () }
@@ -1166,7 +1135,6 @@ pub const fn uninit() -> MaybeUninit<T> {
     /// fields of the struct can hold the bit-pattern 0 as a valid value.
     ///
     /// ```rust
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let x = MaybeUninit::<(u8, bool)>::zeroed();
@@ -1178,7 +1146,6 @@ pub const fn uninit() -> MaybeUninit<T> {
     /// cannot hold 0 as a valid value.
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// enum NotZero { One = 1, Two = 2 };
@@ -1188,7 +1155,7 @@ pub const fn uninit() -> MaybeUninit<T> {
     /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
     /// // This is undefined behavior.
     /// ```
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline]
     pub fn zeroed() -> MaybeUninit<T> {
         let mut u = MaybeUninit::<T>::uninit();
@@ -1202,7 +1169,7 @@ pub fn zeroed() -> MaybeUninit<T> {
     /// without dropping it, so be careful not to use this twice unless you want to
     /// skip running the destructor. For your convenience, this also returns a mutable
     /// reference to the (now safely initialized) contents of `self`.
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
     #[inline(always)]
     pub fn write(&mut self, val: T) -> &mut T {
         unsafe {
@@ -1213,13 +1180,14 @@ pub fn write(&mut self, val: T) -> &mut T {
 
     /// Gets a pointer to the contained value. Reading from this pointer or turning it
     /// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
+    /// Writing to memory that this pointer (non-transitively) points to is undefined behavior
+    /// (except inside an `UnsafeCell<T>`).
     ///
     /// # Examples
     ///
     /// Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
@@ -1232,7 +1200,6 @@ pub fn write(&mut self, val: T) -> &mut T {
     /// *Incorrect* usage of this method:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let x = MaybeUninit::<Vec<u32>>::uninit();
@@ -1242,7 +1209,7 @@ pub fn write(&mut self, val: T) -> &mut T {
     ///
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline(always)]
     pub fn as_ptr(&self) -> *const T {
         unsafe { &*self.value as *const T }
@@ -1256,7 +1223,6 @@ pub fn as_ptr(&self) -> *const T {
     /// Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
@@ -1271,7 +1237,6 @@ pub fn as_ptr(&self) -> *const T {
     /// *Incorrect* usage of this method:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Vec<u32>>::uninit();
@@ -1281,7 +1246,7 @@ pub fn as_ptr(&self) -> *const T {
     ///
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline(always)]
     pub fn as_mut_ptr(&mut self) -> *mut T {
         unsafe { &mut *self.value as *mut T }
@@ -1294,15 +1259,17 @@ pub fn as_mut_ptr(&mut self) -> *mut T {
     /// # Safety
     ///
     /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
-    /// state. Calling this when the content is not yet fully initialized causes undefined
-    /// behavior.
+    /// state. Calling this when the content is not yet fully initialized causes immediate undefined
+    /// behavior. The [type-level documentation][inv] contains more information about
+    /// this initialization invariant.
+    ///
+    /// [inv]: #initialization-invariant
     ///
     /// # Examples
     ///
     /// Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<bool>::uninit();
@@ -1314,14 +1281,13 @@ pub fn as_mut_ptr(&mut self) -> *mut T {
     /// *Incorrect* usage of this method:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit)]
     /// use std::mem::MaybeUninit;
     ///
     /// let x = MaybeUninit::<Vec<u32>>::uninit();
     /// let x_init = unsafe { x.assume_init() };
     /// // `x` had not been initialized yet, so this last line caused undefined behavior.
     /// ```
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    #[stable(feature = "maybe_uninit", since = "1.36.0")]
     #[inline(always)]
     pub unsafe fn assume_init(self) -> T {
         intrinsics::panic_if_uninhabited::<T>();
@@ -1338,13 +1304,15 @@ pub unsafe fn assume_init(self) -> T {
     ///
     /// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
     /// state. Calling this when the content is not yet fully initialized causes undefined
-    /// behavior.
+    /// behavior. The [type-level documentation][inv] contains more information about
+    /// this initialization invariant.
     ///
     /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
     /// multiple copies of the data (by calling `read` multiple times, or first
     /// calling `read` and then [`assume_init`]), it is your responsibility
     /// to ensure that that data may indeed be duplicated.
     ///
+    /// [inv]: #initialization-invariant
     /// [`assume_init`]: #method.assume_init
     ///
     /// # Examples
@@ -1352,7 +1320,7 @@ pub unsafe fn assume_init(self) -> T {
     /// Correct usage of this method:
     ///
     /// ```rust
-    /// #![feature(maybe_uninit)]
+    /// #![feature(maybe_uninit_extra)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<u32>::uninit();
@@ -1373,7 +1341,7 @@ pub unsafe fn assume_init(self) -> T {
     /// *Incorrect* usage of this method:
     ///
     /// ```rust,no_run
-    /// #![feature(maybe_uninit)]
+    /// #![feature(maybe_uninit_extra)]
     /// use std::mem::MaybeUninit;
     ///
     /// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
@@ -1383,7 +1351,7 @@ pub unsafe fn assume_init(self) -> T {
     /// // We now created two copies of the same vector, leading to a double-free when
     /// // they both get dropped!
     /// ```
-    #[unstable(feature = "maybe_uninit", issue = "53491")]
+    #[unstable(feature = "maybe_uninit_extra", issue = "53491")]
     #[inline(always)]
     pub unsafe fn read(&self) -> T {
         intrinsics::panic_if_uninhabited::<T>();
index b6de9f57b0110439227d2ba8ae5797761595b922..006b1e143eeec54772b4f7d06c385ad3b6c53c3f 100644 (file)
 /// location first:
 /// ```
 /// use std::ptr;
-/// use std::mem;
+/// use std::mem::{self, MaybeUninit};
 ///
 /// unsafe fn drop_after_copy<T>(to_drop: *mut T) {
-///     let mut copy: T = mem::uninitialized();
-///     ptr::copy(to_drop, &mut copy, 1);
-///     drop(copy);
+///     let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
+///     ptr::copy(to_drop, copy.as_mut_ptr(), 1);
+///     drop(copy.assume_init());
 /// }
 ///
 /// #[repr(packed, C)]
@@ -810,9 +810,6 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 /// to not be elided or reordered by the compiler across other volatile
 /// operations.
 ///
-/// Memory accessed with `read_volatile` or [`write_volatile`] should not be
-/// accessed with non-volatile operations.
-///
 /// [`write_volatile`]: ./fn.write_volatile.html
 ///
 /// # Notes
@@ -837,7 +834,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 ///
 /// * `src` must be properly aligned.
 ///
-/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of
+/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
 /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
 /// value and the value at `*src` can [violate memory safety][read-ownership].
 /// However, storing non-[`Copy`] types in volatile memory is almost certainly
@@ -881,9 +878,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 /// to not be elided or reordered by the compiler across other volatile
 /// operations.
 ///
-/// Memory accessed with [`read_volatile`] or `write_volatile` should not be
-/// accessed with non-volatile operations.
-///
 /// `write_volatile` does not drop the contents of `dst`. This is safe, but it
 /// could leak allocations or resources, so care should be taken not to overwrite
 /// an object that should be dropped.
index b4e91249832051d7d6fa7482669c6f5bfbb186e7..a6d611d2e93c4b83847a9791a39a28bb1a270e14 100644 (file)
@@ -10,6 +10,8 @@
 ///
 /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that
 /// customizes the behavior of the `RawWaker`.
+///
+/// [`Waker`]: struct.Waker.html
 #[derive(PartialEq, Debug)]
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub struct RawWaker {
@@ -55,6 +57,8 @@ pub const fn new(data: *const (), vtable: &'static RawWakerVTable) -> RawWaker {
 /// pointer of a properly constructed [`RawWaker`] object from inside the
 /// [`RawWaker`] implementation. Calling one of the contained functions using
 /// any other `data` pointer will cause undefined behavior.
+///
+/// [`RawWaker`]: struct.RawWaker.html
 #[stable(feature = "futures_api", since = "1.36.0")]
 #[derive(PartialEq, Copy, Clone, Debug)]
 pub struct RawWakerVTable {
@@ -65,6 +69,9 @@ pub struct RawWakerVTable {
     /// required for this additional instance of a [`RawWaker`] and associated
     /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup
     /// of the same task that would have been awoken by the original [`RawWaker`].
+    ///
+    /// [`Waker`]: struct.Waker.html
+    /// [`RawWaker`]: struct.RawWaker.html
     clone: unsafe fn(*const ()) -> RawWaker,
 
     /// This function will be called when `wake` is called on the [`Waker`].
@@ -73,6 +80,9 @@ pub struct RawWakerVTable {
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
     /// associated task.
+    ///
+    /// [`Waker`]: struct.Waker.html
+    /// [`RawWaker`]: struct.RawWaker.html
     wake: unsafe fn(*const ()),
 
     /// This function will be called when `wake_by_ref` is called on the [`Waker`].
@@ -80,6 +90,9 @@ pub struct RawWakerVTable {
     ///
     /// This function is similar to `wake`, but must not consume the provided data
     /// pointer.
+    ///
+    /// [`Waker`]: struct.Waker.html
+    /// [`RawWaker`]: struct.RawWaker.html
     wake_by_ref: unsafe fn(*const ()),
 
     /// This function gets called when a [`RawWaker`] gets dropped.
@@ -87,6 +100,8 @@ pub struct RawWakerVTable {
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
     /// associated task.
+    ///
+    /// [`RawWaker`]: struct.RawWaker.html
     drop: unsafe fn(*const ()),
 }
 
@@ -128,6 +143,9 @@ impl RawWakerVTable {
     /// The implementation of this function must make sure to release any
     /// resources that are associated with this instance of a [`RawWaker`] and
     /// associated task.
+    ///
+    /// [`Waker`]: struct.Waker.html
+    /// [`RawWaker`]: struct.RawWaker.html
     #[rustc_promotable]
     #[cfg_attr(stage0, unstable(feature = "futures_api_const_fn_ptr", issue = "50547"))]
     #[cfg_attr(not(stage0), stable(feature = "futures_api", since = "1.36.0"))]
@@ -201,6 +219,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// executor-specific wakeup behavior.
 ///
 /// Implements [`Clone`], [`Send`], and [`Sync`].
+///
+/// [`RawWaker`]: struct.RawWaker.html
 #[repr(transparent)]
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Waker {
@@ -266,6 +286,9 @@ pub fn will_wake(&self, other: &Waker) -> bool {
     /// The behavior of the returned `Waker` is undefined if the contract defined
     /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld.
     /// Therefore this method is unsafe.
+    ///
+    /// [`RawWaker`]: struct.RawWaker.html
+    /// [`RawWakerVTable`]: struct.RawWakerVTable.html
     #[inline]
     #[stable(feature = "futures_api", since = "1.36.0")]
     pub unsafe fn from_raw(waker: RawWaker) -> Waker {
diff --git a/src/libcore/tests/alloc.rs b/src/libcore/tests/alloc.rs
new file mode 100644 (file)
index 0000000..63537ba
--- /dev/null
@@ -0,0 +1,10 @@
+use core::alloc::Layout;
+
+#[test]
+fn const_unchecked_layout() {
+    const SIZE: usize = 0x2000;
+    const ALIGN: usize = 0x1000;
+    const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) };
+    assert_eq!(LAYOUT.size(), SIZE);
+    assert_eq!(LAYOUT.align(), ALIGN);
+}
index b8075ef2942e083d67d7af6f5778b68fcb7b648a..c617596aba80159af2ecb5f3c4967bc099897f8f 100644 (file)
 #![feature(slice_partition_dedup)]
 #![feature(copy_within)]
 #![feature(int_error_matching)]
+#![feature(const_fn)]
 #![warn(rust_2018_idioms)]
 
 extern crate test;
 
+mod alloc;
 mod any;
 mod array;
 mod ascii;
index b268a1a494d107cc92b1996b51374f89e61fd2e9..0c4f5fb3fc167bd701087e504c7fa5feab06c876 100644 (file)
@@ -96,34 +96,20 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl serialize::UseSpecializedEncodable for CrateNum {}
 impl serialize::UseSpecializedDecodable for CrateNum {}
 
-/// A DefIndex is an index into the hir-map for a crate, identifying a
-/// particular definition. It should really be considered an interned
-/// shorthand for a particular DefPath.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
-pub struct DefIndex(u32);
-
-/// The crate root is always assigned index 0 by the AST Map code,
-/// thanks to `NodeCollector::new`.
-pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
+newtype_index! {
+    /// A DefIndex is an index into the hir-map for a crate, identifying a
+    /// particular definition. It should really be considered an interned
+    /// shorthand for a particular DefPath.
+    pub struct DefIndex {
+        DEBUG_FORMAT = "DefIndex({})",
 
-impl fmt::Debug for DefIndex {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "DefIndex({})", self.as_array_index())
+        /// The crate root is always assigned index 0 by the AST Map code,
+        /// thanks to `NodeCollector::new`.
+        const CRATE_DEF_INDEX = 0,
     }
 }
 
 impl DefIndex {
-    /// Converts this DefIndex into a zero-based array index.
-    #[inline]
-    pub fn as_array_index(&self) -> usize {
-        self.0 as usize
-    }
-
-    #[inline]
-    pub fn from_array_index(i: usize) -> DefIndex {
-        DefIndex(i as u32)
-    }
-
     // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This
     // function maps the index of the macro within the crate (which is also the
     // index of the macro in the CrateMetadata::proc_macros array) to the
@@ -132,7 +118,7 @@ pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
         // DefIndex for proc macros start from FIRST_FREE_DEF_INDEX,
         // because the first FIRST_FREE_DEF_INDEX indexes are reserved
         // for internal use.
-        let def_index = DefIndex::from_array_index(
+        let def_index = DefIndex::from(
             proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX)
                 .expect("integer overflow adding `proc_macro_index`"));
         assert!(def_index != CRATE_DEF_INDEX);
@@ -141,19 +127,11 @@ pub fn from_proc_macro_index(proc_macro_index: usize) -> DefIndex {
 
     // This function is the reverse of from_proc_macro_index() above.
     pub fn to_proc_macro_index(self: DefIndex) -> usize {
-        self.as_array_index().checked_sub(FIRST_FREE_DEF_INDEX)
+        self.index().checked_sub(FIRST_FREE_DEF_INDEX)
             .unwrap_or_else(|| {
                 bug!("using local index {:?} as proc-macro index", self)
             })
     }
-
-    pub fn from_raw_u32(x: u32) -> DefIndex {
-        DefIndex(x)
-    }
-
-    pub fn as_raw_u32(&self) -> u32 {
-        self.0
-    }
 }
 
 impl serialize::UseSpecializedEncodable for DefIndex {}
@@ -169,7 +147,7 @@ pub struct DefId {
 
 impl fmt::Debug for DefId {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "DefId({}:{}", self.krate, self.index.as_array_index())?;
+        write!(f, "DefId({}:{}", self.krate, self.index.index())?;
 
         ty::tls::with_opt(|opt_tcx| {
             if let Some(tcx) = opt_tcx {
index 970f6ba01773557ebc8d94203fba55f4160b52f8..3ec4d4e8cc8f68350eba397be435676d2c89fc91 100644 (file)
@@ -855,10 +855,6 @@ fn diagnostic(&self) -> &errors::Handler {
         self.sess.diagnostic()
     }
 
-    fn str_to_ident(&self, s: &'static str) -> Ident {
-        Ident::with_empty_ctxt(Symbol::gensym(s))
-    }
-
     fn with_anonymous_lifetime_mode<R>(
         &mut self,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
@@ -4621,18 +4617,18 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 );
                 head.span = desugared_span;
 
-                let iter = self.str_to_ident("iter");
+                let iter = Ident::with_empty_ctxt(sym::iter);
 
-                let next_ident = self.str_to_ident("__next");
+                let next_ident = Ident::with_empty_ctxt(sym::__next);
                 let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
                     desugared_span,
                     next_ident,
                     hir::BindingAnnotation::Mutable,
                 );
 
-                // `::std::option::Option::Some(val) => next = val`
+                // `::std::option::Option::Some(val) => __next = val`
                 let pat_arm = {
-                    let val_ident = self.str_to_ident("val");
+                    let val_ident = Ident::with_empty_ctxt(sym::val);
                     let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
                     let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
                     let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
@@ -4771,17 +4767,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let unstable_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     e.span,
-                    Some(vec![
-                        Symbol::intern("try_trait")
-                    ].into()),
+                    Some(vec![sym::try_trait].into()),
                 );
                 let try_span = self.sess.source_map().end_point(e.span);
                 let try_span = self.sess.source_map().mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     try_span,
-                    Some(vec![
-                        Symbol::intern("try_trait")
-                    ].into()),
+                    Some(vec![sym::try_trait].into()),
                 );
 
                 // `Try::into_result(<expr>)`
@@ -4802,7 +4794,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     // `allow(unreachable_code)`
                     let allow = {
                         let allow_ident = Ident::with_empty_ctxt(sym::allow).with_span_pos(e.span);
-                        let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span);
+                        let uc_ident = Ident::with_empty_ctxt(sym::unreachable_code)
+                            .with_span_pos(e.span);
                         let uc_nested = attr::mk_nested_word_item(uc_ident);
                         attr::mk_list_item(e.span, allow_ident, vec![uc_nested])
                     };
@@ -4812,7 +4805,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 // `Ok(val) => #[allow(unreachable_code)] val,`
                 let ok_arm = {
-                    let val_ident = self.str_to_ident("val");
+                    let val_ident = Ident::with_empty_ctxt(sym::val);
                     let (val_pat, val_pat_nid) = self.pat_ident(e.span, val_ident);
                     let val_expr = P(self.expr_ident_with_attrs(
                         e.span,
@@ -4828,7 +4821,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 // `Err(err) => #[allow(unreachable_code)]
                 //              return Try::from_error(From::from(err)),`
                 let err_arm = {
-                    let err_ident = self.str_to_ident("err");
+                    let err_ident = Ident::with_empty_ctxt(sym::err);
                     let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
                     let from_expr = {
                         let from_path = &[sym::convert, sym::From, sym::from];
@@ -5552,7 +5545,7 @@ fn lower_await(
         //         match ::std::future::poll_with_tls_context(unsafe {
         //             ::std::pin::Pin::new_unchecked(&mut pinned)
         //         }) {
-        //             ::std::task::Poll::Ready(x) => break x,
+        //             ::std::task::Poll::Ready(result) => break result,
         //             ::std::task::Poll::Pending => {},
         //         }
         //         yield ();
@@ -5580,12 +5573,12 @@ fn lower_await(
         let gen_future_span = self.sess.source_map().mark_span_with_reason(
             CompilerDesugaringKind::Await,
             await_span,
-            Some(vec![Symbol::intern("gen_future")].into()),
+            Some(vec![sym::gen_future].into()),
         );
 
         // let mut pinned = <expr>;
         let expr = P(self.lower_expr(expr));
-        let pinned_ident = self.str_to_ident("pinned");
+        let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
         let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
             span,
             pinned_ident,
@@ -5621,11 +5614,11 @@ fn lower_await(
             ))
         };
 
-        // `::std::task::Poll::Ready(x) => break x`
+        // `::std::task::Poll::Ready(result) => break result`
         let loop_node_id = self.sess.next_node_id();
         let loop_hir_id = self.lower_node_id(loop_node_id);
         let ready_arm = {
-            let x_ident = self.str_to_ident("x");
+            let x_ident = Ident::with_empty_ctxt(sym::result);
             let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
             let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
             let ready_pat = self.pat_std_enum(
index a1cf338bf12ea991e6199dc2363cafc34ffe6723..eeba628b3bf2168ad943ac41fe4cca076ed5bf72 100644 (file)
@@ -226,7 +226,7 @@ pub(super) fn finalize_and_compute_crate_hash(mut self,
 
     fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) {
         debug!("hir_map: {:?} => {:?}", id, entry);
-        let local_map = &mut self.map[id.owner.as_array_index()];
+        let local_map = &mut self.map[id.owner.index()];
         let i = id.local_id.as_u32() as usize;
         if local_map.is_none() {
             *local_map = Some(IndexVec::with_capacity(i + 1));
index 9cb85c4db47579f8403de8d8369a5de6138226cd..1cc9a2c0e8a1b9d875b7f9a31520c5644f727e76 100644 (file)
@@ -38,7 +38,7 @@ fn allocate(&mut self,
                 def_path_hash: DefPathHash)
                 -> DefIndex {
         let index = {
-            let index = DefIndex::from_array_index(self.index_to_key.len());
+            let index = DefIndex::from(self.index_to_key.len());
             debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
             self.index_to_key.push(key);
             index
@@ -49,17 +49,17 @@ fn allocate(&mut self,
     }
 
     pub fn next_id(&self) -> DefIndex {
-        DefIndex::from_array_index(self.index_to_key.len())
+        DefIndex::from(self.index_to_key.len())
     }
 
     #[inline(always)]
     pub fn def_key(&self, index: DefIndex) -> DefKey {
-        self.index_to_key[index.as_array_index()].clone()
+        self.index_to_key[index.index()].clone()
     }
 
     #[inline(always)]
     pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        let ret = self.def_path_hashes[index.as_array_index()];
+        let ret = self.def_path_hashes[index.index()];
         debug!("def_path_hash({:?}) = {:?}", index, ret);
         return ret
     }
@@ -74,7 +74,7 @@ pub fn add_def_path_hashes_to(&self,
                 .map(|(index, &hash)| {
                     let def_id = DefId {
                         krate: cnum,
-                        index: DefIndex::from_array_index(index),
+                        index: DefIndex::from(index),
                     };
                     (hash, def_id)
                 })
@@ -387,7 +387,7 @@ pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
     #[inline]
     pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
         if def_id.krate == LOCAL_CRATE {
-            let node_id = self.def_index_to_node[def_id.index.as_array_index()];
+            let node_id = self.def_index_to_node[def_id.index.index()];
             if node_id != ast::DUMMY_NODE_ID {
                 return Some(node_id);
             }
@@ -417,7 +417,7 @@ pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId {
 
     #[inline]
     pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId {
-        let node_id = self.def_index_to_node[def_index.as_array_index()];
+        let node_id = self.def_index_to_node[def_index.index()];
         self.node_to_hir_id[node_id]
     }
 
@@ -508,7 +508,7 @@ pub fn create_def_with_parent(&mut self,
 
         // Create the definition.
         let index = self.table.allocate(key, def_path_hash);
-        assert_eq!(index.as_array_index(), self.def_index_to_node.len());
+        assert_eq!(index.index(), self.def_index_to_node.len());
         self.def_index_to_node.push(node_id);
 
         // Some things for which we allocate DefIndices don't correspond to
@@ -653,7 +653,7 @@ pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex {
                                           .position(|k| *k == def_key)
                                           .unwrap();
 
-                DefIndex::from_array_index(index)
+                DefIndex::from(index)
             }
 
             fn name(&self) -> Symbol {
index b8ee98551a20e758f4b025f7fc54167a87bd2309..4b94f772554e76910aa228856853fe0ad3e65cb0 100644 (file)
@@ -189,7 +189,7 @@ pub struct Map<'hir> {
 impl<'hir> Map<'hir> {
     #[inline]
     fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> {
-        let local_map = self.map.get(id.owner.as_array_index())?;
+        let local_map = self.map.get(id.owner.index())?;
         local_map.as_ref()?.get(id.local_id)?.as_ref()
     }
 
@@ -1023,7 +1023,7 @@ fn all_ids<'a>(&'a self) -> impl Iterator<Item = HirId> + 'a {
             local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| {
                 // Reconstruct the HirId based on the 3 indices we used to find it
                 HirId {
-                    owner: DefIndex::from_array_index(array_index),
+                    owner: DefIndex::from(array_index),
                     local_id: i,
                 }
             }))
index f407be4e87b828390db961551aa7d19e24607e1d..57304c5ed37aec722b0f860cab48ff126235fb2f 100644 (file)
@@ -609,9 +609,9 @@ pub fn own_counts(&self) -> GenericParamCount {
         own_counts
     }
 
-    pub fn get_named(&self, name: &InternedString) -> Option<&GenericParam> {
+    pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> {
         for param in &self.params {
-            if *name == param.name.ident().as_interned_str() {
+            if name == param.name.ident().as_interned_str() {
                 return Some(param);
             }
         }
@@ -1356,7 +1356,7 @@ pub struct Expr {
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 72);
+static_assert_size!(Expr, 72);
 
 impl Expr {
     pub fn precedence(&self) -> ExprPrecedence {
index 4b6e7da333081891add336eb6ac22a3fd79f80b0..e4505a240379f0047bbde6f12e9f1e85c2f7612d 100644 (file)
@@ -194,20 +194,20 @@ fn msg_span_from_early_bound_and_free_regions(
                 let mut sp = cm.def_span(self.hir().span_by_hir_id(node));
                 if let Some(param) = self.hir()
                     .get_generics(scope)
-                    .and_then(|generics| generics.get_named(&br.name))
+                    .and_then(|generics| generics.get_named(br.name))
                 {
                     sp = param.span;
                 }
                 (format!("the lifetime {} as defined on", br.name), sp)
             }
             ty::ReFree(ty::FreeRegion {
-                bound_region: ty::BoundRegion::BrNamed(_, ref name),
+                bound_region: ty::BoundRegion::BrNamed(_, name),
                 ..
             }) => {
                 let mut sp = cm.def_span(self.hir().span_by_hir_id(node));
                 if let Some(param) = self.hir()
                     .get_generics(scope)
-                    .and_then(|generics| generics.get_named(&name))
+                    .and_then(|generics| generics.get_named(name))
                 {
                     sp = param.span;
                 }
index 3ed28a1f9882562f495db732b2052a5dc41f46b9..feade7a8f56f26d1c8b7e4b73e8bca45f4d8af60 100644 (file)
@@ -43,7 +43,7 @@ pub(super) fn find_arg_with_region(
     ) -> Option<AnonymousArgInfo<'_>> {
         let (id, bound_region) = match *anon_region {
             ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
-            ty::ReEarlyBound(ref ebr) => (
+            ty::ReEarlyBound(ebr) => (
                 self.tcx().parent(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name),
             ),
index 073a3f74422c6ff2bdf82ca62f0e3fe2f7b4ecc6..1878afd581dd48746bc6fd4a2512f39ba2848d00 100644 (file)
@@ -56,7 +56,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
     }
 
     let requested_node = env::var("RUST_REGION_GRAPH_NODE")
-        .ok().and_then(|s| s.parse().map(DefIndex::from_raw_u32).ok());
+        .ok().and_then(|s| s.parse().map(DefIndex::from_u32).ok());
 
     if requested_node.is_some() && requested_node != Some(context.index) {
         return;
@@ -90,7 +90,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
             let mut new_str = String::new();
             for c in output_template.chars() {
                 if c == '%' {
-                    new_str.push_str(&context.index.as_raw_u32().to_string());
+                    new_str.push_str(&context.index.as_u32().to_string());
                 } else {
                     new_str.push(c);
                 }
index e713cf8d805531669f4d6a4759d046986e0240f2..7e1e751e856478197de92a2e69dc2e2b86ebcea3 100644 (file)
@@ -828,8 +828,8 @@ fn path_qualified(
 
                 // This shouldn't ever be needed, but just in case:
                 Ok(vec![match trait_ref {
-                    Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(),
-                    None => Symbol::intern(&format!("<{}>", self_ty)).as_str(),
+                    Some(trait_ref) => LocalInternedString::intern(&format!("{:?}", trait_ref)),
+                    None => LocalInternedString::intern(&format!("<{}>", self_ty)),
                 }])
             }
 
@@ -845,9 +845,10 @@ fn path_append_impl(
                 // This shouldn't ever be needed, but just in case:
                 path.push(match trait_ref {
                     Some(trait_ref) => {
-                        Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str()
+                        LocalInternedString::intern(&format!("<impl {} for {}>", trait_ref,
+                                                    self_ty))
                     },
-                    None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
+                    None => LocalInternedString::intern(&format!("<impl {}>", self_ty)),
                 });
 
                 Ok(path)
index 68b65f9b4a1ccfa9c948d76a4f1b8310e209f9a3..9c4683e094634eea384d348ff8c2b9785a6c6dfe 100644 (file)
@@ -778,6 +778,9 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
 
     let push = builder.levels.push(&krate.attrs);
     builder.levels.register_id(hir::CRATE_HIR_ID);
+    for macro_def in &krate.exported_macros {
+       builder.levels.register_id(macro_def.hir_id);
+    }
     intravisit::walk_crate(&mut builder, krate);
     builder.levels.pop(push);
 
index 8ef4e9ac8f45faeb357b0a56aa5b172e84967c55..37681ad7fcdd2bc51708264a8246e7a8a3ede9f0 100644 (file)
@@ -158,7 +158,7 @@ pub struct FirstStatementIndex { .. }
 impl_stable_hash_for!(struct crate::middle::region::FirstStatementIndex { private });
 
 // compilation error if size of `ScopeData` is not the same as a `u32`
-static_assert!(ASSERT_SCOPE_DATA: mem::size_of::<ScopeData>() == 4);
+static_assert_size!(ScopeData, 4);
 
 impl Scope {
     /// Returns a item-local ID associated with this scope.
index 75e0f704a58545e239e05f14ba0ad9990cf8bb46..59b7891b90fde918284e32a82dfdf68ffa0aeeec 100644 (file)
@@ -78,7 +78,7 @@ pub struct Pointer<Tag=(),Id=AllocId> {
     pub tag: Tag,
 }
 
-static_assert!(POINTER_SIZE: ::std::mem::size_of::<Pointer>() == 16);
+static_assert_size!(Pointer, 16);
 
 /// Produces a `Pointer` which points to the beginning of the Allocation
 impl From<AllocId> for Pointer {
index 7e45568725f3557c67e0c021ee700881a6e14832..551b86390db4c43d1e0a3253cf2a16c11776c2ae 100644 (file)
@@ -54,7 +54,7 @@ pub enum ConstValue<'tcx> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(CONST_SIZE: ::std::mem::size_of::<ConstValue<'static>>() == 40);
+static_assert_size!(ConstValue<'_>, 40);
 
 impl<'tcx> ConstValue<'tcx> {
     #[inline]
@@ -111,7 +111,7 @@ pub enum Scalar<Tag=(), Id=AllocId> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(SCALAR_SIZE: ::std::mem::size_of::<Scalar>() == 24);
+static_assert_size!(Scalar, 24);
 
 impl<Tag> fmt::Display for Scalar<Tag> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
index bd67aabfe8e5f77b5688231077929dad626236f6..dd43cb2f18ece8d3c09ec480dc786b12f97c2295 100644 (file)
@@ -1738,7 +1738,7 @@ pub struct Statement<'tcx> {
 
 // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Statement<'_>>() == 56);
+static_assert_size!(Statement<'_>, 56);
 
 impl<'tcx> Statement<'tcx> {
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
@@ -1997,10 +1997,9 @@ pub enum ProjectionElem<V, T> {
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
-// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
-static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
-    mem::size_of::<PlaceElem<'_>>() <= 16
-);
+// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(PlaceElem<'_>, 16);
 
 /// Alias for projections as they appear in `UserTypeProjection`, where we
 /// need neither the `V` parameter for `Index` nor the `T` for `Field`.
index e82e90ede8c103daf1c91cca1a5daa669612b3bc..a26468b0fb6ce0560bc1a1cb46c404dddd0a1872 100644 (file)
@@ -1,6 +1,6 @@
 use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use crate::hir::HirId;
-use syntax::symbol::{Symbol, InternedString};
+use syntax::symbol::InternedString;
 use crate::ty::{Instance, TyCtxt};
 use crate::util::nodemap::FxHashMap;
 use rustc_data_structures::base_n;
@@ -280,7 +280,7 @@ pub fn build_cgu_name<I, C, S>(&mut self,
             cgu_name
         } else {
             let cgu_name = &cgu_name.as_str()[..];
-            Symbol::intern(&CodegenUnit::mangle_name(cgu_name)).as_interned_str()
+            InternedString::intern(&CodegenUnit::mangle_name(cgu_name))
         }
     }
 
@@ -336,6 +336,6 @@ pub fn build_cgu_name_no_mangle<I, C, S>(&mut self,
             write!(cgu_name, ".{}", special_suffix).unwrap();
         }
 
-        Symbol::intern(&cgu_name[..]).as_interned_str()
+        InternedString::intern(&cgu_name[..])
     }
 }
index d3fa5e84b6ad1fde4e98cd251752e372587b1cf2..5135aeb2392cd85e054023c22c1cf6077a004bac 100644 (file)
@@ -17,9 +17,9 @@ pub struct PlaceTy<'tcx> {
     pub variant_index: Option<VariantIdx>,
 }
 
-static_assert!(PLACE_TY_IS_3_PTRS_LARGE:
-    mem::size_of::<PlaceTy<'_>>() <= 24
-);
+// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers.
+#[cfg(target_arch = "x86_64")]
+static_assert_size!(PlaceTy<'_>, 16);
 
 impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> {
index df2688397102299ab0c1602a27fd53a27e714cea..9019c4a0575d40b9c5c12df1aa7fb6335cd946cf 100644 (file)
@@ -643,13 +643,16 @@ pub fn report_selection_error(
                             .map(|s| &s == "?")
                             .unwrap_or(false);
                         let is_from = format!("{}", trait_ref).starts_with("std::convert::From<");
-                        let message = if is_try && is_from {
-                            Some(format!(
+                        let (message, note) = if is_try && is_from {
+                            (Some(format!(
                                 "`?` couldn't convert the error to `{}`",
                                 trait_ref.self_ty(),
+                            )), Some(
+                                "the question mark operation (`?`) implicitly performs a \
+                                 conversion on the error value using the `From` trait".to_owned()
                             ))
                         } else {
-                            message
+                            (message, note)
                         };
 
                         let mut err = struct_span_err!(
index 1c8ea5c7b9c5b0dd437301f536a24c15e19472f9..55216f644a180626fdf1eb15369ce64999fe8c1a 100644 (file)
@@ -18,7 +18,8 @@
 use crate::ty::subst::{Subst, InternalSubsts};
 use std::borrow::Cow;
 use std::iter::{self};
-use syntax::ast::{self, Name};
+use syntax::ast::{self};
+use syntax::symbol::InternedString;
 use syntax_pos::Span;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -539,7 +540,7 @@ fn receiver_is_dispatchable(
         // are implemented
         let unsized_self_ty: Ty<'tcx> = self.mk_ty_param(
             ::std::u32::MAX,
-            Name::intern("RustaceansAreAwesome").as_interned_str(),
+            InternedString::intern("RustaceansAreAwesome"),
         );
 
         // `Receiver[Self => U]`
index fc20735eb0f6726b90ee705e0f5dfe32719b1400..fdd1a821e31b56964bae3db7af15581bc05fd1a7 100644 (file)
@@ -298,7 +298,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
     // negated `CrateNum` (so remote definitions are visited first) and then
     // by a flattened version of the `DefIndex`.
     trait_impls.sort_unstable_by_key(|def_id| {
-        (-(def_id.krate.as_u32() as i64), def_id.index.as_array_index())
+        (-(def_id.krate.as_u32() as i64), def_id.index.index())
     });
 
     for impl_def_id in trait_impls {
index 400a0f526c4ef887e3bdf7c8c7ade4816b4fa13d..404fadbc78afce2119335eff2afcfde7e9876c04 100644 (file)
@@ -312,17 +312,15 @@ fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
     }
 
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
-        use syntax::symbol::Symbol;
-
         match t.sty {
             ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
                 self.types.insert(
                     bound_ty.var.as_u32(),
                     match bound_ty.kind {
                         ty::BoundTyKind::Param(name) => name,
-                        ty::BoundTyKind::Anon => Symbol::intern(
-                            &format!("^{}", bound_ty.var.as_u32())
-                        ).as_interned_str(),
+                        ty::BoundTyKind::Anon =>
+                            InternedString::intern(&format!("^{}", bound_ty.var.as_u32()),
+                        ),
                     }
                 );
             }
@@ -334,8 +332,6 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
-        use syntax::symbol::Symbol;
-
         match r {
             ty::ReLateBound(index, br) if *index == self.binder_index => {
                 match br {
@@ -344,9 +340,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
                     }
 
                     ty::BoundRegion::BrAnon(var) => {
-                        self.regions.insert(Symbol::intern(
-                            &format!("'^{}", var)
-                        ).as_interned_str());
+                        self.regions.insert(InternedString::intern(&format!("'^{}", var)));
                     }
 
                     _ => (),
index 2f71861d4dc0df57d8de5e9e87da1036af49eec2..91e996178e7d54904cbdde900e8524bf60d1f5da 100644 (file)
@@ -510,7 +510,7 @@ pub struct TyS<'tcx> {
 
 // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TY_S: ::std::mem::size_of::<TyS<'_>>() == 32);
+static_assert_size!(TyS<'_>, 32);
 
 impl<'tcx> Ord for TyS<'tcx> {
     fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
@@ -3405,7 +3405,7 @@ pub struct SymbolName {
 impl SymbolName {
     pub fn new(name: &str) -> SymbolName {
         SymbolName {
-            name: Symbol::intern(name).as_interned_str()
+            name: InternedString::intern(name)
         }
     }
 
index 8e98d4d85b9cc04d437fc2d24d014575ae819de4..91b708d7dbe10339d00813f79f85cfd108a4f57b 100644 (file)
@@ -7,10 +7,8 @@
 use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
 use crate::ty::subst::{Kind, Subst, UnpackedKind};
 use crate::mir::interpret::ConstValue;
-use syntax::symbol::{keywords, Symbol};
-
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::InternedString;
+use syntax::symbol::{keywords, InternedString};
 
 use std::cell::Cell;
 use std::fmt::{self, Write as _};
@@ -1285,10 +1283,10 @@ pub fn pretty_in_binder<T>(
     {
         fn name_by_region_index(index: usize) -> InternedString {
             match index {
-                0 => Symbol::intern("'r"),
-                1 => Symbol::intern("'s"),
-                i => Symbol::intern(&format!("'t{}", i-2)),
-            }.as_interned_str()
+                0 => InternedString::intern("'r"),
+                1 => InternedString::intern("'s"),
+                i => InternedString::intern(&format!("'t{}", i-2)),
+            }
         }
 
         // Replace any anonymous late-bound regions with named
index a4b8d365a12ef3b01c2e449973147a0bf9474d2b..2fb318a47befd80f6919cd0b22c9eb56bbe3f8f4 100644 (file)
@@ -1,7 +1,7 @@
 use crate::ty::{self, Ty, TyCtxt, AdtSizedConstraint};
 use crate::ty::util::NeedsDrop;
 
-use syntax::symbol::Symbol;
+use syntax::symbol::InternedString;
 
 pub(super) trait Value<'tcx>: Sized {
     fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
@@ -28,7 +28,7 @@ fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
 
 impl<'tcx> Value<'tcx> for ty::SymbolName {
     fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
-        ty::SymbolName { name: Symbol::intern("<error>").as_interned_str() }
+        ty::SymbolName { name: InternedString::intern("<error>") }
     }
 }
 
index 760f3d60d0571c3a6c8a375fc203a65269d0c901..e8f3bad4d3ee32832666fd66f72f4cc502707da8 100644 (file)
@@ -211,7 +211,7 @@ pub enum TyKind<'tcx> {
 
 // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TY_KIND: ::std::mem::size_of::<TyKind<'_>>() == 24);
+static_assert_size!(TyKind<'_>, 24);
 
 /// A closure can be modeled as a struct that looks like:
 ///
@@ -1136,7 +1136,7 @@ pub fn is_self(&self) -> bool {
         // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere,
         // but this should only be possible when using `-Z continue-parse-after-error` like
         // `compile-fail/issue-36638.rs`.
-        self.name == keywords::SelfUpper.name().as_str() && self.index == 0
+        self.name.as_symbol() == keywords::SelfUpper.name() && self.index == 0
     }
 }
 
@@ -2207,7 +2207,7 @@ pub struct Const<'tcx> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(CONST_SIZE: ::std::mem::size_of::<Const<'static>>() == 48);
+static_assert_size!(Const<'_>, 48);
 
 impl<'tcx> Const<'tcx> {
     #[inline]
index cb59cf41a3ca531a8adeecac42debee4d6279ed1..66ba95810a62516a109462f740955fed5c54afb8 100644 (file)
@@ -795,10 +795,10 @@ fn create_msvc_imps(
         return
     }
     // The x86 ABI seems to require that leading underscores are added to symbol
-    // names, so we need an extra underscore on 32-bit. There's also a leading
+    // names, so we need an extra underscore on x86. There's also a leading
     // '\x01' here which disables LLVM's symbol mangling (e.g., no extra
     // underscores added in front).
-    let prefix = if cgcx.target_pointer_width == "32" {
+    let prefix = if cgcx.target_arch == "x86" {
         "\x01__imp__"
     } else {
         "\x01__imp_"
index ceb08f943678b15a97aa5273effc4741dd962229..9ae0e26196d94fb142ef516b6a2942fca28c5cb9 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc::hir;
 use syntax::ast::{self, FloatTy};
-use syntax::symbol::Symbol;
+use syntax::symbol::LocalInternedString;
 
 use rustc_codegen_ssa::traits::*;
 
@@ -213,7 +213,7 @@ fn codegen_intrinsic_call(
             }
             "type_name" => {
                 let tp_ty = substs.type_at(0);
-                let ty_name = Symbol::intern(&tp_ty.to_string()).as_str();
+                let ty_name = LocalInternedString::intern(&tp_ty.to_string());
                 self.const_str_slice(ty_name)
             }
             "type_id" => {
index 6320d8a671ddbfd66f87de8060b86e9641839956..1c793996c83db65cc1cc2960546f358197812253 100644 (file)
@@ -248,6 +248,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub tm_factory: TargetMachineFactory<B>,
     pub msvc_imps_needed: bool,
     pub target_pointer_width: String,
+    pub target_arch: String,
     pub debuginfo: config::DebugInfo,
 
     // Number of cgus excluding the allocator/metadata modules
@@ -1103,6 +1104,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         total_cgus,
         msvc_imps_needed: msvc_imps_needed(tcx),
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
+        target_arch: tcx.sess.target.target.arch.clone(),
         debuginfo: tcx.sess.opts.debuginfo,
         assembler_cmd,
     };
index 96b8558c1d2c447f2b8149f6d71cf647f5696260..c7dd019fc3eb8abb464c0bcca87e15059a312c76 100644 (file)
@@ -15,7 +15,7 @@
 
 use std::borrow::Cow;
 
-use syntax::symbol::Symbol;
+use syntax::symbol::LocalInternedString;
 use syntax_pos::Pos;
 
 use super::{FunctionCx, LocalRef};
@@ -401,7 +401,7 @@ fn codegen_assert_terminator<'b>(
 
         // Get the location information.
         let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-        let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
+        let filename = LocalInternedString::intern(&loc.file.name.to_string());
         let line = bx.const_u32(loc.line as u32);
         let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
 
@@ -423,7 +423,7 @@ fn codegen_assert_terminator<'b>(
             }
             _ => {
                 let str = msg.description();
-                let msg_str = Symbol::intern(str).as_str();
+                let msg_str = LocalInternedString::intern(str);
                 let msg_file_line_col = bx.static_panic_msg(
                     Some(msg_str),
                     filename,
@@ -535,7 +535,7 @@ fn codegen_call_terminator<'b>(
             let layout = bx.layout_of(ty);
             if layout.abi.is_uninhabited() {
                 let loc = bx.sess().source_map().lookup_char_pos(span.lo());
-                let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
+                let filename = LocalInternedString::intern(&loc.file.name.to_string());
                 let line = bx.const_u32(loc.line as u32);
                 let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
 
@@ -543,7 +543,7 @@ fn codegen_call_terminator<'b>(
                     "Attempted to instantiate uninhabited type {}",
                     ty
                 );
-                let msg_str = Symbol::intern(&str).as_str();
+                let msg_str = LocalInternedString::intern(&str);
                 let msg_file_line_col = bx.static_panic_msg(
                     Some(msg_str),
                     filename,
index d50a9a1607b240da1f7c3b2fceb125c3e2148162..6915687ceba930d0bde8a5844293a7e7465ca89e 100644 (file)
 use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt};
 use rustc_mir::monomorphize::Instance;
 
-use syntax_pos::symbol::{Symbol, InternedString};
+use syntax_pos::symbol::InternedString;
 
 use log::debug;
 
@@ -238,13 +238,13 @@ fn compute_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) ->
     if def_id.is_local() {
         if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator))
-                .as_interned_str();
+            return
+                InternedString::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator));
         }
         if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator))
-                .as_interned_str();
+            return
+                InternedString::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator));
         }
     }
 
@@ -322,7 +322,7 @@ fn compute_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) ->
         let _ = printer.write_str("{{vtable-shim}}");
     }
 
-    Symbol::intern(&printer.path.finish(hash)).as_interned_str()
+    InternedString::intern(&printer.path.finish(hash))
 }
 
 // Follow C++ namespace-mangling style, see
index 029e7267c8247d40e0e5c91e4292a57966aef2ee..7fc23999284a71681dc53506aba56a12bc42f526 100644 (file)
@@ -10,3 +10,12 @@ macro_rules! static_assert {
         static $name: () = [()][!($test: bool) as usize];
     }
 }
+
+/// Type size assertion. The first argument is a type and the second argument is its expected size.
+#[macro_export]
+#[allow_internal_unstable(underscore_const_names)]
+macro_rules! static_assert_size {
+    ($ty:ty, $size:expr) => {
+        const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
+    }
+}
index fa573907d4c735a68752bc5c59076b67e3c0c676..2b844aa24d49c92a6d5bdbd165762f5a00908b31 100644 (file)
@@ -15,7 +15,6 @@
 /// extended to 64 bits if needed.
 pub struct StableHasher<W> {
     state: SipHasher128,
-    bytes_hashed: u64,
     width: PhantomData<W>,
 }
 
@@ -33,7 +32,6 @@ impl<W: StableHasherResult> StableHasher<W> {
     pub fn new() -> Self {
         StableHasher {
             state: SipHasher128::new_with_keys(0, 0),
-            bytes_hashed: 0,
             width: PhantomData,
         }
     }
@@ -61,11 +59,6 @@ impl<W> StableHasher<W> {
     pub fn finalize(self) -> (u64, u64) {
         self.state.finish128()
     }
-
-    #[inline]
-    pub fn bytes_hashed(&self) -> u64 {
-        self.bytes_hashed
-    }
 }
 
 impl<W> Hasher for StableHasher<W> {
@@ -76,37 +69,31 @@ fn finish(&self) -> u64 {
     #[inline]
     fn write(&mut self, bytes: &[u8]) {
         self.state.write(bytes);
-        self.bytes_hashed += bytes.len() as u64;
     }
 
     #[inline]
     fn write_u8(&mut self, i: u8) {
         self.state.write_u8(i);
-        self.bytes_hashed += 1;
     }
 
     #[inline]
     fn write_u16(&mut self, i: u16) {
         self.state.write_u16(i.to_le());
-        self.bytes_hashed += 2;
     }
 
     #[inline]
     fn write_u32(&mut self, i: u32) {
         self.state.write_u32(i.to_le());
-        self.bytes_hashed += 4;
     }
 
     #[inline]
     fn write_u64(&mut self, i: u64) {
         self.state.write_u64(i.to_le());
-        self.bytes_hashed += 8;
     }
 
     #[inline]
     fn write_u128(&mut self, i: u128) {
         self.state.write_u128(i.to_le());
-        self.bytes_hashed += 16;
     }
 
     #[inline]
@@ -115,37 +102,31 @@ fn write_usize(&mut self, i: usize) {
         // platforms. This is important for symbol hashes when cross compiling,
         // for example.
         self.state.write_u64((i as u64).to_le());
-        self.bytes_hashed += 8;
     }
 
     #[inline]
     fn write_i8(&mut self, i: i8) {
         self.state.write_i8(i);
-        self.bytes_hashed += 1;
     }
 
     #[inline]
     fn write_i16(&mut self, i: i16) {
         self.state.write_i16(i.to_le());
-        self.bytes_hashed += 2;
     }
 
     #[inline]
     fn write_i32(&mut self, i: i32) {
         self.state.write_i32(i.to_le());
-        self.bytes_hashed += 4;
     }
 
     #[inline]
     fn write_i64(&mut self, i: i64) {
         self.state.write_i64(i.to_le());
-        self.bytes_hashed += 8;
     }
 
     #[inline]
     fn write_i128(&mut self, i: i128) {
         self.state.write_i128(i.to_le());
-        self.bytes_hashed += 16;
     }
 
     #[inline]
@@ -154,12 +135,35 @@ fn write_isize(&mut self, i: isize) {
         // platforms. This is important for symbol hashes when cross compiling,
         // for example.
         self.state.write_i64((i as i64).to_le());
-        self.bytes_hashed += 8;
     }
 }
 
 /// Something that implements `HashStable<CTX>` can be hashed in a way that is
 /// stable across multiple compilation sessions.
+///
+/// Note that `HashStable` imposes rather more strict requirements than usual
+/// hash functions:
+///
+/// - Stable hashes are sometimes used as identifiers. Therefore they must
+///   conform to the corresponding `PartialEq` implementations:
+///
+///     - `x == y` implies `hash_stable(x) == hash_stable(y)`, and
+///     - `x != y` implies `hash_stable(x) != hash_stable(y)`.
+///
+///   That second condition is usually not required for hash functions
+///   (e.g. `Hash`). In practice this means that `hash_stable` must feed any
+///   information into the hasher that a `PartialEq` comparision takes into
+///   account. See [#49300](https://github.com/rust-lang/rust/issues/49300)
+///   for an example where violating this invariant has caused trouble in the
+///   past.
+///
+/// - `hash_stable()` must be independent of the current
+///    compilation session. E.g. they must not hash memory addresses or other
+///    things that are "randomly" assigned per compilation session.
+///
+/// - `hash_stable()` must be independent of the host architecture. The
+///   `StableHasher` takes care of endianness and `isize`/`usize` platform
+///   differences.
 pub trait HashStable<CTX> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut CTX,
index c74ed5ec30c3cade8d6b7b91cbf1dedc92a4af44..812321ff5e6c36f8fd16f772752f03b6d25eb5c2 100644 (file)
@@ -648,7 +648,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
     // have to be user friendly.
     let name = format!(
         "hir_id_{}_{}",
-        hir_id.owner.as_array_index(),
+        hir_id.owner.index(),
         hir_id.local_id.index(),
     );
     let lcfg = LabelledCFG {
index 7f2a1c0b4b1d11d6f28a1fe96c60e1a920a23020..3e00ba3c62004bf435cea8598604e15a7a274b55 100644 (file)
@@ -95,7 +95,7 @@ enum LoadError<'a> {
 impl<'a> LoadError<'a> {
     fn report(self) -> ! {
         match self {
-            LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(),
+            LoadError::LocatorError(locate_ctxt) => locate_ctxt.report_errs(),
         }
     }
 }
@@ -365,8 +365,8 @@ fn resolve_crate<'b>(
                 span,
                 ident,
                 crate_name: name,
-                hash: hash.map(|a| &*a),
-                extra_filename: extra_filename,
+                hash,
+                extra_filename,
                 filesearch: self.sess.target_filesearch(path_kind),
                 target: &self.sess.target.target,
                 triple: self.sess.opts.target_triple.clone(),
index e950c2815e9b4547f60a0ecf25b4a9b0964bad76..d882fe6f27ecc7a8f115306a43066b0a428cbb73 100644 (file)
@@ -264,7 +264,7 @@ fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
 impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
     #[inline]
     fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
-        Ok(DefIndex::from_raw_u32(self.read_u32()?))
+        Ok(DefIndex::from_u32(self.read_u32()?))
     }
 }
 
index 0ac03526832b7506c969c00e20318f4008c64157..939aadcc9ec9bfeefd0b44d1fca11df5060d0298 100644 (file)
@@ -134,7 +134,7 @@ fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
 impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
     #[inline]
     fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
-        self.emit_u32(def_index.as_raw_u32())
+        self.emit_u32(def_index.as_u32())
     }
 }
 
index 4c1e39cd0a9e1a945c1ed3c18ebc8e8cdd1f0f45..934e871559c79939010ffb30377007afc5b96ba6 100644 (file)
@@ -93,7 +93,7 @@ pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'_>>) {
     pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'_>>) {
         assert!(entry.position < (u32::MAX as usize));
         let position = entry.position as u32;
-        let array_index = item.as_array_index();
+        let array_index = item.index();
 
         let positions = &mut self.positions;
         assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX,
@@ -126,7 +126,7 @@ pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tc
                def_index,
                self.len);
 
-        let position = u32::read_from_bytes_at(bytes, 1 + def_index.as_array_index());
+        let position = u32::read_from_bytes_at(bytes, 1 + def_index.index());
         if position == u32::MAX {
             debug!("Index::lookup: position=u32::MAX");
             None
index 7d7dd1061a959db19aa1b8571db02167691c78a2..3832c8ee227de1208bab95dd5bf864d93ccc964f 100644 (file)
@@ -321,7 +321,7 @@ pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
         }
     }
 
-    pub fn report_errs(&mut self) -> ! {
+    pub fn report_errs(self) -> ! {
         let add = match self.root {
             &None => String::new(),
             &Some(ref r) => format!(" which `{}` depends on", r.ident),
@@ -901,8 +901,7 @@ fn get_metadata_section_imp(target: &Target,
             let mut inflated = Vec::new();
             match DeflateDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
                 Ok(_) => {
-                    let buf = unsafe { OwningRef::new_assert_stable_address(inflated) };
-                    rustc_erase_owner!(buf.map_owner_box())
+                    rustc_erase_owner!(OwningRef::new(inflated).map_owner_box())
                 }
                 Err(_) => {
                     return Err(format!("failed to decompress metadata: {}", filename.display()));
index 4ced31593b1ae6cc0264bcdb6bb160eb4c51eb99..4d8acd241acd893f17910c81d87d8b09d8b979b6 100644 (file)
@@ -12,7 +12,6 @@
 use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt};
 use rustc::ty::print::RegionHighlightMode;
 use rustc_errors::DiagnosticBuilder;
-use syntax::ast::Name;
 use syntax::symbol::keywords;
 use syntax_pos::Span;
 use syntax_pos::symbol::InternedString;
@@ -60,8 +59,8 @@ impl RegionName {
     }
 
     #[allow(dead_code)]
-    crate fn name(&self) -> &InternedString {
-        &self.name
+    crate fn name(&self) -> InternedString {
+        self.name
     }
 
     crate fn highlight_region_name(
@@ -206,7 +205,7 @@ fn give_name_from_error_region(
         match error_region {
             ty::ReEarlyBound(ebr) => {
                 if ebr.has_name() {
-                    let span = self.get_named_span(tcx, error_region, &ebr.name);
+                    let span = self.get_named_span(tcx, error_region, ebr.name);
                     Some(RegionName {
                         name: ebr.name,
                         source: RegionNameSource::NamedEarlyBoundRegion(span)
@@ -223,7 +222,7 @@ fn give_name_from_error_region(
 
             ty::ReFree(free_region) => match free_region.bound_region {
                 ty::BoundRegion::BrNamed(_, name) => {
-                    let span = self.get_named_span(tcx, error_region, &name);
+                    let span = self.get_named_span(tcx, error_region, name);
                     Some(RegionName {
                         name,
                         source: RegionNameSource::NamedFreeRegion(span),
@@ -306,7 +305,7 @@ fn get_named_span(
         &self,
         tcx: TyCtxt<'_, '_, 'tcx>,
         error_region: &RegionKind,
-        name: &InternedString,
+        name: InternedString,
     ) -> Span {
         let scope = error_region.free_region_binding_scope(tcx);
         let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
@@ -791,6 +790,6 @@ fn synthesize_region_name(&self, counter: &mut usize) -> InternedString {
         let c = *counter;
         *counter += 1;
 
-        Name::intern(&format!("'{:?}", c)).as_interned_str()
+        InternedString::intern(&format!("'{:?}", c))
     }
 }
index db827afdb94f4481096d600aa8db0cd5ec599e9d..d4c1e5416d565c50232d271ac1ec800c2c899f3b 100644 (file)
@@ -613,7 +613,9 @@ pub fn storage_live(
         trace!("{:?} is now live", local);
 
         let local_val = LocalValue::Uninitialized;
-        // StorageLive *always* kills the value that's currently stored
+        // StorageLive *always* kills the value that's currently stored.
+        // However, we do not error if the variable already is live;
+        // see <https://github.com/rust-lang/rust/issues/42371>.
         Ok(mem::replace(&mut self.frame_mut().locals[local].value, local_val))
     }
 
index 999e7402afd93a57f64787feee4416534a6a2d33..6b40245d39a8eae5fb7c094cb85f3d8bd0d122d0 100644 (file)
@@ -10,7 +10,7 @@
 use std::fmt::{self, Write};
 use std::iter;
 use rustc::mir::mono::Linkage;
-use syntax_pos::symbol::Symbol;
+use syntax_pos::symbol::InternedString;
 use syntax::source_map::Span;
 pub use rustc::mir::mono::MonoItem;
 
@@ -61,7 +61,7 @@ fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName {
             MonoItem::GlobalAsm(hir_id) => {
                 let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
                 ty::SymbolName {
-                    name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str()
+                    name: InternedString::intern(&format!("global_asm_{:?}", def_id))
                 }
             }
         }
index fab07a2290eb5a31efc5bebf8a33aede8a6c7269..394d1f06029cb6459f2e579b50d770d9dddbd32a 100644 (file)
@@ -12,7 +12,7 @@
 use rustc::mir::*;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext};
 
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::{InternedString, sym};
 
 use std::ops::Bound;
 
@@ -167,9 +167,9 @@ fn visit_rvalue(&mut self,
                     (CastTy::FnPtr, CastTy::Int(_)) => {
                         self.register_violations(&[UnsafetyViolation {
                             source_info: self.source_info,
-                            description: Symbol::intern("cast of pointer to int").as_interned_str(),
-                            details: Symbol::intern("casting pointers to integers in constants")
-                                     .as_interned_str(),
+                            description: InternedString::intern("cast of pointer to int"),
+                            details: InternedString::intern(
+                                "casting pointers to integers in constants"),
                             kind: UnsafetyViolationKind::General,
                         }], &[]);
                     },
@@ -185,9 +185,8 @@ fn visit_rvalue(&mut self,
                 if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty {
                     self.register_violations(&[UnsafetyViolation {
                         source_info: self.source_info,
-                        description: Symbol::intern("pointer operation").as_interned_str(),
-                        details: Symbol::intern("operations on pointers in constants")
-                                 .as_interned_str(),
+                        description: InternedString::intern("pointer operation"),
+                        details: InternedString::intern("operations on pointers in constants"),
                         kind: UnsafetyViolationKind::General,
                     }], &[]);
                 }
@@ -212,13 +211,11 @@ fn visit_place(&mut self,
                             self.source_scope_local_data[source_info.scope].lint_root;
                         self.register_violations(&[UnsafetyViolation {
                             source_info,
-                            description: Symbol::intern("borrow of packed field").as_interned_str(),
-                            details:
-                                Symbol::intern("fields of packed structs might be misaligned: \
-                                                dereferencing a misaligned pointer or even just \
-                                                creating a misaligned reference is undefined \
-                                                behavior")
-                                    .as_interned_str(),
+                            description: InternedString::intern("borrow of packed field"),
+                            details: InternedString::intern(
+                                "fields of packed structs might be misaligned: dereferencing a \
+                                misaligned pointer or even just creating a misaligned reference \
+                                is undefined behavior"),
                             kind: UnsafetyViolationKind::BorrowPacked(lint_root)
                         }], &[]);
                     }
@@ -315,12 +312,10 @@ fn visit_place(&mut self,
                         self.source_scope_local_data[source_info.scope].lint_root;
                     self.register_violations(&[UnsafetyViolation {
                         source_info,
-                        description: Symbol::intern("use of extern static").as_interned_str(),
-                        details:
-                            Symbol::intern("extern statics are not controlled by the Rust type \
-                                            system: invalid data, aliasing violations or data \
-                                            races will cause undefined behavior")
-                                .as_interned_str(),
+                        description: InternedString::intern("use of extern static"),
+                        details: InternedString::intern(
+                            "extern statics are not controlled by the Rust type system: invalid \
+                            data, aliasing violations or data races will cause undefined behavior"),
                         kind: UnsafetyViolationKind::ExternStatic(lint_root)
                     }], &[]);
                 }
@@ -340,8 +335,8 @@ fn require_unsafe(
         let source_info = self.source_info;
         self.register_violations(&[UnsafetyViolation {
             source_info,
-            description: Symbol::intern(description).as_interned_str(),
-            details: Symbol::intern(details).as_interned_str(),
+            description: InternedString::intern(description),
+            details: InternedString::intern(details),
             kind,
         }], &[]);
     }
@@ -441,8 +436,8 @@ fn check_mut_borrowing_layout_constrained_field(
                                 let source_info = self.source_info;
                                 self.register_violations(&[UnsafetyViolation {
                                     source_info,
-                                    description: Symbol::intern(description).as_interned_str(),
-                                    details: Symbol::intern(details).as_interned_str(),
+                                    description: InternedString::intern(description),
+                                    details: InternedString::intern(details),
                                     kind: UnsafetyViolationKind::GeneralAndConstFn,
                                 }], &[]);
                             }
index 4e214c3c7253ee71d8455d5e0cf5d6367a895041..8f3dd72c4f2450a82ca151b53d8ebbe9128b72d6 100644 (file)
@@ -546,6 +546,10 @@ fn replace_with_const(&self, rval: &mut Rvalue<'tcx>, value: Const<'tcx>, span:
             }
         }
     }
+
+    fn should_const_prop(&self) -> bool {
+        self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2
+    }
 }
 
 fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -639,7 +643,7 @@ fn visit_statement(
                             assert!(self.places[local].is_none());
                             self.places[local] = Some(value);
 
-                            if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+                            if self.should_const_prop() {
                                 self.replace_with_const(rval, value, statement.source_info.span);
                             }
                         }
@@ -656,75 +660,112 @@ fn visit_terminator(
         location: Location,
     ) {
         self.super_terminator(terminator, location);
-        let source_info = terminator.source_info;;
-        if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind {
-            if let Some(value) = self.eval_operand(&cond, source_info) {
-                trace!("assertion on {:?} should be {:?}", value, expected);
-                let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
-                if expected != self.ecx.read_scalar(value).unwrap() {
-                    // poison all places this operand references so that further code
-                    // doesn't use the invalid value
-                    match cond {
-                        Operand::Move(ref place) | Operand::Copy(ref place) => {
-                            let mut place = place;
-                            while let Place::Projection(ref proj) = *place {
-                                place = &proj.base;
-                            }
-                            if let Place::Base(PlaceBase::Local(local)) = *place {
-                                self.places[local] = None;
+        let source_info = terminator.source_info;
+        match &mut terminator.kind {
+            TerminatorKind::Assert { expected, msg, ref mut cond, .. } => {
+                if let Some(value) = self.eval_operand(&cond, source_info) {
+                    trace!("assertion on {:?} should be {:?}", value, expected);
+                    let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
+                    let value_const = self.ecx.read_scalar(value).unwrap();
+                    if expected != value_const {
+                        // poison all places this operand references so that further code
+                        // doesn't use the invalid value
+                        match cond {
+                            Operand::Move(ref place) | Operand::Copy(ref place) => {
+                                let mut place = place;
+                                while let Place::Projection(ref proj) = *place {
+                                    place = &proj.base;
+                                }
+                                if let Place::Base(PlaceBase::Local(local)) = *place {
+                                    self.places[local] = None;
+                                }
+                            },
+                            Operand::Constant(_) => {}
+                        }
+                        let span = terminator.source_info.span;
+                        let hir_id = self
+                            .tcx
+                            .hir()
+                            .as_local_hir_id(self.source.def_id())
+                            .expect("some part of a failing const eval must be local");
+                        use rustc::mir::interpret::InterpError::*;
+                        let msg = match msg {
+                            Overflow(_) |
+                            OverflowNeg |
+                            DivisionByZero |
+                            RemainderByZero => msg.description().to_owned(),
+                            BoundsCheck { ref len, ref index } => {
+                                let len = self
+                                    .eval_operand(len, source_info)
+                                    .expect("len must be const");
+                                let len = match self.ecx.read_scalar(len) {
+                                    Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                                        bits, ..
+                                    })) => bits,
+                                    other => bug!("const len not primitive: {:?}", other),
+                                };
+                                let index = self
+                                    .eval_operand(index, source_info)
+                                    .expect("index must be const");
+                                let index = match self.ecx.read_scalar(index) {
+                                    Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                                        bits, ..
+                                    })) => bits,
+                                    other => bug!("const index not primitive: {:?}", other),
+                                };
+                                format!(
+                                    "index out of bounds: \
+                                    the len is {} but the index is {}",
+                                    len,
+                                    index,
+                                )
+                            },
+                            // Need proper const propagator for these
+                            _ => return,
+                        };
+                        self.tcx.lint_hir(
+                            ::rustc::lint::builtin::CONST_ERR,
+                            hir_id,
+                            span,
+                            &msg,
+                        );
+                    } else {
+                        if self.should_const_prop() {
+                            if let ScalarMaybeUndef::Scalar(scalar) = value_const {
+                                *cond = self.operand_from_scalar(
+                                    scalar,
+                                    self.tcx.types.bool,
+                                    source_info.span,
+                                );
                             }
-                        },
-                        Operand::Constant(_) => {}
+                        }
                     }
-                    let span = terminator.source_info.span;
-                    let hir_id = self
-                        .tcx
-                        .hir()
-                        .as_local_hir_id(self.source.def_id())
-                        .expect("some part of a failing const eval must be local");
-                    use rustc::mir::interpret::InterpError::*;
-                    let msg = match msg {
-                        Overflow(_) |
-                        OverflowNeg |
-                        DivisionByZero |
-                        RemainderByZero => msg.description().to_owned(),
-                        BoundsCheck { ref len, ref index } => {
-                            let len = self
-                                .eval_operand(len, source_info)
-                                .expect("len must be const");
-                            let len = match self.ecx.read_scalar(len) {
-                                Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
-                                    bits, ..
-                                })) => bits,
-                                other => bug!("const len not primitive: {:?}", other),
-                            };
-                            let index = self
-                                .eval_operand(index, source_info)
-                                .expect("index must be const");
-                            let index = match self.ecx.read_scalar(index) {
-                                Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
-                                    bits, ..
-                                })) => bits,
-                                other => bug!("const index not primitive: {:?}", other),
-                            };
-                            format!(
-                                "index out of bounds: \
-                                the len is {} but the index is {}",
-                                len,
-                                index,
-                            )
-                        },
-                        // Need proper const propagator for these
-                        _ => return,
-                    };
-                    self.tcx.lint_hir(
-                        ::rustc::lint::builtin::CONST_ERR,
-                        hir_id,
-                        span,
-                        &msg,
-                    );
                 }
-            }
+            },
+            TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => {
+                if self.should_const_prop() {
+                    if let Some(value) = self.eval_operand(&discr, source_info) {
+                        if let ScalarMaybeUndef::Scalar(scalar) =
+                                self.ecx.read_scalar(value).unwrap() {
+                            *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span);
+                        }
+                    }
+                }
+            },
+            //none of these have Operands to const-propagate
+            TerminatorKind::Goto { .. } |
+            TerminatorKind::Resume |
+            TerminatorKind::Abort |
+            TerminatorKind::Return |
+            TerminatorKind::Unreachable |
+            TerminatorKind::Drop { .. } |
+            TerminatorKind::DropAndReplace { .. } |
+            TerminatorKind::Yield { .. } |
+            TerminatorKind::GeneratorDrop |
+            TerminatorKind::FalseEdges { .. } |
+            TerminatorKind::FalseUnwind { .. } => { }
+            //FIXME(wesleywiser) Call does have Operands that could be const-propagated
+            TerminatorKind::Call { .. } => { }
         }
     }
 }
index 188da9a82dc995a07c85e1119c51b3a3894a3807..fc4c6b3fd3f244afc5a41d37239e39c31ba8f987 100644 (file)
@@ -27,7 +27,7 @@ pub fn graphviz_safe_def_name(def_id: DefId) -> String {
     format!(
         "{}_{}",
         def_id.krate.index(),
-        def_id.index.as_array_index(),
+        def_id.index.index(),
     )
 }
 
index 9f3e1c308f6379e9c591b7530381098459057b0a..e34a33ef8fad9b2a7476e2d8a096e11b5e610ceb 100644 (file)
@@ -172,7 +172,7 @@ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFra
     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
         let def_id = DefId {
             krate: CrateNum::BuiltinMacros,
-            index: DefIndex::from_array_index(self.macro_map.len()),
+            index: DefIndex::from(self.macro_map.len()),
         };
         let kind = ext.kind();
         self.macro_map.insert(def_id, ext);
index e03da2ed608be02f02d3137dd1d9af17412ac6bb..d34f5633946bfa281773da81d21cab2b44013bcc 100644 (file)
@@ -1170,7 +1170,7 @@ fn generated_code(span: Span) -> bool {
 fn id_from_def_id(id: DefId) -> rls_data::Id {
     rls_data::Id {
         krate: id.krate.as_u32(),
-        index: id.index.as_raw_u32(),
+        index: id.index.as_u32(),
     }
 }
 
index 40c60caffa42d8eb7dd81d67af010c49b924e428..c6191e6b579ce45c036876db9c47656585997c97 100644 (file)
@@ -7,7 +7,7 @@
 use crate::require_same_types;
 
 use rustc_target::spec::abi::Abi;
-use syntax::symbol::Symbol;
+use syntax::symbol::InternedString;
 
 use rustc::hir;
 
@@ -80,7 +80,7 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
 /// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       it: &hir::ForeignItem) {
-    let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
+    let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n)));
     let name = it.ident.as_str();
 
     let mk_va_list_ty = || {
@@ -397,7 +397,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                it: &hir::ForeignItem) {
     let param = |n| {
-        let name = Symbol::intern(&format!("P{}", n)).as_interned_str();
+        let name = InternedString::intern(&format!("P{}", n));
         tcx.mk_ty_param(n, name)
     };
 
index cbb6d9b29f59f7f642588ffbe18ae3e0e18d7d22..3c3509f24ce1eb97000433d6245363ec14f114dd 100644 (file)
@@ -158,6 +158,13 @@ fn unused_crates_lint<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) {
             continue;
         }
 
+        // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
+        // would not insert the new name into the prelude, where other imports in the crate may be
+        // expecting it.
+        if extern_crate.orig_name.is_some() {
+            continue;
+        }
+
         // If the extern crate has any attributes, they may have funky
         // semantics we can't faithfully represent using `use` (most
         // notably `#[macro_use]`). Ignore it.
index 6527e8655b5ef21bb6d93a7b65f5fed7c8c098fa..711d79f95f53a658d42a1fff866a78c9a78ff4e5 100644 (file)
@@ -39,7 +39,7 @@
 use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used};
 use syntax::source_map::Spanned;
 use syntax::feature_gate;
-use syntax::symbol::{keywords, Symbol, sym};
+use syntax::symbol::{InternedString, keywords, Symbol, sym};
 use syntax_pos::{Span, DUMMY_SP};
 
 use rustc::hir::def::{CtorKind, Res, DefKind};
@@ -1082,7 +1082,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
                 .enumerate()
                 .map(|(i, &arg)| ty::GenericParamDef {
                     index: type_start + i as u32,
-                    name: Symbol::intern(arg).as_interned_str(),
+                    name: InternedString::intern(arg),
                     def_id,
                     pure_wrt_drop: false,
                     kind: ty::GenericParamDefKind::Type {
@@ -1097,7 +1097,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
             params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
                 ty::GenericParamDef {
                     index: type_start + i,
-                    name: Symbol::intern("<upvar>").as_interned_str(),
+                    name: InternedString::intern("<upvar>"),
                     def_id,
                     pure_wrt_drop: false,
                     kind: ty::GenericParamDefKind::Type {
index e9ccc61280b10a9b517a58a29da48f0595f1fd96..e434623d4a12759fe3f1bb82cef4fa0cd11fca18 100644 (file)
@@ -3149,7 +3149,10 @@ impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
     fn clean(&self, cx: &DocContext<'_>) -> Constant {
         Constant {
             type_: self.ty.clean(cx),
-            expr: format!("{:?}", self.val), // FIXME(const_generics)
+            expr: match self.val {
+                ConstValue::Param(ty::ParamConst { name, .. }) => format!("{}", name),
+                e => format!("{:?}", e), // FIXME generic consts with expressions
+            },
         }
     }
 }
@@ -3405,6 +3408,7 @@ pub struct Span {
     pub locol: usize,
     pub hiline: usize,
     pub hicol: usize,
+    pub original: syntax_pos::Span,
 }
 
 impl Span {
@@ -3413,8 +3417,13 @@ pub fn empty() -> Span {
             filename: FileName::Anon(0),
             loline: 0, locol: 0,
             hiline: 0, hicol: 0,
+            original: syntax_pos::DUMMY_SP,
         }
     }
+
+    pub fn span(&self) -> syntax_pos::Span {
+        self.original
+    }
 }
 
 impl Clean<Span> for syntax_pos::Span {
@@ -3433,6 +3442,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Span {
             locol: lo.col.to_usize(),
             hiline: hi.line,
             hicol: hi.col.to_usize(),
+            original: *self,
         }
     }
 }
index 72421c9decc6febf4c10e40cfd56a42aec037783..6b490f730afa0c951cab05c7dd5fcb79841321a7 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::session::search_paths::SearchPath;
 use rustc_driver;
 use rustc_target::spec::TargetTriple;
-use syntax::edition::Edition;
+use syntax::edition::{Edition, DEFAULT_EDITION};
 
 use crate::core::new_handler;
 use crate::externalfiles::ExternalHtml;
@@ -386,6 +386,18 @@ pub fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
             }
         }
 
+        let edition = if let Some(e) = matches.opt_str("edition") {
+            match e.parse() {
+                Ok(e) => e,
+                Err(_) => {
+                    diag.struct_err("could not parse edition").emit();
+                    return Err(1);
+                }
+            }
+        } else {
+            DEFAULT_EDITION
+        };
+
         let mut id_map = html::markdown::IdMap::new();
         id_map.populate(html::render::initial_ids());
         let external_html = match ExternalHtml::load(
@@ -393,20 +405,12 @@ pub fn from_matches(matches: &getopts::Matches) -> Result<Options, i32> {
                 &matches.opt_strs("html-before-content"),
                 &matches.opt_strs("html-after-content"),
                 &matches.opt_strs("markdown-before-content"),
-                &matches.opt_strs("markdown-after-content"), &diag, &mut id_map) {
+                &matches.opt_strs("markdown-after-content"),
+                &diag, &mut id_map, edition) {
             Some(eh) => eh,
             None => return Err(3),
         };
 
-        let edition = matches.opt_str("edition").unwrap_or("2015".to_string());
-        let edition = match edition.parse() {
-            Ok(e) => e,
-            Err(_) => {
-                diag.struct_err("could not parse edition").emit();
-                return Err(1);
-            }
-        };
-
         match matches.opt_str("r").as_ref().map(|s| &**s) {
             Some("rust") | None => {}
             Some(s) => {
@@ -538,7 +542,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler)
        "passes",
     ];
 
-    for flag in deprecated_flags.into_iter() {
+    for flag in deprecated_flags.iter() {
         if matches.opt_present(flag) {
             let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated",
                                                     flag));
index 428f4f328b907987356c418a09511b582e205c3b..2a3bc5e99617f468375a834110a7e7cf45e431ed 100644 (file)
@@ -143,7 +143,7 @@ pub fn next_def_id(&self, crate_num: CrateNum) -> DefId {
             crate_num,
             DefId {
                 krate: crate_num,
-                index: DefIndex::from_array_index(def_id.index.as_array_index() + 1),
+                index: DefIndex::from(def_id.index.index() + 1),
             },
         );
 
index 0378b12662da26fa5fd6ee525f7ae5d8b244d18a..d604ba11d41860fd39f0b70d56dd6051a9bb9424 100644 (file)
@@ -3,6 +3,7 @@
 use std::str;
 use errors;
 use crate::syntax::feature_gate::UnstableFeatures;
+use crate::syntax::edition::Edition;
 use crate::html::markdown::{IdMap, ErrorCodes, Markdown};
 
 use std::cell::RefCell;
@@ -23,7 +24,7 @@ pub struct ExternalHtml {
 impl ExternalHtml {
     pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
                 md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler,
-                id_map: &mut IdMap)
+                id_map: &mut IdMap, edition: Edition)
             -> Option<ExternalHtml> {
         let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
         load_external_files(in_header, diag)
@@ -34,7 +35,8 @@ pub fn load(in_header: &[String], before_content: &[String], after_content: &[St
             .and_then(|(ih, bc)|
                 load_external_files(md_before_content, diag)
                     .map(|m_bc| (ih,
-                            format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes))))
+                            format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map),
+                                    codes, edition))))
             )
             .and_then(|(ih, bc)|
                 load_external_files(after_content, diag)
@@ -43,7 +45,8 @@ pub fn load(in_header: &[String], before_content: &[String], after_content: &[St
             .and_then(|(ih, bc, ac)|
                 load_external_files(md_after_content, diag)
                     .map(|m_ac| (ih, bc,
-                            format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes))))
+                            format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map),
+                                    codes, edition))))
             )
             .map(|(ih, bc, ac)|
                 ExternalHtml {
index 3d8af7c7716b1475439bd40ba3252c09d6ccdb3e..2784d5b3e10a0bbf85e5c46e9ea56afe54131c06 100644 (file)
@@ -262,9 +262,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl fmt::Display for clean::Constant {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.expr, f)?;
-        f.write_str(": ")?;
-        fmt::Display::fmt(&self.type_, f)
+        fmt::Display::fmt(&self.expr, f)
     }
 }
 
index acf019fd2254dfd52bf7804a66a708bfec525845..ae0bd1aafa8f159393fce8482bc54eb47e314e27 100644 (file)
@@ -182,14 +182,14 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
         let p = SlashChecker(&p);
         if layout.logo.is_empty() {
             format!("<a href='{path}index.html'>\
-                     <img src='{static_root_path}rust-logo{suffix}.png' \
-                          alt='logo' width='100'></a>",
+                     <div class='logo-container'>\
+                     <img src='{static_root_path}rust-logo{suffix}.png' alt='logo'></div></a>",
                     path=p,
                     static_root_path=static_root_path,
                     suffix=page.resource_suffix)
         } else {
             format!("<a href='{}index.html'>\
-                     <img src='{}' alt='logo' width='100'></a>",
+                     <div class='logo-container'><img src='{}' alt='logo'></div></a>",
                     p,
                     layout.logo)
         }
index a3b041c6954c58b7c93eb524971652b1d7781952..12d10254c4d09ecf7574ca63ed0d75643dd7c393 100644 (file)
@@ -8,12 +8,16 @@
 //! ```
 //! #![feature(rustc_private)]
 //!
+//! extern crate syntax;
+//!
+//! use syntax::edition::Edition;
 //! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes};
 //! use std::cell::RefCell;
 //!
 //! let s = "My *markdown* _text_";
 //! let mut id_map = IdMap::new();
-//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes));
+//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map),
+//!                                   ErrorCodes::Yes, Edition::Edition2015));
 //! // ... something using html
 //! ```
 
@@ -42,14 +46,21 @@ fn opts() -> Options {
 /// A unit struct which has the `fmt::Display` trait implemented. When
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
-/// The second parameter is a list of link replacements
+///
+/// The second parameter is a list of link replacements.
+///
+/// The third is the current list of used header IDs.
+///
+/// The fourth is whether to allow the use of explicit error codes in doctest lang strings.
+///
+/// The fifth is what default edition to use when parsing doctests (to add a `fn main`).
 pub struct Markdown<'a>(
-    pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes);
+    pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
-pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
+pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
-pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes);
+pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition);
 /// A unit struct like `Markdown`, that renders only the first paragraph.
 pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]);
 
@@ -146,13 +157,15 @@ fn slugify(c: char) -> Option<char> {
 struct CodeBlocks<'a, I: Iterator<Item = Event<'a>>> {
     inner: I,
     check_error_codes: ErrorCodes,
+    edition: Edition,
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> CodeBlocks<'a, I> {
-    fn new(iter: I, error_codes: ErrorCodes) -> Self {
+    fn new(iter: I, error_codes: ErrorCodes, edition: Edition) -> Self {
         CodeBlocks {
             inner: iter,
             check_error_codes: error_codes,
+            edition,
         }
     }
 }
@@ -177,6 +190,9 @@ fn next(&mut self) -> Option<Self::Item> {
             return event;
         }
 
+        let explicit_edition = edition.is_some();
+        let edition = edition.unwrap_or(self.edition);
+
         let mut origtext = String::new();
         for event in &mut self.inner {
             match event {
@@ -202,22 +218,14 @@ fn next(&mut self) -> Option<Self::Item> {
                     .collect::<Vec<Cow<'_, str>>>().join("\n");
                 let krate = krate.as_ref().map(|s| &**s);
                 let (test, _) = test::make_test(&test, krate, false,
-                                           &Default::default());
+                                           &Default::default(), edition);
                 let channel = if test.contains("#![feature(") {
                     "&amp;version=nightly"
                 } else {
                     ""
                 };
 
-                let edition_string = if let Some(e @ Edition::Edition2018) = edition {
-                    format!("&amp;edition={}{}", e,
-                            if channel == "&amp;version=nightly" { "" }
-                            else { "&amp;version=nightly" })
-                } else if let Some(e) = edition {
-                    format!("&amp;edition={}", e)
-                } else {
-                    "".to_owned()
-                };
+                let edition_string = format!("&amp;edition={}", edition);
 
                 // These characters don't need to be escaped in a URI.
                 // FIXME: use a library function for percent encoding.
@@ -247,8 +255,8 @@ fn dont_escape(c: u8) -> bool {
                 Some(("This example is not tested".to_owned(), "ignore"))
             } else if compile_fail {
                 Some(("This example deliberately fails to compile".to_owned(), "compile_fail"))
-            } else if let Some(e) = edition {
-                Some((format!("This code runs with edition {}", e), "edition"))
+            } else if explicit_edition {
+                Some((format!("This code runs with edition {}", edition), "edition"))
             } else {
                 None
             };
@@ -259,7 +267,7 @@ fn dont_escape(c: u8) -> bool {
                     Some(&format!("rust-example-rendered{}",
                                   if ignore { " ignore" }
                                   else if compile_fail { " compile_fail" }
-                                  else if edition.is_some() { " edition " }
+                                  else if explicit_edition { " edition " }
                                   else { "" })),
                     playground_button.as_ref().map(String::as_str),
                     Some((s1.as_str(), s2))));
@@ -270,7 +278,7 @@ fn dont_escape(c: u8) -> bool {
                     Some(&format!("rust-example-rendered{}",
                                   if ignore { " ignore" }
                                   else if compile_fail { " compile_fail" }
-                                  else if edition.is_some() { " edition " }
+                                  else if explicit_edition { " edition " }
                                   else { "" })),
                     playground_button.as_ref().map(String::as_str),
                     None));
@@ -659,7 +667,7 @@ fn parse(string: &str, allow_error_code_check: ErrorCodes) -> LangString {
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Markdown(md, links, ref ids, codes) = *self;
+        let Markdown(md, links, ref ids, codes, edition) = *self;
         let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
@@ -678,7 +686,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
         let p = HeadingLinks::new(p, None, &mut ids);
         let p = LinkReplacer::new(p, links);
-        let p = CodeBlocks::new(p, codes);
+        let p = CodeBlocks::new(p, codes, edition);
         let p = Footnotes::new(p);
         html::push_html(&mut s, p);
 
@@ -688,7 +696,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl<'a> fmt::Display for MarkdownWithToc<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let MarkdownWithToc(md, ref ids, codes) = *self;
+        let MarkdownWithToc(md, ref ids, codes, edition) = *self;
         let mut ids = ids.borrow_mut();
 
         let p = Parser::new_ext(md, opts());
@@ -699,7 +707,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
         {
             let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
-            let p = CodeBlocks::new(p, codes);
+            let p = CodeBlocks::new(p, codes, edition);
             let p = Footnotes::new(p);
             html::push_html(&mut s, p);
         }
@@ -712,7 +720,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl<'a> fmt::Display for MarkdownHtml<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let MarkdownHtml(md, ref ids, codes) = *self;
+        let MarkdownHtml(md, ref ids, codes, edition) = *self;
         let mut ids = ids.borrow_mut();
 
         // This is actually common enough to special-case
@@ -728,7 +736,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, &mut ids);
-        let p = CodeBlocks::new(p, codes);
+        let p = CodeBlocks::new(p, codes, edition);
         let p = Footnotes::new(p);
         html::push_html(&mut s, p);
 
@@ -1046,7 +1054,7 @@ mod tests {
     use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap};
     use super::plain_summary_line;
     use std::cell::RefCell;
-    use syntax::edition::Edition;
+    use syntax::edition::{Edition, DEFAULT_EDITION};
 
     #[test]
     fn test_lang_string_parse() {
@@ -1098,7 +1106,8 @@ fn v() -> Vec<String> {
     fn test_header() {
         fn t(input: &str, expect: &str) {
             let mut map = IdMap::new();
-            let output = Markdown(input, &[], RefCell::new(&mut map), ErrorCodes::Yes).to_string();
+            let output = Markdown(input, &[], RefCell::new(&mut map),
+                                  ErrorCodes::Yes, DEFAULT_EDITION).to_string();
             assert_eq!(output, expect, "original: {}", input);
         }
 
@@ -1120,7 +1129,8 @@ fn t(input: &str, expect: &str) {
     fn test_header_ids_multiple_blocks() {
         let mut map = IdMap::new();
         fn t(map: &mut IdMap, input: &str, expect: &str) {
-            let output = Markdown(input, &[], RefCell::new(map), ErrorCodes::Yes).to_string();
+            let output = Markdown(input, &[], RefCell::new(map),
+                                  ErrorCodes::Yes, DEFAULT_EDITION).to_string();
             assert_eq!(output, expect, "original: {}", input);
         }
 
@@ -1157,7 +1167,8 @@ fn t(input: &str, expect: &str) {
     fn test_markdown_html_escape() {
         fn t(input: &str, expect: &str) {
             let mut idmap = IdMap::new();
-            let output = MarkdownHtml(input, RefCell::new(&mut idmap), ErrorCodes::Yes).to_string();
+            let output = MarkdownHtml(input, RefCell::new(&mut idmap),
+                                      ErrorCodes::Yes, DEFAULT_EDITION).to_string();
             assert_eq!(output, expect, "original: {}", input);
         }
 
index 0207fcda9e880ea6525550ae6b8f3d8a176ca0b3..b628bd450d314b8a690dea5e0beae786db59a0ef 100644 (file)
@@ -47,6 +47,7 @@
 use errors;
 use serialize::json::{ToJson, Json, as_json};
 use syntax::ast;
+use syntax::edition::Edition;
 use syntax::ext::base::MacroKind;
 use syntax::source_map::FileName;
 use syntax::feature_gate::UnstableFeatures;
@@ -108,6 +109,8 @@ struct Context {
     /// publicly reused items to redirect to the right location.
     pub render_redirect_pages: bool,
     pub codes: ErrorCodes,
+    /// The default edition used to parse doctests.
+    pub edition: Edition,
     /// The map used to ensure all generated 'id=' attributes are unique.
     id_map: Rc<RefCell<IdMap>>,
     pub shared: Arc<SharedContext>,
@@ -506,7 +509,7 @@ pub fn initial_ids() -> Vec<String> {
      "methods",
      "deref-methods",
      "implementations",
-    ].into_iter().map(|id| (String::from(*id))).collect()
+    ].iter().map(|id| (String::from(*id))).collect()
 }
 
 /// Generates the documentation for `crate` into the directory `dst`
@@ -514,7 +517,8 @@ pub fn run(mut krate: clean::Crate,
            options: RenderOptions,
            passes: FxHashSet<String>,
            renderinfo: RenderInfo,
-           diag: &errors::Handler) -> Result<(), Error> {
+           diag: &errors::Handler,
+           edition: Edition) -> Result<(), Error> {
     // need to save a copy of the options for rendering the index page
     let md_opts = options.clone();
     let RenderOptions {
@@ -604,6 +608,7 @@ pub fn run(mut krate: clean::Crate,
         dst,
         render_redirect_pages: false,
         codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
+        edition,
         id_map: Rc::new(RefCell::new(id_map)),
         shared: Arc::new(scx),
     };
@@ -1128,7 +1133,7 @@ fn to_json_string(&self) -> String {
             md_opts.output = cx.dst.clone();
             md_opts.external_html = (*cx.shared).layout.external_html.clone();
 
-            crate::markdown::render(index_page, md_opts, diag);
+            crate::markdown::render(index_page, md_opts, diag, cx.edition);
         } else {
             let dst = cx.dst.join("index.html");
             let mut w = BufWriter::new(try_err!(File::create(&dst), &dst));
@@ -2553,7 +2558,7 @@ fn render_markdown(w: &mut fmt::Formatter<'_>,
            if is_hidden { " hidden" } else { "" },
            prefix,
            Markdown(md_text, &links, RefCell::new(&mut ids),
-           cx.codes))
+           cx.codes, cx.edition))
 }
 
 fn document_short(
@@ -2918,7 +2923,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
 
         if let Some(note) = note {
             let mut ids = cx.id_map.borrow_mut();
-            let html = MarkdownHtml(&note, RefCell::new(&mut ids), error_codes);
+            let html = MarkdownHtml(&note, RefCell::new(&mut ids), error_codes, cx.edition);
             message.push_str(&format!(": {}", html));
         }
         stability.push(format!("<div class='stab deprecated'>{}</div>", message));
@@ -2967,7 +2972,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
             message = format!(
                 "<details><summary>{}</summary>{}</details>",
                 message,
-                MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes)
+                MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes, cx.edition)
             );
         }
 
@@ -2992,7 +2997,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec<String> {
 fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                  c: &clean::Constant) -> fmt::Result {
     write!(w, "<pre class='rust const'>")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "{vis}const \
                {name}: {typ}</pre>",
            vis = VisSpace(&it.visibility),
@@ -3004,7 +3009,7 @@ fn item_constant(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
 fn item_static(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                s: &clean::Static) -> fmt::Result {
     write!(w, "<pre class='rust static'>")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "{vis}static {mutability}\
                {name}: {typ}</pre>",
            vis = VisSpace(&it.visibility),
@@ -3027,7 +3032,7 @@ fn item_function(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
         f.generics
     ).len();
     write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it)?)?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w,
            "{vis}{constness}{unsafety}{asyncness}{abi}fn \
            {name}{generics}{decl}{where_clause}</pre>",
@@ -3116,7 +3121,7 @@ fn item_trait(
     // Output the trait definition
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust trait'>")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         write!(w, "{}{}{}trait {}{}{}",
                VisSpace(&it.visibility),
                UnsafetySpace(t.unsafety),
@@ -3379,8 +3384,10 @@ fn assoc_const(w: &mut fmt::Formatter<'_>,
                it: &clean::Item,
                ty: &clean::Type,
                _default: Option<&String>,
-               link: AssocItemLink<'_>) -> fmt::Result {
-    write!(w, "{}const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
+               link: AssocItemLink<'_>,
+               extra: &str) -> fmt::Result {
+    write!(w, "{}{}const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
+           extra,
            VisSpace(&it.visibility),
            naive_assoc_href(it, link),
            it.name.as_ref().unwrap(),
@@ -3391,8 +3398,10 @@ fn assoc_const(w: &mut fmt::Formatter<'_>,
 fn assoc_type<W: fmt::Write>(w: &mut W, it: &clean::Item,
                              bounds: &[clean::GenericBound],
                              default: Option<&clean::Type>,
-                             link: AssocItemLink<'_>) -> fmt::Result {
-    write!(w, "type <a href='{}' class=\"type\">{}</a>",
+                             link: AssocItemLink<'_>,
+                             extra: &str) -> fmt::Result {
+    write!(w, "{}type <a href='{}' class=\"type\">{}</a>",
+           extra,
            naive_assoc_href(it, link),
            it.name.as_ref().unwrap())?;
     if !bounds.is_empty() {
@@ -3469,7 +3478,7 @@ fn method(w: &mut fmt::Formatter<'_>,
         } else {
             (0, true)
         };
-        render_attributes(w, meth)?;
+        render_attributes(w, meth, false)?;
         write!(w, "{}{}{}{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                if parent == ItemType::Trait { "    " } else { "" },
@@ -3503,10 +3512,12 @@ fn method(w: &mut fmt::Formatter<'_>,
             method(w, item, m.header, &m.generics, &m.decl, link, parent)
         }
         clean::AssociatedConstItem(ref ty, ref default) => {
-            assoc_const(w, item, ty, default.as_ref(), link)
+            assoc_const(w, item, ty, default.as_ref(), link,
+                        if parent == ItemType::Trait { "    " } else { "" })
         }
         clean::AssociatedTypeItem(ref bounds, ref default) => {
-            assoc_type(w, item, bounds, default.as_ref(), link)
+            assoc_type(w, item, bounds, default.as_ref(), link,
+                       if parent == ItemType::Trait { "    " } else { "" })
         }
         _ => panic!("render_assoc_item called on non-associated-item")
     }
@@ -3516,7 +3527,7 @@ fn item_struct(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                s: &clean::Struct) -> fmt::Result {
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust struct'>")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         render_struct(w,
                       it,
                       Some(&s.generics),
@@ -3567,7 +3578,7 @@ fn item_union(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                s: &clean::Union) -> fmt::Result {
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust union'>")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         render_union(w,
                      it,
                      Some(&s.generics),
@@ -3612,7 +3623,7 @@ fn item_enum(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
              e: &clean::Enum) -> fmt::Result {
     wrap_into_docblock(w, |w| {
         write!(w, "<pre class='rust enum'>")?;
-        render_attributes(w, it)?;
+        render_attributes(w, it, true)?;
         write!(w, "{}enum {}{}{}",
                VisSpace(&it.visibility),
                it.name.as_ref().unwrap(),
@@ -3773,7 +3784,15 @@ fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
     sym::non_exhaustive
 ];
 
-fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result {
+// The `top` parameter is used when generating the item declaration to ensure it doesn't have a
+// left padding. For example:
+//
+// #[foo] <----- "top" attribute
+// struct Foo {
+//     #[bar] <---- not "top" attribute
+//     bar: usize,
+// }
+fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item, top: bool) -> fmt::Result {
     let mut attrs = String::new();
 
     for attr in &it.attrs.other_attrs {
@@ -3785,7 +3804,8 @@ fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item) -> fmt::Result {
         }
     }
     if attrs.len() > 0 {
-        write!(w, "<div class=\"docblock attributes\">{}</div>", &attrs)?;
+        write!(w, "<div class=\"docblock attributes{}\">{}</div>",
+               if top { " top-attr" } else { "" }, &attrs)?;
     }
     Ok(())
 }
@@ -4118,7 +4138,8 @@ fn spotlight_decl(decl: &clean::FnDecl) -> Result<String, fmt::Error> {
                             out.push_str("<span class=\"where fmt-newline\">    ");
                             assoc_type(&mut out, it, &[],
                                        Some(&tydef.type_),
-                                       AssocItemLink::GotoSource(t_did, &FxHashSet::default()))?;
+                                       AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
+                                       "")?;
                             out.push_str(";</span>");
                         }
                     }
@@ -4158,7 +4179,8 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt
                     if let clean::TypedefItem(ref tydef, _) = it.inner {
                         write!(w, "<span class=\"where fmt-newline\">  ")?;
                         assoc_type(w, it, &vec![], Some(&tydef.type_),
-                                   AssocItemLink::Anchor(None))?;
+                                   AssocItemLink::Anchor(None),
+                                   "")?;
                         write!(w, ";</span>")?;
                     }
                 }
@@ -4180,7 +4202,8 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt
         if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) {
             let mut ids = cx.id_map.borrow_mut();
             write!(w, "<div class='docblock'>{}</div>",
-                   Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?;
+                   Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids),
+                            cx.codes, cx.edition))?;
         }
     }
 
@@ -4228,7 +4251,7 @@ fn doc_impl_item(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item,
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                 write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<code id='{}'>", ns_id)?;
-                assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id))?;
+                assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id), "")?;
                 write!(w, "</code></h4>")?;
             }
             clean::AssociatedConstItem(ref ty, ref default) => {
@@ -4236,7 +4259,7 @@ fn doc_impl_item(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item,
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                 write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<code id='{}'>", ns_id)?;
-                assoc_const(w, item, ty, default.as_ref(), link.anchor(&id))?;
+                assoc_const(w, item, ty, default.as_ref(), link.anchor(&id), "")?;
                 write!(w, "</code>")?;
                 render_stability_since_raw(w, item.stable_since(), outer_version)?;
                 if let Some(l) = (Item { cx, item }).src_href() {
@@ -4250,7 +4273,7 @@ fn doc_impl_item(w: &mut fmt::Formatter<'_>, cx: &Context, item: &clean::Item,
                 let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
                 write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class)?;
                 write!(w, "<code id='{}'>", ns_id)?;
-                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id))?;
+                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "")?;
                 write!(w, "</code></h4>")?;
             }
             clean::StrippedItem(..) => return Ok(()),
@@ -4338,7 +4361,7 @@ fn item_existential(
     t: &clean::Existential,
 ) -> fmt::Result {
     write!(w, "<pre class='rust existential'>")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "existential type {}{}{where_clause}: {bounds};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
@@ -4357,7 +4380,7 @@ fn item_existential(
 fn item_trait_alias(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                     t: &clean::TraitAlias) -> fmt::Result {
     write!(w, "<pre class='rust trait-alias'>")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "trait {}{}{} = {};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
@@ -4376,7 +4399,7 @@ fn item_trait_alias(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
 fn item_typedef(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
                 t: &clean::Typedef) -> fmt::Result {
     write!(w, "<pre class='rust typedef'>")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(w, "type {}{}{where_clause} = {type_};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
@@ -4394,7 +4417,7 @@ fn item_typedef(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item,
 
 fn item_foreign_type(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item) -> fmt::Result {
     writeln!(w, "<pre class='rust foreigntype'>extern {{")?;
-    render_attributes(w, it)?;
+    render_attributes(w, it, false)?;
     write!(
         w,
         "    {}type {};\n}}</pre>",
index 85ab0855f05e9511de9bbead3d194429f9b37c00..72a01a49bc66dc2d8ddaf1cda6195062f2bea2eb 100644 (file)
@@ -2325,7 +2325,11 @@ if (!DOMTokenList.prototype.remove) {
     }
     var attributesToggle = createToggleWrapper(createSimpleToggle(false));
     onEachLazy(main.getElementsByClassName("attributes"), function(i_e) {
-        i_e.parentNode.insertBefore(attributesToggle.cloneNode(true), i_e);
+        var attr_tog = attributesToggle.cloneNode(true);
+        if (hasClass(i_e, "top-attr") === true) {
+            addClass(attr_tog, "top-attr");
+        }
+        i_e.parentNode.insertBefore(attr_tog, i_e);
         itemAttributesFunc(i_e);
     });
 
index 880b824335517a63f76f98104c66836d1b62a110..0493bf7c5c0f51c9045f89337db911f0c1a2d0a6 100644 (file)
@@ -182,12 +182,25 @@ nav.sub {
        display: none !important;
 }
 
-.sidebar img {
+.logo-container {
+       height: 100px;
+       width: 100px;
+       position: relative;
        margin: 20px auto;
        display: block;
        margin-top: 10px;
 }
 
+.logo-container > img {
+       max-width: 100px;
+       max-height: 100px;
+       position: absolute;
+       left: 50%;
+       top: 50%;
+       transform: translate(-50%, -50%);
+       display: block;
+}
+
 .sidebar .location {
        border: 1px solid;
        font-size: 17px;
@@ -658,18 +671,18 @@ a {
        transition: border-color 300ms ease;
        transition: border-radius 300ms ease-in-out;
        transition: box-shadow 300ms ease-in-out;
-       width: calc(100% - 32px);
+       width: 100%;
 }
 
 #crate-search + .search-input {
        border-radius: 0 1px 1px 0;
+       width: calc(100% - 32px);
 }
 
 .search-input:focus {
        border-radius: 2px;
        border: 0;
        outline: 0;
-       box-shadow: 0 0 8px #078dd8;
 }
 
 .search-results .desc {
@@ -998,6 +1011,195 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
        opacity: 1;
 }
 
+.information {
+       position: absolute;
+       left: -20px;
+       margin-top: 7px;
+       z-index: 1;
+}
+
+.tooltip {
+       position: relative;
+       display: inline-block;
+       cursor: pointer;
+}
+
+.tooltip .tooltiptext {
+       width: 120px;
+       display: none;
+       text-align: center;
+       padding: 5px 3px;
+       border-radius: 6px;
+       margin-left: 5px;
+       top: -5px;
+       left: 105%;
+       z-index: 10;
+}
+
+.tooltip:hover .tooltiptext {
+       display: inline;
+}
+
+.tooltip .tooltiptext::after {
+       content: " ";
+       position: absolute;
+       top: 50%;
+       left: 11px;
+       margin-top: -5px;
+       border-width: 5px;
+       border-style: solid;
+}
+
+.important-traits .tooltip .tooltiptext {
+       border: 1px solid;
+}
+
+pre.rust {
+       position: relative;
+       tab-width: 4;
+       -moz-tab-width: 4;
+}
+
+.search-failed {
+       text-align: center;
+       margin-top: 20px;
+}
+
+.search-failed > ul {
+       text-align: left;
+       max-width: 570px;
+       margin-left: auto;
+       margin-right: auto;
+}
+
+#titles {
+       height: 35px;
+}
+
+#titles > div {
+       float: left;
+       width: 33.3%;
+       text-align: center;
+       font-size: 18px;
+       cursor: pointer;
+       border-top: 2px solid;
+}
+
+#titles > div:not(:last-child) {
+       margin-right: 1px;
+       width: calc(33.3% - 1px);
+}
+
+#titles > div > div.count {
+       display: inline-block;
+       font-size: 16px;
+}
+
+.important-traits {
+       cursor: pointer;
+       z-index: 2;
+}
+
+h4 > .important-traits {
+       position: absolute;
+       left: -44px;
+       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;
+}
+
+#sidebar-toggle {
+       position: fixed;
+       top: 30px;
+       left: 300px;
+       z-index: 10;
+       padding: 3px;
+       border-top-right-radius: 3px;
+       border-bottom-right-radius: 3px;
+       cursor: pointer;
+       font-weight: bold;
+       transition: left .5s;
+       font-size: 1.2em;
+       border: 1px solid;
+       border-left: 0;
+}
+#source-sidebar {
+       position: fixed;
+       top: 0;
+       bottom: 0;
+       left: 0;
+       width: 300px;
+       z-index: 1;
+       overflow: auto;
+       transition: left .5s;
+       border-right: 1px solid;
+}
+#source-sidebar > .title {
+       font-size: 1.5em;
+       text-align: center;
+       border-bottom: 1px solid;
+       margin-bottom: 6px;
+}
+
+.theme-picker {
+       position: absolute;
+       left: 211px;
+       top: 19px;
+}
+
+.theme-picker button {
+       outline: none;
+}
+
+#settings-menu {
+       position: absolute;
+       right: 0;
+       top: 10px;
+       outline: none;
+}
+
+#theme-picker, #settings-menu {
+       padding: 4px;
+       width: 27px;
+       height: 29px;
+       border: 1px solid;
+       border-radius: 3px;
+       cursor: pointer;
+}
+
+#theme-choices {
+       display: none;
+       position: absolute;
+       left: 0;
+       top: 28px;
+       border: 1px solid;
+       border-radius: 3px;
+       z-index: 1;
+       cursor: pointer;
+}
+
+#theme-choices > button {
+       border: none;
+       width: 100%;
+       padding: 4px;
+       text-align: center;
+       background: rgba(0,0,0,0);
+}
+
+#theme-choices > button:not(:first-child) {
+       border-top: 1px solid;
+}
+
 /* Media Queries */
 
 @media (max-width: 700px) {
@@ -1030,14 +1232,20 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
                padding: 0;
        }
 
-       .sidebar img {
+       .sidebar .logo-container {
                width: 35px;
+               height: 35px;
                margin-top: 5px;
                margin-bottom: 5px;
                float: left;
                margin-left: 50px;
        }
 
+       .sidebar .logo-container > img {
+               max-width: 35px;
+               max-height: 35px;
+       }
+
        .sidebar-menu {
                position: fixed;
                z-index: 10;
@@ -1118,125 +1326,12 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
                overflow: initial;
        }
 
-       #main > .line-numbers {
-               margin-top: 0;
-       }
-}
-
-@media print {
-       nav.sub, .content .out-of-band, .collapse-toggle {
-               display: none;
+       .theme-picker {
+               left: 10px;
+               top: 54px;
+               z-index: 1;
        }
-}
 
-.information {
-       position: absolute;
-       left: -20px;
-       margin-top: 7px;
-       z-index: 1;
-}
-
-.tooltip {
-       position: relative;
-       display: inline-block;
-       cursor: pointer;
-}
-
-.tooltip .tooltiptext {
-       width: 120px;
-       display: none;
-       text-align: center;
-       padding: 5px 3px;
-       border-radius: 6px;
-       margin-left: 5px;
-       top: -5px;
-       left: 105%;
-       z-index: 10;
-}
-
-.tooltip:hover .tooltiptext {
-       display: inline;
-}
-
-.tooltip .tooltiptext::after {
-       content: " ";
-       position: absolute;
-       top: 50%;
-       left: 11px;
-       margin-top: -5px;
-       border-width: 5px;
-       border-style: solid;
-}
-
-.important-traits .tooltip .tooltiptext {
-       border: 1px solid;
-}
-
-pre.rust {
-       position: relative;
-       tab-width: 4;
-       -moz-tab-width: 4;
-}
-
-.search-failed {
-       text-align: center;
-       margin-top: 20px;
-}
-
-.search-failed > ul {
-       text-align: left;
-       max-width: 570px;
-       margin-left: auto;
-       margin-right: auto;
-}
-
-#titles {
-       height: 35px;
-}
-
-#titles > div {
-       float: left;
-       width: 33.3%;
-       text-align: center;
-       font-size: 18px;
-       cursor: pointer;
-       border-top: 2px solid;
-}
-
-#titles > div:not(:last-child) {
-       margin-right: 1px;
-       width: calc(33.3% - 1px);
-}
-
-#titles > div > div.count {
-       display: inline-block;
-       font-size: 16px;
-}
-
-.important-traits {
-       cursor: pointer;
-       z-index: 2;
-}
-
-h4 > .important-traits {
-       position: absolute;
-       left: -44px;
-       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;
                left: -22px;
@@ -1311,8 +1406,29 @@ h4 > .important-traits {
        #all-types {
                margin: 10px;
        }
+
+       #sidebar-toggle {
+               top: 100px;
+               width: 30px;
+               font-size: 1.5rem;
+               text-align: center;
+               padding: 0;
+       }
+
+       #source-sidebar {
+               z-index: 11;
+       }
+
+       #main > .line-numbers {
+               margin-top: 0;
+       }
 }
 
+@media print {
+       nav.sub, .content .out-of-band, .collapse-toggle {
+               display: none;
+       }
+}
 
 @media (max-width: 416px) {
        #titles {
@@ -1412,63 +1528,6 @@ kbd {
        cursor: default;
 }
 
-.theme-picker {
-       position: absolute;
-       left: 211px;
-       top: 19px;
-}
-
-.theme-picker button {
-       outline: none;
-}
-
-#settings-menu {
-       position: absolute;
-       right: 0;
-       top: 10px;
-       outline: none;
-}
-
-#theme-picker, #settings-menu {
-       padding: 4px;
-       width: 27px;
-       height: 29px;
-       border: 1px solid;
-       border-radius: 3px;
-       cursor: pointer;
-}
-
-#theme-choices {
-       display: none;
-       position: absolute;
-       left: 0;
-       top: 28px;
-       border: 1px solid;
-       border-radius: 3px;
-       z-index: 1;
-       cursor: pointer;
-}
-
-#theme-choices > button {
-       border: none;
-       width: 100%;
-       padding: 4px;
-       text-align: center;
-       background: rgba(0,0,0,0);
-}
-
-#theme-choices > button:not(:first-child) {
-       border-top: 1px solid;
-}
-
-@media (max-width: 700px) {
-       .theme-picker {
-               left: 10px;
-               top: 54px;
-               z-index: 1;
-       }
-}
-
 .hidden-by-impl-hider,
 .hidden-by-usual-hider {
        /* important because of conflicting rule for small screens */
@@ -1520,39 +1579,6 @@ kbd {
        margin-bottom: 1em;
 }
 
-#sidebar-toggle {
-       position: fixed;
-       top: 30px;
-       left: 300px;
-       z-index: 10;
-       padding: 3px;
-       border-top-right-radius: 3px;
-       border-bottom-right-radius: 3px;
-       cursor: pointer;
-       font-weight: bold;
-       transition: left .5s;
-       font-size: 1.2em;
-       border: 1px solid;
-       border-left: 0;
-}
-#source-sidebar {
-       position: fixed;
-       top: 0;
-       bottom: 0;
-       left: 0;
-       width: 300px;
-       z-index: 1;
-       overflow: auto;
-       transition: left .5s;
-       border-right: 1px solid;
-}
-#source-sidebar > .title {
-       font-size: 1.5em;
-       text-align: center;
-       border-bottom: 1px solid;
-       margin-bottom: 6px;
-}
-
 div.children {
        padding-left: 27px;
        display: none;
@@ -1587,10 +1613,10 @@ div.name.expand::before {
 }
 
 /* This part is to fix the "Expand attributes" part in the type declaration. */
-.type-decl > pre > :first-child {
+.type-decl > pre > .toggle-wrapper.toggle-attributes.top-attr {
        margin-left: 0 !important;
 }
-.type-decl > pre > :nth-child(2) {
+.type-decl > pre > .docblock.attributes.top-attr {
        margin-left: 1.8em !important;
 }
 .type-decl > pre > .toggle-attributes {
index f1255f52247376bd1e7f8285dd10bb695e33b592..e44ae2ad10cee286cba893f9ac63cffd2f96e6de 100644 (file)
@@ -164,20 +164,21 @@ a.test-arrow {
        color: #111;
        background-color: #f0f0f0;
        border-color: #000;
+       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
 }
 
 .search-input {
        color: #111;
-       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
        background-color: #f0f0f0;
+       box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent;
 }
 
 .search-input:focus {
        border-color: #008dfd;
 }
 
-#crate-search + .search-input {
-       box-shadow: 1px 0 0 1px #000, 0 0 0 2px transparent;
+#crate-search + .search-input:focus {
+       box-shadow: 0 0 8px 4px #078dd8;
 }
 
 .module-item .stab {
index c052e6b37ade7a51e9ac9bfad44763811af9e74b..4c37000dde2c5e4f6840309b237eae17d85e0461 100644 (file)
@@ -164,21 +164,21 @@ a.test-arrow {
        color: #555;
        background-color: white;
        border-color: #e0e0e0;
-       box-shadow: 0px 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
 }
 
 .search-input {
        color: #555;
-       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
        background-color: white;
+       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
 }
 
 .search-input:focus {
        border-color: #66afe9;
 }
 
-#crate-search + .search-input {
-       box-shadow: 1px 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+#crate-search + .search-input:focus {
+       box-shadow: 0 0 8px #078dd8;
 }
 
 .module-item .stab {
index 5b76f6861de79b084739f850186c562626032695..f5061b671828e04e704509fa535b531ba6cc941d 100644 (file)
@@ -391,7 +391,10 @@ fn main_args(args: &[String]) -> i32 {
     match (options.should_test, options.markdown_input()) {
         (true, true) => return markdown::test(options, &diag),
         (true, false) => return test::run(options),
-        (false, true) => return markdown::render(options.input, options.render_options, &diag),
+        (false, true) => return markdown::render(options.input,
+                                                 options.render_options,
+                                                 &diag,
+                                                 options.edition),
         (false, false) => {}
     }
 
@@ -399,7 +402,8 @@ fn main_args(args: &[String]) -> i32 {
     // but we can't crates the Handler ahead of time because it's not Send
     let diag_opts = (options.error_format,
                      options.debugging_options.treat_err_as_bug,
-                     options.debugging_options.ui_testing);
+                     options.debugging_options.ui_testing,
+                     options.edition);
     let show_coverage = options.show_coverage;
     rust_input(options, move |out| {
         if show_coverage {
@@ -410,7 +414,7 @@ fn main_args(args: &[String]) -> i32 {
 
         let Output { krate, passes, renderinfo, renderopts } = out;
         info!("going to format");
-        let (error_format, treat_err_as_bug, ui_testing) = diag_opts;
+        let (error_format, treat_err_as_bug, ui_testing, edition) = diag_opts;
         let diag = core::new_handler(error_format, None, treat_err_as_bug, ui_testing);
         match html::render::run(
             krate,
@@ -418,6 +422,7 @@ fn main_args(args: &[String]) -> i32 {
             passes.into_iter().collect(),
             renderinfo,
             &diag,
+            edition,
         ) {
             Ok(_) => rustc_driver::EXIT_SUCCESS,
             Err(e) => {
index c496dde8426c0fd8ba84bf64b8b43e0e5954fbe6..b0a37ea9c8081f50025fad2cfa5d50f5b0e80e1d 100644 (file)
@@ -5,6 +5,7 @@
 
 use errors;
 use testing;
+use syntax::edition::Edition;
 use syntax::source_map::DUMMY_SP;
 use syntax::feature_gate::UnstableFeatures;
 
@@ -36,7 +37,12 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
 
 /// Render `input` (e.g., "foo.md") into an HTML file in `output`
 /// (e.g., output = "bar" => "bar/foo.html").
-pub fn render(input: PathBuf, options: RenderOptions, diag: &errors::Handler) -> i32 {
+pub fn render(
+    input: PathBuf,
+    options: RenderOptions,
+    diag: &errors::Handler,
+    edition: Edition
+) -> i32 {
     let mut output = options.output;
     output.push(input.file_stem().unwrap());
     output.set_extension("html");
@@ -76,9 +82,9 @@ pub fn render(input: PathBuf, options: RenderOptions, diag: &errors::Handler) ->
     let mut ids = IdMap::new();
     let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
     let text = if !options.markdown_no_toc {
-        MarkdownWithToc(text, RefCell::new(&mut ids), error_codes).to_string()
+        MarkdownWithToc(text, RefCell::new(&mut ids), error_codes, edition).to_string()
     } else {
-        Markdown(text, &[], RefCell::new(&mut ids), error_codes).to_string()
+        Markdown(text, &[], RefCell::new(&mut ids), error_codes, edition).to_string()
     };
 
     let err = write!(
index 9e108e605c8bba9fc42a9f57cb2a22a519fe911d..2c382a1c1759632806bb316f621aa582564b9fe0 100644 (file)
@@ -321,7 +321,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
                             res
                         } else {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             // This could just be a normal link or a broken link
                             // we could potentially check if something is
                             // "intra-doc-link-like" and warn in that case.
@@ -332,7 +332,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         if let Ok(res) = self.resolve(path_str, ns, &current_item, parent_node) {
                             res
                         } else {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             // This could just be a normal link.
                             continue;
                         }
@@ -357,7 +357,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         };
 
                         if candidates.is_empty() {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             // this could just be a normal link
                             continue;
                         }
@@ -368,7 +368,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         } else {
                             ambiguity_error(
                                 cx,
-                                &item.attrs,
+                                &item,
                                 path_str,
                                 &dox,
                                 link_range,
@@ -381,7 +381,7 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
                         if let Some(res) = macro_resolve(cx, path_str) {
                             (res, None)
                         } else {
-                            resolution_failure(cx, &item.attrs, path_str, &dox, link_range);
+                            resolution_failure(cx, &item, path_str, &dox, link_range);
                             continue
                         }
                     }
@@ -452,16 +452,24 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
 /// line containing the failure as a note as well.
 fn resolution_failure(
     cx: &DocContext<'_>,
-    attrs: &Attributes,
+    item: &Item,
     path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
 ) {
+    let hir_id = match cx.as_local_hir_id(item.def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            // If non-local, no need to check anything.
+            return;
+        }
+    };
+    let attrs = &item.attrs;
     let sp = span_of_attrs(attrs);
 
     let mut diag = cx.tcx.struct_span_lint_hir(
         lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        hir::CRATE_HIR_ID,
+        hir_id,
         sp,
         &format!("`[{}]` cannot be resolved, ignoring it...", path_str),
     );
@@ -495,12 +503,20 @@ fn resolution_failure(
 
 fn ambiguity_error(
     cx: &DocContext<'_>,
-    attrs: &Attributes,
+    item: &Item,
     path_str: &str,
     dox: &str,
     link_range: Option<Range<usize>>,
     candidates: PerNS<Option<Res>>,
 ) {
+    let hir_id = match cx.as_local_hir_id(item.def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            // If non-local, no need to check anything.
+            return;
+        }
+    };
+    let attrs = &item.attrs;
     let sp = span_of_attrs(attrs);
 
     let mut msg = format!("`{}` is ", path_str);
@@ -532,7 +548,7 @@ fn ambiguity_error(
 
     let mut diag = cx.tcx.struct_span_lint_hir(
         lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
-        hir::CRATE_HIR_ID,
+        hir_id,
         sp,
         &msg,
     );
index 99aca0634710fdc88ac688cf1ffb45bac9ce7cba..d9af33ac5b622a39f288c14b3eca760c02900245 100644 (file)
@@ -1,7 +1,6 @@
 //! Contains information about "passes", used to modify crate information during the documentation
 //! process.
 
-use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::lint as lint;
 use rustc::middle::privacy::AccessLevels;
@@ -314,10 +313,13 @@ pub fn look_for_tests<'tcx>(
     item: &Item,
     check_missing_code: bool,
 ) {
-    if cx.as_local_hir_id(item.def_id).is_none() {
-        // If non-local, no need to check anything.
-        return;
-    }
+    let hir_id = match cx.as_local_hir_id(item.def_id) {
+        Some(hir_id) => hir_id,
+        None => {
+            // If non-local, no need to check anything.
+            return;
+        }
+    };
 
     struct Tests {
         found_tests: usize,
@@ -336,10 +338,11 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
     find_testable_code(&dox, &mut tests, ErrorCodes::No);
 
     if check_missing_code == true && tests.found_tests == 0 {
+        let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span());
         let mut diag = cx.tcx.struct_span_lint_hir(
             lint::builtin::MISSING_DOC_CODE_EXAMPLES,
-            hir::CRATE_HIR_ID,
-            span_of_attrs(&item.attrs),
+            hir_id,
+            sp,
             "Missing code example in this documentation");
         diag.emit();
     } else if check_missing_code == false &&
@@ -347,7 +350,7 @@ fn add_test(&mut self, _: String, _: LangString, _: usize) {
               !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) {
         let mut diag = cx.tcx.struct_span_lint_hir(
             lint::builtin::PRIVATE_DOC_TESTS,
-            hir::CRATE_HIR_ID,
+            hir_id,
             span_of_attrs(&item.attrs),
             "Documentation test in private item");
         diag.emit();
index e40dbe52ffe6423ecb9e259e7bfcd8b931a98088..0cc99da64079c006efb0df5493b1c210ac6cecf0 100644 (file)
@@ -167,7 +167,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
             maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
             persist_doctests: Option<PathBuf>) {
     let (test, line_offset) = match panic::catch_unwind(|| {
-        make_test(test, Some(cratename), as_test_harness, opts)
+        make_test(test, Some(cratename), as_test_harness, opts, edition)
     }) {
         Ok((test, line_offset)) => (test, line_offset),
         Err(cause) if cause.is::<errors::FatalErrorMarker>() => {
@@ -356,7 +356,8 @@ fn path(&self) -> &std::path::Path {
 pub fn make_test(s: &str,
                  cratename: Option<&str>,
                  dont_insert_main: bool,
-                 opts: &TestOptions)
+                 opts: &TestOptions,
+                 edition: Edition)
                  -> (String, usize) {
     let (crate_attrs, everything_else, crates) = partition_source(s);
     let everything_else = everything_else.trim();
@@ -390,6 +391,8 @@ pub fn make_test(s: &str,
         use errors::emitter::EmitterWriter;
         use errors::Handler;
 
+        syntax::ext::hygiene::set_default_edition(edition);
+
         let filename = FileName::anon_source_code(s);
         let source = crates + &everything_else;
 
@@ -397,6 +400,7 @@ pub fn make_test(s: &str,
         // send all the errors that libsyntax emits directly into a `Sink` instead of stderr.
         let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
         let emitter = EmitterWriter::new(box io::sink(), None, false, false, false);
+        // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
         let handler = Handler::with_emitter(false, None, box emitter);
         let sess = ParseSess::with_span_handler(handler, cm);
 
@@ -880,6 +884,7 @@ fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef) {
 #[cfg(test)]
 mod tests {
     use super::{TestOptions, make_test};
+    use syntax::edition::DEFAULT_EDITION;
 
     #[test]
     fn make_test_basic() {
@@ -892,7 +897,7 @@ fn make_test_basic() {
 fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, None, false, &opts);
+        let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -908,7 +913,7 @@ fn make_test_crate_name_no_use() {
 fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -927,7 +932,7 @@ fn main() {
 use asdf::qwop;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 3));
     }
 
@@ -949,7 +954,7 @@ fn main() {
 use asdf::qwop;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -968,7 +973,7 @@ fn main() {
 use std::*;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("std"), false, &opts);
+        let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -988,7 +993,7 @@ fn main() {
 use asdf::qwop;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -1006,7 +1011,7 @@ fn main() {
 use asdf::qwop;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -1026,7 +1031,7 @@ fn main() {
 use asdf::qwop;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 3));
 
         // Adding more will also bump the returned line offset.
@@ -1039,7 +1044,7 @@ fn main() {
 use asdf::qwop;
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 4));
     }
 
@@ -1057,7 +1062,7 @@ fn make_test_crate_attrs() {
 fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, None, false, &opts);
+        let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -1074,7 +1079,7 @@ fn make_test_with_main() {
 fn main() {
     assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, None, false, &opts);
+        let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 1));
     }
 
@@ -1091,7 +1096,7 @@ fn make_test_fake_main() {
 fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, None, false, &opts);
+        let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
     }
 
@@ -1106,7 +1111,7 @@ fn make_test_dont_insert_main() {
 "#![allow(unused)]
 //Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);".to_string();
-        let output = make_test(input, None, true, &opts);
+        let output = make_test(input, None, true, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 1));
     }
 
@@ -1121,7 +1126,7 @@ fn make_test_display_warnings() {
 "fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
-        let output = make_test(input, None, false, &opts);
+        let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 1));
     }
 
@@ -1140,7 +1145,7 @@ fn main() {
 assert_eq!(2+2, 4);
 }".to_string();
 
-        let output = make_test(input, None, false, &opts);
+        let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 2));
 
         let input =
@@ -1155,7 +1160,7 @@ fn main() {
 assert_eq!(asdf::foo, 4);
 }".to_string();
 
-        let output = make_test(input, Some("asdf"), false, &opts);
+        let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 3));
     }
 
@@ -1174,7 +1179,7 @@ fn main() {}
     fn main() {}
 }".to_string();
 
-        let output = make_test(input, Some("my_crate"), false, &opts);
+        let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
         assert_eq!(output, (expected, 1));
     }
 }
index 4241f47b661d721b742a0b9bc8124592d7efeb8e..ff52974775b05268e1a4b3b49a704340a6f24d50 100644 (file)
@@ -173,6 +173,9 @@ unsafe fn realloc(&mut self,
 /// about the allocation that failed.
 ///
 /// The allocation error hook is a global resource.
+///
+/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html
+/// [`take_alloc_error_hook`]: fn.take_alloc_error_hook.html
 #[unstable(feature = "alloc_error_hook", issue = "51245")]
 pub fn set_alloc_error_hook(hook: fn(Layout)) {
     HOOK.store(hook as *mut (), Ordering::SeqCst);
@@ -183,6 +186,8 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) {
 /// *See also the function [`set_alloc_error_hook`].*
 ///
 /// If no custom hook is registered, the default hook will be returned.
+///
+/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html
 #[unstable(feature = "alloc_error_hook", issue = "51245")]
 pub fn take_alloc_error_hook() -> fn(Layout) {
     let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst);
index 478f63ab3d7f7bbb8e08ffb2e0b7550cd6bd6995..5a2fe2b244f556d16127daf3244da70fed785ecc 100644 (file)
@@ -2494,7 +2494,10 @@ pub fn new() -> DefaultHasher {
 
 #[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
 impl Default for DefaultHasher {
-    /// Creates a new `DefaultHasher` using [`new`][DefaultHasher::new].
+    // FIXME: here should link `new` to [DefaultHasher::new], but it occurs intra-doc link
+    // resolution failure when re-exporting libstd items. When #56922 fixed,
+    // link `new` to [DefaultHasher::new] again.
+    /// Creates a new `DefaultHasher` using `new`.
     /// See its documentation for more.
     fn default() -> DefaultHasher {
         DefaultHasher::new()
index 62282006a40248df320c8eedc5c99c37b5b4683c..aeb822fa99e66a6fd1920de1c16aea4203ff4677 100644 (file)
@@ -218,6 +218,8 @@ mod private {
 impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
     /// Converts a type of [`Error`] into a box of dyn [`Error`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -255,6 +257,8 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
     /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] +
     /// [`Send`] + [`Sync`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -296,6 +300,8 @@ fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
 impl From<String> for Box<dyn Error + Send + Sync> {
     /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -329,6 +335,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl From<String> for Box<dyn Error> {
     /// Converts a [`String`] into a box of dyn [`Error`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -350,6 +358,8 @@ fn from(str_err: String) -> Box<dyn Error> {
 impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
     /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -370,6 +380,8 @@ fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
 impl From<&str> for Box<dyn Error> {
     /// Converts a [`str`] into a box of dyn [`Error`].
     ///
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -389,6 +401,9 @@ fn from(err: &str) -> Box<dyn Error> {
 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
     /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
     ///
+    /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -410,6 +425,9 @@ fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
     /// Converts a [`Cow`] into a box of dyn [`Error`].
     ///
+    /// [`Cow`]: ../borrow/enum.Cow.html
+    /// [`Error`]: ../error/trait.Error.html
+    ///
     /// # Examples
     ///
     /// ```
index 13aee783750f1dfbb8a9cc81fcddcce61890baa0..c7c5849a00fa03e7ded2fe25de405f195575d0f2 100644 (file)
@@ -351,6 +351,8 @@ impl From<String> for OsString {
     /// Converts a [`String`] into a [`OsString`].
     ///
     /// The conversion copies the data, and includes an allocation on the heap.
+    ///
+    /// [`OsString`]: ../../std/ffi/struct.OsString.html
     fn from(s: String) -> OsString {
         OsString { inner: Buf::from_string(s) }
     }
index 991b45fd4a2ec2caf03b10b4d49237967226c7f2..616b5eb836ffd6c8c20163cd752790ade30ef170 100644 (file)
@@ -1812,6 +1812,8 @@ pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 ///   function.)
 /// * `path` already exists.
 ///
+/// [`create_dir_all`]: fn.create_dir_all.html
+///
 /// # Examples
 ///
 /// ```no_run
index 5be2687d8f5ff3bb14af96ab9c413ec7d46d123e..e309f81192cf3ffb7322bd4540da7beb5c384461 100644 (file)
@@ -754,7 +754,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// completed, rather than the entire buffer at once. Enter `LineWriter`. It
 /// does exactly that.
 ///
-/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
+/// Like [`BufWriter`][bufwriter], a `LineWriter`’s buffer will also be flushed when the
 /// `LineWriter` goes out of scope or when its internal buffer is full.
 ///
 /// [bufwriter]: struct.BufWriter.html
index 8fea6251e652a143a2ae29aab6f616692f543080..917199f8ea8d03fe770c6a806a59d54ae207eac4 100644 (file)
@@ -1579,18 +1579,13 @@ pub trait BufRead: Read {
     /// let stdin = io::stdin();
     /// let mut stdin = stdin.lock();
     ///
-    /// // we can't have two `&mut` references to `stdin`, so use a block
-    /// // to end the borrow early.
-    /// let length = {
-    ///     let buffer = stdin.fill_buf().unwrap();
+    /// let buffer = stdin.fill_buf().unwrap();
     ///
-    ///     // work with buffer
-    ///     println!("{:?}", buffer);
-    ///
-    ///     buffer.len()
-    /// };
+    /// // work with buffer
+    /// println!("{:?}", buffer);
     ///
     /// // ensure the bytes we worked with aren't returned again later
+    /// let length = buffer.len();
     /// stdin.consume(length);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
index 2401946536ffa0f9af76ad43871d03ac4eb0aa12..e044b46e0d0763252baf5254a69fe57f88d1e5b8 100644 (file)
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(linkage)]
-#![feature(maybe_uninit)]
 #![feature(needs_panic_runtime)]
 #![feature(never_type)]
 #![feature(nll)]
index 03aebeda47c4851f707c2d2ffb39682e166c4dcf..9af7bba97aa58de06daab2106874f17909a16cd6 100644 (file)
@@ -357,61 +357,6 @@ macro_rules! dbg {
     };
 }
 
-/// Selects the first successful receive event from a number of receivers.
-///
-/// This macro is used to wait for the first event to occur on a number of
-/// receivers. It places no restrictions on the types of receivers given to
-/// this macro, this can be viewed as a heterogeneous select.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(mpsc_select)]
-///
-/// use std::thread;
-/// use std::sync::mpsc;
-///
-/// // two placeholder functions for now
-/// fn long_running_thread() {}
-/// fn calculate_the_answer() -> u32 { 42 }
-///
-/// let (tx1, rx1) = mpsc::channel();
-/// let (tx2, rx2) = mpsc::channel();
-///
-/// thread::spawn(move|| { long_running_thread(); tx1.send(()).unwrap(); });
-/// thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); });
-///
-/// select! {
-///     _ = rx1.recv() => println!("the long running thread finished first"),
-///     answer = rx2.recv() => {
-///         println!("the answer was: {}", answer.unwrap());
-///     }
-/// }
-/// # drop(rx1.recv());
-/// # drop(rx2.recv());
-/// ```
-///
-/// For more information about select, see the `std::sync::mpsc::Select` structure.
-#[macro_export]
-#[unstable(feature = "mpsc_select", issue = "27800")]
-#[rustc_deprecated(since = "1.32.0",
-                   reason = "channel selection will be removed in a future release")]
-macro_rules! select {
-    (
-        $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
-    ) => ({
-        use $crate::sync::mpsc::Select;
-        let sel = Select::new();
-        $( let mut $rx = sel.handle(&$rx); )+
-        unsafe {
-            $( $rx.add(); )+
-        }
-        let ret = sel.wait();
-        $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
-        { unreachable!() }
-    })
-}
-
 #[cfg(test)]
 macro_rules! assert_approx_eq {
     ($a:expr, $b:expr) => ({
index e7923e381f1407205c647012acf15c81aab40644..ca86a175058b512dd2259349393a2c200565f920 100644 (file)
@@ -546,6 +546,9 @@ fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV4> for SocketAddr {
     /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
+    ///
+    /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+    /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
     fn from(sock4: SocketAddrV4) -> SocketAddr {
         SocketAddr::V4(sock4)
     }
@@ -554,6 +557,9 @@ fn from(sock4: SocketAddrV4) -> SocketAddr {
 #[stable(feature = "ip_from_ip", since = "1.16.0")]
 impl From<SocketAddrV6> for SocketAddr {
     /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
+    ///
+    /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+    /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
     fn from(sock6: SocketAddrV6) -> SocketAddr {
         SocketAddr::V6(sock6)
     }
@@ -567,6 +573,13 @@ impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
     /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
     ///
     /// `u16` is treated as port of the newly created [`SocketAddr`].
+    ///
+    /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+    /// [`IpAddr::V4`]: ../../std/net/enum.IpAddr.html#variant.V4
+    /// [`IpAddr::V6`]: ../../std/net/enum.IpAddr.html#variant.V6
+    /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+    /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
+    /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
     fn from(pieces: (I, u16)) -> SocketAddr {
         SocketAddr::new(pieces.0.into(), pieces.1)
     }
index 04353fde1b4d97620d17ad07702446d130dc5073..69ecd201063b034baf0f8d5df0074823a89ecda6 100644 (file)
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
-#![allow(deprecated)] // for mpsc_select
 
 // A description of how Rust's channel implementation works
 //
 // believe that there is anything fundamental that needs to change about these
 // channels, however, in order to support a more efficient select().
 //
+// FIXME: Select is now removed, so these factors are ready to be cleaned up!
+//
 // # Conclusion
 //
 // And now that you've seen all the races that I found and attempted to fix,
 use crate::cell::UnsafeCell;
 use crate::time::{Duration, Instant};
 
-#[unstable(feature = "mpsc_select", issue = "27800")]
-pub use self::select::{Select, Handle};
-use self::select::StartResult;
-use self::select::StartResult::*;
-use self::blocking::SignalToken;
-
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod select_tests;
-
 mod blocking;
 mod oneshot;
-mod select;
 mod shared;
 mod stream;
 mod sync;
@@ -1514,78 +1505,6 @@ pub fn try_iter(&self) -> TryIter<'_, T> {
 
 }
 
-impl<T> select::Packet for Receiver<T> {
-    fn can_recv(&self) -> bool {
-        loop {
-            let new_port = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => {
-                    match p.can_recv() {
-                        Ok(ret) => return ret,
-                        Err(upgrade) => upgrade,
-                    }
-                }
-                Flavor::Stream(ref p) => {
-                    match p.can_recv() {
-                        Ok(ret) => return ret,
-                        Err(upgrade) => upgrade,
-                    }
-                }
-                Flavor::Shared(ref p) => return p.can_recv(),
-                Flavor::Sync(ref p) => return p.can_recv(),
-            };
-            unsafe {
-                mem::swap(self.inner_mut(),
-                          new_port.inner_mut());
-            }
-        }
-    }
-
-    fn start_selection(&self, mut token: SignalToken) -> StartResult {
-        loop {
-            let (t, new_port) = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => {
-                    match p.start_selection(token) {
-                        oneshot::SelSuccess => return Installed,
-                        oneshot::SelCanceled => return Abort,
-                        oneshot::SelUpgraded(t, rx) => (t, rx),
-                    }
-                }
-                Flavor::Stream(ref p) => {
-                    match p.start_selection(token) {
-                        stream::SelSuccess => return Installed,
-                        stream::SelCanceled => return Abort,
-                        stream::SelUpgraded(t, rx) => (t, rx),
-                    }
-                }
-                Flavor::Shared(ref p) => return p.start_selection(token),
-                Flavor::Sync(ref p) => return p.start_selection(token),
-            };
-            token = t;
-            unsafe {
-                mem::swap(self.inner_mut(), new_port.inner_mut());
-            }
-        }
-    }
-
-    fn abort_selection(&self) -> bool {
-        let mut was_upgrade = false;
-        loop {
-            let result = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => p.abort_selection(),
-                Flavor::Stream(ref p) => p.abort_selection(was_upgrade),
-                Flavor::Shared(ref p) => return p.abort_selection(was_upgrade),
-                Flavor::Sync(ref p) => return p.abort_selection(),
-            };
-            let new_port = match result { Ok(b) => return b, Err(p) => p };
-            was_upgrade = true;
-            unsafe {
-                mem::swap(self.inner_mut(),
-                          new_port.inner_mut());
-            }
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = T;
index 5c516d5de0f176ed735d8e2cc7a6de488d5e83c2..e7a5cc46b31a857912e23bc880fac2c97d4580e2 100644 (file)
@@ -24,7 +24,6 @@
 
 pub use self::Failure::*;
 pub use self::UpgradeResult::*;
-pub use self::SelectionResult::*;
 use self::MyUpgrade::*;
 
 use crate::sync::mpsc::Receiver;
@@ -66,12 +65,6 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
-    SelCanceled,
-    SelUpgraded(SignalToken, Receiver<T>),
-    SelSuccess,
-}
-
 enum MyUpgrade<T> {
     NothingSent,
     SendUsed,
@@ -264,71 +257,6 @@ pub fn drop_port(&self) {
     // select implementation
     ////////////////////////////////////////////////////////////////////////////
 
-    // If Ok, the value is whether this port has data, if Err, then the upgraded
-    // port needs to be checked instead of this one.
-    pub fn can_recv(&self) -> Result<bool, Receiver<T>> {
-        unsafe {
-            match self.state.load(Ordering::SeqCst) {
-                EMPTY => Ok(false), // Welp, we tried
-                DATA => Ok(true),   // we have some un-acquired data
-                DISCONNECTED if (*self.data.get()).is_some() => Ok(true), // we have data
-                DISCONNECTED => {
-                    match ptr::replace(self.upgrade.get(), SendUsed) {
-                        // The other end sent us an upgrade, so we need to
-                        // propagate upwards whether the upgrade can receive
-                        // data
-                        GoUp(upgrade) => Err(upgrade),
-
-                        // If the other end disconnected without sending an
-                        // upgrade, then we have data to receive (the channel is
-                        // disconnected).
-                        up => { ptr::write(self.upgrade.get(), up); Ok(true) }
-                    }
-                }
-                _ => unreachable!(), // we're the "one blocker"
-            }
-        }
-    }
-
-    // Attempts to start selection on this port. This can either succeed, fail
-    // because there is data, or fail because there is an upgrade pending.
-    pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> {
-        unsafe {
-            let ptr = token.cast_to_usize();
-            match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
-                EMPTY => SelSuccess,
-                DATA => {
-                    drop(SignalToken::cast_from_usize(ptr));
-                    SelCanceled
-                }
-                DISCONNECTED if (*self.data.get()).is_some() => {
-                    drop(SignalToken::cast_from_usize(ptr));
-                    SelCanceled
-                }
-                DISCONNECTED => {
-                    match ptr::replace(self.upgrade.get(), SendUsed) {
-                        // The other end sent us an upgrade, so we need to
-                        // propagate upwards whether the upgrade can receive
-                        // data
-                        GoUp(upgrade) => {
-                            SelUpgraded(SignalToken::cast_from_usize(ptr), upgrade)
-                        }
-
-                        // If the other end disconnected without sending an
-                        // upgrade, then we have data to receive (the channel is
-                        // disconnected).
-                        up => {
-                            ptr::write(self.upgrade.get(), up);
-                            drop(SignalToken::cast_from_usize(ptr));
-                            SelCanceled
-                        }
-                    }
-                }
-                _ => unreachable!(), // we're the "one blocker"
-            }
-        }
-    }
-
     // Remove a previous selecting thread from this port. This ensures that the
     // blocked thread will no longer be visible to any other threads.
     //
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
deleted file mode 100644 (file)
index d1b5f2d..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-//! Selection over an array of receivers
-//!
-//! This module contains the implementation machinery necessary for selecting
-//! over a number of receivers. One large goal of this module is to provide an
-//! efficient interface to selecting over any receiver of any type.
-//!
-//! This is achieved through an architecture of a "receiver set" in which
-//! receivers are added to a set and then the entire set is waited on at once.
-//! The set can be waited on multiple times to prevent re-adding each receiver
-//! to the set.
-//!
-//! Usage of this module is currently encouraged to go through the use of the
-//! `select!` macro. This macro allows naturally binding of variables to the
-//! received values of receivers in a much more natural syntax then usage of the
-//! `Select` structure directly.
-//!
-//! # Examples
-//!
-//! ```rust
-//! #![feature(mpsc_select)]
-//!
-//! use std::sync::mpsc::channel;
-//!
-//! let (tx1, rx1) = channel();
-//! let (tx2, rx2) = channel();
-//!
-//! tx1.send(1).unwrap();
-//! tx2.send(2).unwrap();
-//!
-//! select! {
-//!     val = rx1.recv() => {
-//!         assert_eq!(val.unwrap(), 1);
-//!     },
-//!     val = rx2.recv() => {
-//!         assert_eq!(val.unwrap(), 2);
-//!     }
-//! }
-//! ```
-
-#![allow(dead_code)]
-#![unstable(feature = "mpsc_select",
-            reason = "This implementation, while likely sufficient, is unsafe and \
-                      likely to be error prone. At some point in the future this \
-                      module will be removed.",
-            issue = "27800")]
-#![rustc_deprecated(since = "1.32.0",
-                    reason = "channel selection will be removed in a future release")]
-
-use core::cell::{Cell, UnsafeCell};
-use core::marker;
-use core::ptr;
-use core::usize;
-
-use crate::fmt;
-use crate::sync::mpsc::{Receiver, RecvError};
-use crate::sync::mpsc::blocking::{self, SignalToken};
-
-/// The "receiver set" of the select interface. This structure is used to manage
-/// a set of receivers which are being selected over.
-pub struct Select {
-    inner: UnsafeCell<SelectInner>,
-    next_id: Cell<usize>,
-}
-
-struct SelectInner {
-    head: *mut Handle<'static, ()>,
-    tail: *mut Handle<'static, ()>,
-}
-
-impl !marker::Send for Select {}
-
-/// A handle to a receiver which is currently a member of a `Select` set of
-/// receivers. This handle is used to keep the receiver in the set as well as
-/// interact with the underlying receiver.
-pub struct Handle<'rx, T:Send+'rx> {
-    /// The ID of this handle, used to compare against the return value of
-    /// `Select::wait()`.
-    id: usize,
-    selector: *mut SelectInner,
-    next: *mut Handle<'static, ()>,
-    prev: *mut Handle<'static, ()>,
-    added: bool,
-    packet: &'rx (dyn Packet+'rx),
-
-    // due to our fun transmutes, we be sure to place this at the end. (nothing
-    // previous relies on T)
-    rx: &'rx Receiver<T>,
-}
-
-struct Packets { cur: *mut Handle<'static, ()> }
-
-#[doc(hidden)]
-#[derive(PartialEq, Eq)]
-pub enum StartResult {
-    Installed,
-    Abort,
-}
-
-#[doc(hidden)]
-pub trait Packet {
-    fn can_recv(&self) -> bool;
-    fn start_selection(&self, token: SignalToken) -> StartResult;
-    fn abort_selection(&self) -> bool;
-}
-
-impl Select {
-    /// Creates a new selection structure. This set is initially empty.
-    ///
-    /// Usage of this struct directly can sometimes be burdensome, and usage is much easier through
-    /// the `select!` macro.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(mpsc_select)]
-    ///
-    /// use std::sync::mpsc::Select;
-    ///
-    /// let select = Select::new();
-    /// ```
-    pub fn new() -> Select {
-        Select {
-            inner: UnsafeCell::new(SelectInner {
-                head: ptr::null_mut(),
-                tail: ptr::null_mut(),
-            }),
-            next_id: Cell::new(1),
-        }
-    }
-
-    /// Creates a new handle into this receiver set for a new receiver. Note
-    /// that this does *not* add the receiver to the receiver set, for that you
-    /// must call the `add` method on the handle itself.
-    pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
-        let id = self.next_id.get();
-        self.next_id.set(id + 1);
-        Handle {
-            id,
-            selector: self.inner.get(),
-            next: ptr::null_mut(),
-            prev: ptr::null_mut(),
-            added: false,
-            rx,
-            packet: rx,
-        }
-    }
-
-    /// Waits for an event on this receiver set. The returned value is *not* an
-    /// index, but rather an ID. This ID can be queried against any active
-    /// `Handle` structures (each one has an `id` method). The handle with
-    /// the matching `id` will have some sort of event available on it. The
-    /// event could either be that data is available or the corresponding
-    /// channel has been closed.
-    pub fn wait(&self) -> usize {
-        self.wait2(true)
-    }
-
-    /// Helper method for skipping the preflight checks during testing
-    pub(super) fn wait2(&self, do_preflight_checks: bool) -> usize {
-        // Note that this is currently an inefficient implementation. We in
-        // theory have knowledge about all receivers in the set ahead of time,
-        // so this method shouldn't really have to iterate over all of them yet
-        // again. The idea with this "receiver set" interface is to get the
-        // interface right this time around, and later this implementation can
-        // be optimized.
-        //
-        // This implementation can be summarized by:
-        //
-        //      fn select(receivers) {
-        //          if any receiver ready { return ready index }
-        //          deschedule {
-        //              block on all receivers
-        //          }
-        //          unblock on all receivers
-        //          return ready index
-        //      }
-        //
-        // Most notably, the iterations over all of the receivers shouldn't be
-        // necessary.
-        unsafe {
-            // Stage 1: preflight checks. Look for any packets ready to receive
-            if do_preflight_checks {
-                for handle in self.iter() {
-                    if (*handle).packet.can_recv() {
-                        return (*handle).id();
-                    }
-                }
-            }
-
-            // Stage 2: begin the blocking process
-            //
-            // Create a number of signal tokens, and install each one
-            // sequentially until one fails. If one fails, then abort the
-            // selection on the already-installed tokens.
-            let (wait_token, signal_token) = blocking::tokens();
-            for (i, handle) in self.iter().enumerate() {
-                match (*handle).packet.start_selection(signal_token.clone()) {
-                    StartResult::Installed => {}
-                    StartResult::Abort => {
-                        // Go back and abort the already-begun selections
-                        for handle in self.iter().take(i) {
-                            (*handle).packet.abort_selection();
-                        }
-                        return (*handle).id;
-                    }
-                }
-            }
-
-            // Stage 3: no messages available, actually block
-            wait_token.wait();
-
-            // Stage 4: there *must* be message available; find it.
-            //
-            // Abort the selection process on each receiver. If the abort
-            // process returns `true`, then that means that the receiver is
-            // ready to receive some data. Note that this also means that the
-            // receiver may have yet to have fully read the `to_wake` field and
-            // woken us up (although the wakeup is guaranteed to fail).
-            //
-            // This situation happens in the window of where a sender invokes
-            // increment(), sees -1, and then decides to wake up the thread. After
-            // all this is done, the sending thread will set `selecting` to
-            // `false`. Until this is done, we cannot return. If we were to
-            // return, then a sender could wake up a receiver which has gone
-            // back to sleep after this call to `select`.
-            //
-            // Note that it is a "fairly small window" in which an increment()
-            // views that it should wake a thread up until the `selecting` bit
-            // is set to false. For now, the implementation currently just spins
-            // in a yield loop. This is very distasteful, but this
-            // implementation is already nowhere near what it should ideally be.
-            // A rewrite should focus on avoiding a yield loop, and for now this
-            // implementation is tying us over to a more efficient "don't
-            // iterate over everything every time" implementation.
-            let mut ready_id = usize::MAX;
-            for handle in self.iter() {
-                if (*handle).packet.abort_selection() {
-                    ready_id = (*handle).id;
-                }
-            }
-
-            // We must have found a ready receiver
-            assert!(ready_id != usize::MAX);
-            return ready_id;
-        }
-    }
-
-    fn iter(&self) -> Packets { Packets { cur: unsafe { &*self.inner.get() }.head } }
-}
-
-impl<'rx, T: Send> Handle<'rx, T> {
-    /// Retrieves the ID of this handle.
-    #[inline]
-    pub fn id(&self) -> usize { self.id }
-
-    /// Blocks to receive a value on the underlying receiver, returning `Some` on
-    /// success or `None` if the channel disconnects. This function has the same
-    /// semantics as `Receiver.recv`
-    pub fn recv(&mut self) -> Result<T, RecvError> { self.rx.recv() }
-
-    /// Adds this handle to the receiver set that the handle was created from. This
-    /// method can be called multiple times, but it has no effect if `add` was
-    /// called previously.
-    ///
-    /// This method is unsafe because it requires that the `Handle` is not moved
-    /// while it is added to the `Select` set.
-    pub unsafe fn add(&mut self) {
-        if self.added { return }
-        let selector = &mut *self.selector;
-        let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>;
-
-        if selector.head.is_null() {
-            selector.head = me;
-            selector.tail = me;
-        } else {
-            (*me).prev = selector.tail;
-            assert!((*me).next.is_null());
-            (*selector.tail).next = me;
-            selector.tail = me;
-        }
-        self.added = true;
-    }
-
-    /// Removes this handle from the `Select` set. This method is unsafe because
-    /// it has no guarantee that the `Handle` was not moved since `add` was
-    /// called.
-    pub unsafe fn remove(&mut self) {
-        if !self.added { return }
-
-        let selector = &mut *self.selector;
-        let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>;
-
-        if self.prev.is_null() {
-            assert_eq!(selector.head, me);
-            selector.head = self.next;
-        } else {
-            (*self.prev).next = self.next;
-        }
-        if self.next.is_null() {
-            assert_eq!(selector.tail, me);
-            selector.tail = self.prev;
-        } else {
-            (*self.next).prev = self.prev;
-        }
-
-        self.next = ptr::null_mut();
-        self.prev = ptr::null_mut();
-
-        self.added = false;
-    }
-}
-
-impl Drop for Select {
-    fn drop(&mut self) {
-        unsafe {
-            assert!((&*self.inner.get()).head.is_null());
-            assert!((&*self.inner.get()).tail.is_null());
-        }
-    }
-}
-
-impl<T: Send> Drop for Handle<'_, T> {
-    fn drop(&mut self) {
-        unsafe { self.remove() }
-    }
-}
-
-impl Iterator for Packets {
-    type Item = *mut Handle<'static, ()>;
-
-    fn next(&mut self) -> Option<*mut Handle<'static, ()>> {
-        if self.cur.is_null() {
-            None
-        } else {
-            let ret = Some(self.cur);
-            unsafe { self.cur = (*self.cur).next; }
-            ret
-        }
-    }
-}
-
-impl fmt::Debug for Select {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Select").finish()
-    }
-}
-
-impl<T: Send> fmt::Debug for Handle<'_, T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Handle").finish()
-    }
-}
diff --git a/src/libstd/sync/mpsc/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs
deleted file mode 100644 (file)
index 18d9346..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-#![allow(unused_imports)]
-
-/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238
-
-use crate::thread;
-use crate::sync::mpsc::*;
-
-// Don't use the libstd version so we can pull in the right Select structure
-// (std::comm points at the wrong one)
-macro_rules! select {
-    (
-        $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
-    ) => ({
-        let sel = Select::new();
-        $( let mut $rx = sel.handle(&$rx); )+
-        unsafe {
-            $( $rx.add(); )+
-        }
-        let ret = sel.wait();
-        $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+
-        { unreachable!() }
-    })
-}
-
-#[test]
-fn smoke() {
-    let (tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    tx1.send(1).unwrap();
-    select! {
-        foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); },
-        _bar = rx2.recv() => { panic!() }
-    }
-    tx2.send(2).unwrap();
-    select! {
-        _foo = rx1.recv() => { panic!() },
-        bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) }
-    }
-    drop(tx1);
-    select! {
-        foo = rx1.recv() => { assert!(foo.is_err()); },
-        _bar = rx2.recv() => { panic!() }
-    }
-    drop(tx2);
-    select! {
-        bar = rx2.recv() => { assert!(bar.is_err()); }
-    }
-}
-
-#[test]
-fn smoke2() {
-    let (_tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (_tx3, rx3) = channel::<i32>();
-    let (_tx4, rx4) = channel::<i32>();
-    let (tx5, rx5) = channel::<i32>();
-    tx5.send(4).unwrap();
-    select! {
-        _foo = rx1.recv() => { panic!("1") },
-        _foo = rx2.recv() => { panic!("2") },
-        _foo = rx3.recv() => { panic!("3") },
-        _foo = rx4.recv() => { panic!("4") },
-        foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); }
-    }
-}
-
-#[test]
-fn closed() {
-    let (_tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    drop(tx2);
-
-    select! {
-        _a1 = rx1.recv() => { panic!() },
-        a2 = rx2.recv() => { assert!(a2.is_err()); }
-    }
-}
-
-#[test]
-fn unblocks() {
-    let (tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<i32>();
-
-    let _t = thread::spawn(move|| {
-        for _ in 0..20 { thread::yield_now(); }
-        tx1.send(1).unwrap();
-        rx3.recv().unwrap();
-        for _ in 0..20 { thread::yield_now(); }
-    });
-
-    select! {
-        a = rx1.recv() => { assert_eq!(a.unwrap(), 1); },
-        _b = rx2.recv() => { panic!() }
-    }
-    tx3.send(1).unwrap();
-    select! {
-        a = rx1.recv() => { assert!(a.is_err()) },
-        _b = rx2.recv() => { panic!() }
-    }
-}
-
-#[test]
-fn both_ready() {
-    let (tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        for _ in 0..20 { thread::yield_now(); }
-        tx1.send(1).unwrap();
-        tx2.send(2).unwrap();
-        rx3.recv().unwrap();
-    });
-
-    select! {
-        a = rx1.recv() => { assert_eq!(a.unwrap(), 1); },
-        a = rx2.recv() => { assert_eq!(a.unwrap(), 2); }
-    }
-    select! {
-        a = rx1.recv() => { assert_eq!(a.unwrap(), 1); },
-        a = rx2.recv() => { assert_eq!(a.unwrap(), 2); }
-    }
-    assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
-    assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty));
-    tx3.send(()).unwrap();
-}
-
-#[test]
-fn stress() {
-    const AMT: i32 = 10000;
-    let (tx1, rx1) = channel::<i32>();
-    let (tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        for i in 0..AMT {
-            if i % 2 == 0 {
-                tx1.send(i).unwrap();
-            } else {
-                tx2.send(i).unwrap();
-            }
-            rx3.recv().unwrap();
-        }
-    });
-
-    for i in 0..AMT {
-        select! {
-            i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); },
-            i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); }
-        }
-        tx3.send(()).unwrap();
-    }
-}
-
-#[allow(unused_must_use)]
-#[test]
-fn cloning() {
-    let (tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        rx3.recv().unwrap();
-        tx1.clone();
-        assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty));
-        tx1.send(2).unwrap();
-        rx3.recv().unwrap();
-    });
-
-    tx3.send(()).unwrap();
-    select! {
-        _i1 = rx1.recv() => {},
-        _i2 = rx2.recv() => panic!()
-    }
-    tx3.send(()).unwrap();
-}
-
-#[allow(unused_must_use)]
-#[test]
-fn cloning2() {
-    let (tx1, rx1) = channel::<i32>();
-    let (_tx2, rx2) = channel::<i32>();
-    let (tx3, rx3) = channel::<()>();
-
-    let _t = thread::spawn(move|| {
-        rx3.recv().unwrap();
-        tx1.clone();
-        assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty));
-        tx1.send(2).unwrap();
-        rx3.recv().unwrap();
-    });
-
-    tx3.send(()).unwrap();
-    select! {
-        _i1 = rx1.recv() => {},
-        _i2 = rx2.recv() => panic!()
-    }
-    tx3.send(()).unwrap();
-}
-
-#[test]
-fn cloning3() {
-    let (tx1, rx1) = channel::<()>();
-    let (tx2, rx2) = channel::<()>();
-    let (tx3, rx3) = channel::<()>();
-    let _t = thread::spawn(move|| {
-        let s = Select::new();
-        let mut h1 = s.handle(&rx1);
-        let mut h2 = s.handle(&rx2);
-        unsafe { h2.add(); }
-        unsafe { h1.add(); }
-        assert_eq!(s.wait(), h2.id());
-        tx3.send(()).unwrap();
-    });
-
-    for _ in 0..1000 { thread::yield_now(); }
-    drop(tx1.clone());
-    tx2.send(()).unwrap();
-    rx3.recv().unwrap();
-}
-
-#[test]
-fn preflight1() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    select! {
-        _n = rx.recv() => {}
-    }
-}
-
-#[test]
-fn preflight2() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    tx.send(()).unwrap();
-    select! {
-        _n = rx.recv() => {}
-    }
-}
-
-#[test]
-fn preflight3() {
-    let (tx, rx) = channel();
-    drop(tx.clone());
-    tx.send(()).unwrap();
-    select! {
-        _n = rx.recv() => {}
-    }
-}
-
-#[test]
-fn preflight4() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight5() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    tx.send(()).unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight6() {
-    let (tx, rx) = channel();
-    drop(tx.clone());
-    tx.send(()).unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight7() {
-    let (tx, rx) = channel::<()>();
-    drop(tx);
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight8() {
-    let (tx, rx) = channel();
-    tx.send(()).unwrap();
-    drop(tx);
-    rx.recv().unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn preflight9() {
-    let (tx, rx) = channel();
-    drop(tx.clone());
-    tx.send(()).unwrap();
-    drop(tx);
-    rx.recv().unwrap();
-    let s = Select::new();
-    let mut h = s.handle(&rx);
-    unsafe { h.add(); }
-    assert_eq!(s.wait2(false), h.id());
-}
-
-#[test]
-fn oneshot_data_waiting() {
-    let (tx1, rx1) = channel();
-    let (tx2, rx2) = channel();
-    let _t = thread::spawn(move|| {
-        select! {
-            _n = rx1.recv() => {}
-        }
-        tx2.send(()).unwrap();
-    });
-
-    for _ in 0..100 { thread::yield_now() }
-    tx1.send(()).unwrap();
-    rx2.recv().unwrap();
-}
-
-#[test]
-fn stream_data_waiting() {
-    let (tx1, rx1) = channel();
-    let (tx2, rx2) = channel();
-    tx1.send(()).unwrap();
-    tx1.send(()).unwrap();
-    rx1.recv().unwrap();
-    rx1.recv().unwrap();
-    let _t = thread::spawn(move|| {
-        select! {
-            _n = rx1.recv() => {}
-        }
-        tx2.send(()).unwrap();
-    });
-
-    for _ in 0..100 { thread::yield_now() }
-    tx1.send(()).unwrap();
-    rx2.recv().unwrap();
-}
-
-#[test]
-fn shared_data_waiting() {
-    let (tx1, rx1) = channel();
-    let (tx2, rx2) = channel();
-    drop(tx1.clone());
-    tx1.send(()).unwrap();
-    rx1.recv().unwrap();
-    let _t = thread::spawn(move|| {
-        select! {
-            _n = rx1.recv() => {}
-        }
-        tx2.send(()).unwrap();
-    });
-
-    for _ in 0..100 { thread::yield_now() }
-    tx1.send(()).unwrap();
-    rx2.recv().unwrap();
-}
-
-#[test]
-fn sync1() {
-    let (tx, rx) = sync_channel::<i32>(1);
-    tx.send(1).unwrap();
-    select! {
-        n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
-    }
-}
-
-#[test]
-fn sync2() {
-    let (tx, rx) = sync_channel::<i32>(0);
-    let _t = thread::spawn(move|| {
-        for _ in 0..100 { thread::yield_now() }
-        tx.send(1).unwrap();
-    });
-    select! {
-        n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
-    }
-}
-
-#[test]
-fn sync3() {
-    let (tx1, rx1) = sync_channel::<i32>(0);
-    let (tx2, rx2): (Sender<i32>, Receiver<i32>) = channel();
-    let _t = thread::spawn(move|| { tx1.send(1).unwrap(); });
-    let _t = thread::spawn(move|| { tx2.send(2).unwrap(); });
-    select! {
-        n = rx1.recv() => {
-            let n = n.unwrap();
-            assert_eq!(n, 1);
-            assert_eq!(rx2.recv().unwrap(), 2);
-        },
-        n = rx2.recv() => {
-            let n = n.unwrap();
-            assert_eq!(n, 2);
-            assert_eq!(rx1.recv().unwrap(), 1);
-        }
-    }
-}
index cc70a62036590b4b514fdbd0639dbf93d64e6f74..dbcdcdac9326855330847013db2d442e233e5623 100644 (file)
@@ -9,6 +9,7 @@
 /// channels are quite similar, and this is no coincidence!
 
 pub use self::Failure::*;
+use self::StartResult::*;
 
 use core::cmp;
 use core::intrinsics::abort;
@@ -19,8 +20,6 @@
 use crate::sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
 use crate::sync::mpsc::blocking::{self, SignalToken};
 use crate::sync::mpsc::mpsc_queue as mpsc;
-use crate::sync::mpsc::select::StartResult::*;
-use crate::sync::mpsc::select::StartResult;
 use crate::sync::{Mutex, MutexGuard};
 use crate::thread;
 use crate::time::Instant;
@@ -57,6 +56,12 @@ pub enum Failure {
     Disconnected,
 }
 
+#[derive(PartialEq, Eq)]
+enum StartResult {
+    Installed,
+    Abort,
+}
+
 impl<T> Packet<T> {
     // Creation of a packet *must* be followed by a call to postinit_lock
     // and later by inherit_blocker
@@ -394,16 +399,6 @@ fn take_to_wake(&self) -> SignalToken {
     // select implementation
     ////////////////////////////////////////////////////////////////////////////
 
-    // Helper function for select, tests whether this port can receive without
-    // blocking (obviously not an atomic decision).
-    //
-    // This is different than the stream version because there's no need to peek
-    // at the queue, we can just look at the local count.
-    pub fn can_recv(&self) -> bool {
-        let cnt = self.cnt.load(Ordering::SeqCst);
-        cnt == DISCONNECTED || cnt - unsafe { *self.steals.get() } > 0
-    }
-
     // increment the count on the channel (used for selection)
     fn bump(&self, amt: isize) -> isize {
         match self.cnt.fetch_add(amt, Ordering::SeqCst) {
@@ -415,22 +410,6 @@ fn bump(&self, amt: isize) -> isize {
         }
     }
 
-    // Inserts the signal token for selection on this port, returning true if
-    // blocking should proceed.
-    //
-    // The code here is the same as in stream.rs, except that it doesn't need to
-    // peek at the channel to see if an upgrade is pending.
-    pub fn start_selection(&self, token: SignalToken) -> StartResult {
-        match self.decrement(token) {
-            Installed => Installed,
-            Abort => {
-                let prev = self.bump(1);
-                assert!(prev == DISCONNECTED || prev >= 0);
-                Abort
-            }
-        }
-    }
-
     // Cancels a previous thread waiting on this port, returning whether there's
     // data on the port.
     //
index 7ae6f68b514595d305bb993f1a73896f622a4f49..40877282761790cd78c989d9eb37fad0cd92c181 100644 (file)
@@ -9,7 +9,6 @@
 
 pub use self::Failure::*;
 pub use self::UpgradeResult::*;
-pub use self::SelectionResult::*;
 use self::Message::*;
 
 use core::cmp;
@@ -60,12 +59,6 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
-    SelSuccess,
-    SelCanceled,
-    SelUpgraded(SignalToken, Receiver<T>),
-}
-
 // Any message could contain an "upgrade request" to a new shared port, so the
 // internal queue it's a queue of T, but rather Message<T>
 enum Message<T> {
@@ -338,27 +331,6 @@ pub fn drop_port(&self) {
     // select implementation
     ////////////////////////////////////////////////////////////////////////////
 
-    // Tests to see whether this port can receive without blocking. If Ok is
-    // returned, then that's the answer. If Err is returned, then the returned
-    // port needs to be queried instead (an upgrade happened)
-    pub fn can_recv(&self) -> Result<bool, Receiver<T>> {
-        // We peek at the queue to see if there's anything on it, and we use
-        // this return value to determine if we should pop from the queue and
-        // upgrade this channel immediately. If it looks like we've got an
-        // upgrade pending, then go through the whole recv rigamarole to update
-        // the internal state.
-        match self.queue.peek() {
-            Some(&mut GoUp(..)) => {
-                match self.recv(None) {
-                    Err(Upgraded(port)) => Err(port),
-                    _ => unreachable!(),
-                }
-            }
-            Some(..) => Ok(true),
-            None => Ok(false)
-        }
-    }
-
     // increment the count on the channel (used for selection)
     fn bump(&self, amt: isize) -> isize {
         match self.queue.producer_addition().cnt.fetch_add(amt, Ordering::SeqCst) {
@@ -370,31 +342,6 @@ fn bump(&self, amt: isize) -> isize {
         }
     }
 
-    // Attempts to start selecting on this port. Like a oneshot, this can fail
-    // immediately because of an upgrade.
-    pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> {
-        match self.decrement(token) {
-            Ok(()) => SelSuccess,
-            Err(token) => {
-                let ret = match self.queue.peek() {
-                    Some(&mut GoUp(..)) => {
-                        match self.queue.pop() {
-                            Some(GoUp(port)) => SelUpgraded(token, port),
-                            _ => unreachable!(),
-                        }
-                    }
-                    Some(..) => SelCanceled,
-                    None => SelCanceled,
-                };
-                // Undo our decrement above, and we should be guaranteed that the
-                // previous value is positive because we're not going to sleep
-                let prev = self.bump(1);
-                assert!(prev == DISCONNECTED || prev >= 0);
-                ret
-            }
-        }
-    }
-
     // Removes a previous thread from being blocked in this port
     pub fn abort_selection(&self,
                            was_upgrade: bool) -> Result<bool, Receiver<T>> {
index b2d9f4c6491e4026c8429cd6ffa11b0d57cdb64c..3c4f8e077c922ee536340b607fc3e2c2b29179cc 100644 (file)
@@ -33,7 +33,6 @@
 
 use crate::sync::atomic::{Ordering, AtomicUsize};
 use crate::sync::mpsc::blocking::{self, WaitToken, SignalToken};
-use crate::sync::mpsc::select::StartResult::{self, Installed, Abort};
 use crate::sync::{Mutex, MutexGuard};
 use crate::time::Instant;
 
@@ -406,42 +405,6 @@ pub fn drop_port(&self) {
         while let Some(token) = queue.dequeue() { token.signal(); }
         waiter.map(|t| t.signal());
     }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // select implementation
-    ////////////////////////////////////////////////////////////////////////////
-
-    // If Ok, the value is whether this port has data, if Err, then the upgraded
-    // port needs to be checked instead of this one.
-    pub fn can_recv(&self) -> bool {
-        let guard = self.lock.lock().unwrap();
-        guard.disconnected || guard.buf.size() > 0
-    }
-
-    // Attempts to start selection on this port. This can either succeed or fail
-    // because there is data waiting.
-    pub fn start_selection(&self, token: SignalToken) -> StartResult {
-        let mut guard = self.lock.lock().unwrap();
-        if guard.disconnected || guard.buf.size() > 0 {
-            Abort
-        } else {
-            match mem::replace(&mut guard.blocker, BlockedReceiver(token)) {
-                NoneBlocked => {}
-                BlockedSender(..) => unreachable!(),
-                BlockedReceiver(..) => unreachable!(),
-            }
-            Installed
-        }
-    }
-
-    // Remove a previous selecting thread from this port. This ensures that the
-    // blocked thread will no longer be visible to any other threads.
-    //
-    // The return value indicates whether there's data on this port.
-    pub fn abort_selection(&self) -> bool {
-        let mut guard = self.lock.lock().unwrap();
-        abort_selection(&mut guard)
-    }
 }
 
 impl<T> Drop for Packet<T> {
index 11ac34fcb24f6c9097fda20e33d6e944d74a6b3c..87c2318a9377c56ff3b3922915d664cd2aeaeaa8 100644 (file)
@@ -376,6 +376,8 @@ fn drop(&mut self) {
 impl<T> From<T> for Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     /// This is equivalent to [`Mutex::new`].
+    ///
+    /// [`Mutex::new`]: ../../std/sync/struct.Mutex.html#method.new
     fn from(t: T) -> Self {
         Mutex::new(t)
     }
index 1299a74409560263edc6b5b3f7e71c8c6336b4fe..b1b56f321fc6b8fb162c68a7ba2362de91621ab3 100644 (file)
@@ -453,6 +453,8 @@ fn default() -> RwLock<T> {
 impl<T> From<T> for RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
     /// This is equivalent to [`RwLock::new`].
+    ///
+    /// [`RwLock::new`]: ../../std/sync/struct.RwLock.html#method.new
     fn from(t: T) -> Self {
         RwLock::new(t)
     }
index 77f1439e17b10324c7d67d25ab036d7755a27922..71c62461ee9cb4aef5aa6e01652c37165842f25e 100644 (file)
@@ -47,7 +47,12 @@ fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
                 let err = errno() as libc::c_int;
                 if err == libc::EINTR {
                     continue;
-                } else if err == libc::ENOSYS {
+                } else if err == libc::ENOSYS || err == libc::EPERM {
+                    // Fall back to reading /dev/urandom if `getrandom` is not
+                    // supported on the current kernel.
+                    //
+                    // Also fall back in case it is disabled by something like
+                    // seccomp or inside of virtual machines.
                     GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed);
                     return false;
                 } else if err == libc::EAGAIN {
index fce28ffd9c3880714fab7b8727459e6efd74f5cf..35de4f4008b6723a67aa2c567ee4fde6987c0067 100644 (file)
@@ -443,6 +443,7 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
     /// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
     /// [`io::Result`]: ../../std/io/type.Result.html
     /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
+    /// [`JoinHandle::join`]: ../../std/thread/struct.JoinHandle.html#method.join
     #[unstable(feature = "thread_spawn_unchecked", issue = "55132")]
     pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
         F: FnOnce() -> T, F: Send + 'a, T: Send + 'a
index d12240655e6289abf36f3ac437870eb4be5c4458..b55ca453fb3dcc8b959a26e05da40cdf67b91b13 100644 (file)
@@ -16,7 +16,7 @@
 
 use rustc_data_structures::indexed_vec::Idx;
 #[cfg(target_arch = "x86_64")]
-use rustc_data_structures::static_assert;
+use rustc_data_structures::static_assert_size;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -964,7 +964,7 @@ pub struct Expr {
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 96);
+static_assert_size!(Expr, 96);
 
 impl Expr {
     /// Whether this expression would be valid somewhere that expects a value; for example, an `if`
index 8a066f3f4a093a82c2fd96c84727d31a166520c3..5b1a9bb739ff8346ec9e889b313d0bebf67129e2 100644 (file)
@@ -998,7 +998,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated),
     (sym::path, Normal, template!(NameValueStr: "file"), Ungated),
     (sym::automatically_derived, Normal, template!(Word), Ungated),
-    (sym::no_mangle, Normal, template!(Word), Ungated),
+    (sym::no_mangle, Whitelisted, template!(Word), Ungated),
     (sym::no_link, Normal, template!(Word), Ungated),
     (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated),
     (
index 049fb6cb78b84f241bc5144ae4771b2c6b5de822..068fc41c87a0baadcff9b67938019cef4880684b 100644 (file)
@@ -19,7 +19,7 @@
 use std::fmt;
 use std::mem;
 #[cfg(target_arch = "x86_64")]
-use rustc_data_structures::static_assert;
+use rustc_data_structures::static_assert_size;
 use rustc_data_structures::sync::Lrc;
 
 #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -74,7 +74,7 @@ pub enum Lit {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_LIT: mem::size_of::<Lit>() == 8);
+static_assert_size!(Lit, 8);
 
 impl Lit {
     crate fn literal_name(&self) -> &'static str {
@@ -220,7 +220,7 @@ pub enum Token {
 
 // `Token` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Token>() == 16);
+static_assert_size!(Token, 16);
 
 impl Token {
     /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary.
index 93b5ecadd148f1f64ec62b1ba666fc2f2829d44f..3cb16c30a50d477692ea93960a1c2f67864c1b36 100644 (file)
@@ -21,7 +21,7 @@
 
 use syntax_pos::{BytePos, Mark, Span, DUMMY_SP};
 #[cfg(target_arch = "x86_64")]
-use rustc_data_structures::static_assert;
+use rustc_data_structures::static_assert_size;
 use rustc_data_structures::sync::Lrc;
 use serialize::{Decoder, Decodable, Encoder, Encodable};
 use smallvec::{SmallVec, smallvec};
@@ -158,7 +158,7 @@ pub fn close_tt(span: Span, delim: DelimToken) -> TokenTree {
 
 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 8);
+static_assert_size!(TokenStream, 8);
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum IsJoint {
index 01b126f48b327151c0e988deec216b1a8372295e..aa9028d4a6bad3758d5ed57bfa1a76defb85bdda 100644 (file)
         eh_personality,
         eh_unwind_resume,
         enable,
+        err,
         Err,
         except,
         exclusive_range_pattern,
         fundamental,
         future,
         Future,
+        gen_future,
         generators,
         generic_associated_types,
         generic_param_attrs,
         never,
         never_type,
         next,
+        __next,
         nll,
         no_builtins,
         no_core,
         Pending,
         pin,
         Pin,
+        pinned,
         platform_intrinsics,
         plugin,
         plugin_registrar,
         trivial_bounds,
         Try,
         try_blocks,
+        try_trait,
         tuple_indexing,
         ty,
         type_alias_enum_variants,
         uniform_paths,
         universal_impl_trait,
         unmarked_api,
+        unreachable_code,
         unrestricted_attribute_tokens,
         unsafe_destructor_blind_to_params,
         unsafe_no_drop_flag,
         use_nested_groups,
         usize,
         v1,
+        val,
         vis,
         visible_private_types,
         volatile,
@@ -1029,6 +1036,17 @@ pub struct LocalInternedString {
 }
 
 impl LocalInternedString {
+    /// Maps a string to its interned representation.
+    pub fn intern(string: &str) -> Self {
+        let string = with_interner(|interner| {
+            let symbol = interner.intern(string);
+            interner.strings[symbol.0.as_usize()]
+        });
+        LocalInternedString {
+            string: unsafe { std::mem::transmute::<&str, &str>(string) }
+        }
+    }
+
     pub fn as_interned_str(self) -> InternedString {
         InternedString {
             symbol: Symbol::intern(self.string)
@@ -1105,7 +1123,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl Decodable for LocalInternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
-        Ok(Symbol::intern(&d.read_str()?).as_str())
+        Ok(LocalInternedString::intern(&d.read_str()?))
     }
 }
 
@@ -1134,6 +1152,13 @@ pub struct InternedString {
 }
 
 impl InternedString {
+    /// Maps a string to its interned representation.
+    pub fn intern(string: &str) -> Self {
+        InternedString {
+            symbol: Symbol::intern(string)
+        }
+    }
+
     pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
         let str = with_interner(|interner| {
             interner.get(self.symbol) as *const str
@@ -1236,7 +1261,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl Decodable for InternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
-        Ok(Symbol::intern(&d.read_str()?).as_interned_str())
+        Ok(InternedString::intern(&d.read_str()?))
     }
 }
 
index c6afa90e4ee614d5c85d2961c8b1bff7424d955f..7f7db2a21251ac8864bcc07faf4a30001c2d6634 100644 (file)
 use term;
 
 // FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind
-//                on aarch64-pc-windows-msvc, so we don't link libtest against
-//                libunwind (for the time being), even though it means that
-//                libtest won't be fully functional on this platform.
+//                on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc
+//                so we don't link libtest against libunwind (for the time being)
+//                even though it means that libtest won't be fully functional on
+//                these platforms.
 //
 // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437
-#[cfg(not(all(windows, target_arch = "aarch64")))]
+#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))]
 extern crate panic_unwind;
 
 pub use self::ColorConfig::*;
index 70f591e653baf4ae139625a2ca253f77e221bc59..20280aa3c41300b96d90efe626d21e41f5c18bc4 100644 (file)
@@ -67,13 +67,10 @@ pub fn compile() {
             cfg.flag("-std=c99");
             cfg.flag("-std=c++11");
             cfg.flag("-nostdinc++");
-            if cfg.is_flag_supported("-funwind-tables").unwrap_or_default() &&
-               cfg.is_flag_supported("-fno-exceptions").unwrap_or_default() {
-                cfg.flag("-funwind-tables");
-                cfg.flag("-fno-exceptions");
-            }
+            cfg.flag("-fno-exceptions");
             cfg.flag("-fno-rtti");
             cfg.flag("-fstrict-aliasing");
+            cfg.flag("-funwind-tables");
         }
 
         let mut unwind_sources = vec![
index eb38a1888d1d29b2d2c6b31428a5201cd8fba0ff..2c5656ae593851d0b2336a727cc14b77a06b8ac0 160000 (submodule)
@@ -1 +1 @@
-Subproject commit eb38a1888d1d29b2d2c6b31428a5201cd8fba0ff
+Subproject commit 2c5656ae593851d0b2336a727cc14b77a06b8ac0
index 0dd67bb95ccaa5d500d2ef6157eedbfc933985d9..5004f787cde190725b2b5d3b69a117a319fcb0a6 100644 (file)
@@ -1,6 +1,5 @@
 // compile-flags: -O
 #![crate_type="lib"]
-#![feature(maybe_uninit)]
 
 use std::mem::MaybeUninit;
 
index 52543297ead647f1f6874204e3e0ec70b3b66b9f..73631b92c1f33463271646907d46abd71540a40b 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-netbsd
 // ignore-openbsd
 // ignore-solaris
+// ignore-sgx no dynamic linking
 
 // aux-build:dummy.rs
 // aux-build:wrapper.rs
index f2fd297dc70f77d37e24d61217575f35f9980b39..8e38245267d41381ae9bc6a3cb179dd79dbbf1f5 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-netbsd
 // ignore-openbsd
 // ignore-solaris
+// ignore-sgx
 
 // compile-flags: -C no-prepopulate-passes -C panic=abort -O
 
index 0581cd799753ef3cb9561264ed040d59b098a0c0..498bf89225000a60a5a31fd2bd579a3a654150f7 100644 (file)
@@ -1,5 +1,6 @@
 // Test what happens we save incremental compilation state that makes
 // use of foreign items. This used to ICE (#34991).
+// ignore-sgx no libc
 
 // revisions: rpass1
 
diff --git a/src/test/incremental/no_mangle.rs b/src/test/incremental/no_mangle.rs
new file mode 100644 (file)
index 0000000..1b17886
--- /dev/null
@@ -0,0 +1,10 @@
+// revisions:rpass1 rpass2
+// compile-flags: --crate-type cdylib
+// skip-codegen
+
+#![deny(unused_attributes)]
+
+#[no_mangle]
+pub extern "C" fn rust_no_mangle() -> i32 {
+    42
+}
index 4b97af68ff08af727a4f923e58c95e9ed4e4bedf..dd22eb5d604ea51b84d8586ebfc26c6e16bcb038 100644 (file)
@@ -23,7 +23,7 @@ fn main() {
 //  bb0: {
 //      ...
 //      _5 = const true;
-//      assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
+//      assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1;
 //  }
 //  bb1: {
 //      _1 = _2[_3];
index 0718316307c5edbb5dda0f88983a9c33196079d8..fe98cf24eec009ecc6416033e5b7a38e787a6dae 100644 (file)
@@ -16,6 +16,6 @@ fn main() {
 //  bb0: {
 //      ...
 //      _2 = (const 2u32, const false);
-//      assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1;
+//      assert(!const false, "attempt to add with overflow") -> bb1;
 //  }
 // END rustc.main.ConstProp.after.mir
diff --git a/src/test/mir-opt/const_prop/switch_int.rs b/src/test/mir-opt/const_prop/switch_int.rs
new file mode 100644 (file)
index 0000000..0df1112
--- /dev/null
@@ -0,0 +1,38 @@
+#[inline(never)]
+fn foo(_: i32) { }
+
+fn main() {
+    match 1 {
+        1 => foo(0),
+        _ => foo(-1),
+    }
+}
+
+// END RUST SOURCE
+// START rustc.main.ConstProp.before.mir
+//  bb0: {
+//      ...
+//      _1 = const 1i32;
+//      switchInt(_1) -> [1i32: bb1, otherwise: bb2];
+//  }
+// END rustc.main.ConstProp.before.mir
+// START rustc.main.ConstProp.after.mir
+//  bb0: {
+//      ...
+//      switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2];
+//  }
+// END rustc.main.ConstProp.after.mir
+// START rustc.main.SimplifyBranches-after-const-prop.before.mir
+//  bb0: {
+//      ...
+//      _1 = const 1i32;
+//      switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2];
+//  }
+// END rustc.main.SimplifyBranches-after-const-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.after.mir
+//  bb0: {
+//      ...
+//      _1 = const 1i32;
+//      goto -> bb1;
+//  }
+// END rustc.main.SimplifyBranches-after-const-prop.after.mir
index b2a99a6d446bbfe113c245ef2c0a33462371e38e..35512b94c0c8cf8f96c87db6ab2350ae51118525 100644 (file)
@@ -5,15 +5,15 @@ fn main() {
 }
 
 // END RUST SOURCE
-// START rustc.main.SimplifyBranches-after-copy-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.before.mir
 // bb0: {
 //     ...
 //     switchInt(const false) -> [false: bb3, otherwise: bb1];
 // }
-// END rustc.main.SimplifyBranches-after-copy-prop.before.mir
-// START rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// END rustc.main.SimplifyBranches-after-const-prop.before.mir
+// START rustc.main.SimplifyBranches-after-const-prop.after.mir
 // bb0: {
 //     ...
 //     goto -> bb3;
 // }
-// END rustc.main.SimplifyBranches-after-copy-prop.after.mir
+// END rustc.main.SimplifyBranches-after-const-prop.after.mir
index c4d23c2938d6368a9d1ea9419f382208bdbf71e4..cd5edb84bdfe451787a472e9835c8dd23694d2b0 100644 (file)
@@ -1,6 +1,7 @@
 // no-prefer-dynamic
 // ignore-cloudabi
 // ignore-emscripten
+// ignore-sgx no processes
 // ignore-macos this needs valgrind 3.11 or higher; see
 // https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679
 
index df94cd5718631e4600a3937a80113689105b392d..110f3eee1ef81cd34fa26571a0f5db55923ba795 100644 (file)
@@ -4,6 +4,7 @@
 
 // ignore-cloudabi no env and process
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::{env, panic};
 use std::io::prelude::*;
index 566aeeb2c395df576884b68c87fd28935b6a693c..ee76ef9b25fb8b82c00c0b8d757504ce9c087f36 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(deprecated)]
 // ignore-cloudabi no process support
 // ignore-emscripten no threads support
+// ignore-sgx no processes
 
 use std::{env, fmt, process, sync, thread};
 
index 279a30d6c2eebcb7645f8820129016de73ef346b..69ce1f70322ab55079fca1834d7e9702cad963c4 100644 (file)
@@ -11,6 +11,7 @@
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // normalize-stderr-test ".*\n" -> ""
+// ignore-sgx no processes
 
 // Note that above `-opt-bisect-limit=0` is used to basically disable
 // optimizations. It creates tons of output on stderr, hence we normalize
index da3871aba095c4f6ba35c98730fe6be44a8a638b..5f6198aff5009ab7f754ece044136c3518d69b64 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
 // ignore-openbsd no support for libbacktrace without filename
+// ignore-sgx no processes
 // compile-flags:-g
 
 use std::env;
index f376bb7fde2e511ebbac0dddfe4f198e3e337d66..ec162b40bf8b6790ddb2b2bfd10657b05790b4d1 100644 (file)
@@ -1,4 +1,5 @@
 // ignore-wasm32-bare no libc to test with
+// ignore-sgx no libc
 
 #![feature(rustc_private)]
 
index 282ac4abcee98c088571e652a77cd6f2034605d2..9fb7c7669219d2007fa7aa8a3770b52b7d401f2f 100644 (file)
@@ -2,6 +2,7 @@
 // pretty-expanded FIXME #23616
 // ignore-cloudabi no target_family
 // ignore-wasm32-bare no target_family
+// ignore-sgx
 
 #[cfg(windows)]
 pub fn main() {
index 2cd0ba5bf881c38e7fa1bd3d653ce79567922a03..ecf802f7281482d1a7381d97a809d667b42311f2 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no target_family
 // ignore-wasm32-bare no target_family
+// ignore-sgx
 
 // pretty-expanded FIXME #23616
 
index ab3d3ebbaad13b57d7e431fc021e97e75ef1a293..aa5a3a377058de1e8deb541e5bb8e74fe1e1a4f2 100644 (file)
@@ -3,6 +3,7 @@
 // ignore-pretty issue #37199
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 #![feature(process_exec)]
 
index 21783fedd39c9ada818cfe30db07fdc311919bfd..5c3cc31de58188d276db6a981fe25d1a602296e2 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-windows - this is a unix-specific test
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 #![feature(process_exec, rustc_private)]
 
 extern crate libc;
index 55d389952cc4089459bf3cf558ea4b083b6226eb..625e51793814e6e7b90f8dcd272ee67202bd37f0 100644 (file)
@@ -5,6 +5,7 @@
 // compile-flags:--test
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 // N.B., these tests kill child processes. Valgrind sees these children as leaking
 // memory, which makes for some *confusing* logs. That's why these are here
index 8dcc8ad5433e0b2621d76100ecaeef8f0e96e11f..7d1624320e6798a6223445e588dc181ced68097a 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::alloc::{Layout, handle_alloc_error};
 use std::env;
index 78548fd9bc57096be4eafadf271965f1fc418f47..d677aa850010376cc9e8c1f057e8cbce3ce44461 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env::args;
 use std::process::Command;
index 79f32bd6c29e3138cb4c3d29cc88a6e6634d98e0..3b236e2b3afbdfa2f2b8456a7221857d931a95b8 100644 (file)
@@ -4,6 +4,7 @@
 // ignore-windows
 // ignore-cloudabi no execve
 // ignore-emscripten no execve
+// ignore-sgx no execve
 // no-prefer-dynamic
 
 #![feature(rustc_private)]
index 90b753447308fcb395b9affed3f5205a196d7764..62f45d0a2eb2a364e296e0f6f3bdc9b070463dfe 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(deprecated)]
 // ignore-cloudabi no environment variables present
 // ignore-emscripten env vars don't work?
+// ignore-sgx env vars cannot be modified
 
 use std::env::*;
 use std::path::PathBuf;
index 1327b558fc967d68569a3dddf9b1aa111ca6a6ea..c1b8e0825143bdb0845979e79b7bc80a5f80b8ac 100644 (file)
@@ -1,6 +1,7 @@
 // exec-env:TEST_EXEC_ENV=22
 // ignore-cloudabi no env vars
 // ignore-emscripten FIXME: issue #31622
+// ignore-sgx unsupported
 
 use std::env;
 
index 3bc0ceb5cf2fa76e2c5773e6a05da25047b182a0..c4091f84af98c6f53896976ef2b2b30ac928f7b8 100644 (file)
@@ -3,6 +3,7 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-haiku
+// ignore-sgx no processes
 
 #![feature(rustc_private)]
 
index 5ed8d19bc5a42e43cbdb4f7c401fb1a4b97807f1..1f048159064b39da80bfcb8488c84eaf0a4dbc7d 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 // ignore-wasm32-bare no libc to test ffi with
+// ignore-sgx no libc
 
 #![feature(rustc_private)]
 
index 8e2401d0c035620e1623429b6b51eac5c3ee561d..229953f1b18d4741f91fe845237b9136ec81587e 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-emscripten
 // ignore-wasm32
+// ignore-sgx no processes
 
 use std::env;
 use std::process::Command;
index ac9fb94c37507c6f82a9b181eba6276e1232fda2..6a67d04a54cf4e1af19395afbd50e97bb5878527 100644 (file)
@@ -40,6 +40,18 @@ pub fn main() {
     }
 }
 
+#[cfg(target_env = "sgx")]
+mod m {
+    #[main]
+    #[cfg(target_arch = "x86_64")]
+    pub fn main() {
+        unsafe {
+            assert_eq!(::rusti::pref_align_of::<u64>(), 8);
+            assert_eq!(::rusti::min_align_of::<u64>(), 8);
+        }
+    }
+}
+
 #[cfg(target_os = "windows")]
 mod m {
     #[main]
index 2775aac015615ed0b7fa7c4744c9a6fd1865a6ae..ddf4dc42424dbe089892bd8a892b5d761edd2251 100644 (file)
@@ -1,6 +1,7 @@
 #![allow(unused_mut)]
 // ignore-wasm32
 // ignore-emscripten
+// ignore-sgx no processes
 
 // compile-flags: -C debug_assertions=yes
 
index a2b11764a2fc64cfd46297caa3ab313676789d93..e7544934da0c83e8c4e228f7a952b2a7d9c11b1d 100644 (file)
@@ -1,6 +1,7 @@
 // edition:2018
 // run-pass
 // ignore-emscripten no threads support
+// ignore-sgx no thread sleep support
 
 use std::thread;
 use std::time::Duration;
index 9c10fd2cea682c56ea8d2073dabea9bd2d670daf..78fa8b7c6fb0722e18b895fbc7b606e53cc70d95 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 // Make sure that if a process doesn't have its stdio/stderr descriptors set up
 // that we don't die in a large ball of fire
index c87a37ab6b787f8474ef185a8f394fb31b02131d..c8aa9bf46491faedd1c221f33124f7dae2e43182 100644 (file)
@@ -5,6 +5,7 @@
 // ignore-cloudabi no dylib support
 // ignore-emscripten no dylib support
 // ignore-musl
+// ignore-sgx no dylib support
 
 // pretty-expanded FIXME #23616
 
index b23853074fa3262ca8c6c2bb20f55e647734ae7b..e26c2d7cde23449043f8fdea2d20bf58b6493873 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 // ignore-wasm32-bare can't block the thread
+// ignore-sgx not supported
 #![allow(deprecated)]
 
 use std::thread;
index cd74ce38dea6fdef1d5d9a18a7703e23716bc246..5698536ab5d050496835772c4cc93bd6ca33fad3 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(unused_mut)]
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::io::prelude::*;
diff --git a/src/test/run-pass/issues/issue-13494.rs b/src/test/run-pass/issues/issue-13494.rs
deleted file mode 100644 (file)
index 12be977..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// run-pass
-#![allow(unused_must_use)]
-// ignore-emscripten no threads support
-
-// This test may not always fail, but it can be flaky if the race it used to
-// expose is still present.
-
-#![feature(mpsc_select)]
-#![allow(deprecated)]
-
-use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread;
-
-fn helper(rx: Receiver<Sender<()>>) {
-    for tx in rx.iter() {
-        let _ = tx.send(());
-    }
-}
-
-fn main() {
-    let (tx, rx) = channel();
-    let t = thread::spawn(move|| { helper(rx) });
-    let (snd, rcv) = channel::<isize>();
-    for _ in 1..100000 {
-        snd.send(1).unwrap();
-        let (tx2, rx2) = channel();
-        tx.send(tx2).unwrap();
-        select! {
-            _ = rx2.recv() => (),
-            _ = rcv.recv() => ()
-        }
-    }
-    drop(tx);
-    t.join();
-}
index 23347d35178e020f4a2b02f9c449c6460bc47e24..164d7ef8af27d5bdb1f1aaac6ce33ce1252a107d 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(unused_mut)]
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::io::prelude::*;
index ce47a623f0011078b05818b021057fd5422182af..785ad6a2c49dae59818c0428150a947bdb295d5d 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::process::Command;
index a2570e763f6da496c9552753a9570316bc13d76a..3ba2483f4306d7d146dc8ebbbd369f854afec9de 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::process::Command;
 use std::env;
index 6e538f711de7c0ccc139007b42357c3b9dbadb86..22f33545cb90958df6ced511feb57a0c3d3c3e3f 100644 (file)
@@ -1,6 +1,6 @@
 // run-pass
 // ignore-wasm32-bare no libc to test ffi with
-
+// ignore-sgx no libc
 #![feature(rustc_private)]
 
 extern crate libc;
index ddcf1d04511064eefbedc1ce2a9fadac8f2f26af..2c420dc056fdad4176eacfcbeef1899b7c8f59f8 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no threads
+// ignore-sgx no processes
 
 use std::thread;
 use std::env;
index 231d41cd86a97d88783eff0bd196dbe1588ac7e3..76e72246887b6941c6bb183969e39f4d65a241f1 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 // Previously libstd would set stdio descriptors of a child process
 // by `dup`ing the requested descriptors to inherit directly into the
index 7962509003f50d21c9d27e8a5f99c66cbcc7a816..39ae009c99650f3e1c4e0437057f851cff592ed7 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::process::{Command, Stdio};
 use std::env;
index 3e7e9a51cdd3ad044d8bee4281abad20283c0345..27b5185377d97be2ef4fd6190189376504a12879 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(unused_must_use)]
 #![allow(deprecated)]
 // ignore-emscripten no threads support
+// ignore-sgx no thread sleep support
 
 use std::sync::mpsc::{TryRecvError, channel};
 use std::thread;
index 4e404f26eec5e1ca99e9790520d2081c93fc34fc..da07385ead748644e65515569922119b012950c5 100644 (file)
@@ -1,6 +1,7 @@
 // ignore-windows
 // ignore-macos
 // ignore-emscripten doesn't support this linkage
+// ignore-sgx weak linkage not permitted
 // aux-build:linkage1.rs
 
 #![feature(linkage)]
index 904f2e2c7fd7eff21de27eb8080a4fc4455d7931..12a612c153ad62f085884b66c058e350a9dbeeb0 100644 (file)
@@ -233,8 +233,6 @@ fn println() {
     println!("hello {}", "world",);
 }
 
-// select! is too troublesome and unlikely to be stabilized
-
 // stringify! is N/A
 
 #[cfg(std)]
index cd30dd62bc4ce767ba40dab56f90f7b20ee569e3..cf8d92b227893dbd091074c17a98e2653d5b2aa0 100644 (file)
@@ -1,5 +1,6 @@
 // compile-flags:--test
 // ignore-emscripten
+// ignore-sgx no thread sleep support
 
 use std::sync::mpsc::channel;
 use std::sync::mpsc::TryRecvError;
index 3f24d989c8c3f6585a41d9693ce4a5f92d5e5e81..900b2b2206f480772620c5fe2c2d321b2b506061 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 fn check_for_no_backtrace(test: std::process::Output) {
     assert!(!test.status.success());
index 005781e1d2f0f67eafc75f1b1d6388247c29d03c..aae1d0b7f81c7a9d65c15cfac142fac3e805f3e7 100644 (file)
@@ -1,6 +1,7 @@
 // ignore-android
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 #![feature(rustc_private)]
 
index 9f868d6e5c3e412422c8034416685f2a61a14fc5..f03935e3d27cc73431cb93acfb16a5177599ec19 100644 (file)
@@ -4,6 +4,7 @@
 // ignore-musl
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 #![feature(asm)]
 #![feature(rustc_private)]
index e2dbb0d175d01127cd45c363f2bd1797ec532a7e..9c099911eab4d39e578eddf4ba65f02cd1daee48 100644 (file)
@@ -5,6 +5,7 @@
 // no-prefer-dynamic
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 // ignore-macos
 
 extern crate exit_success_if_unwind;
index 719034bd11e78a0d0218587dbd024db31df2cc0e..f625fe35d7205367eb7dfe749ba31c97aa54ecc5 100644 (file)
@@ -4,6 +4,7 @@
 // no-prefer-dynamic
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 // ignore-macos
 
 use std::process::Command;
index 9015a8f25a9b6ac970190dc7a33222a3205fcb16..8fff71a629a49e00ff4afcf83d63c6ff5ff22518 100644 (file)
@@ -4,6 +4,7 @@
 // no-prefer-dynamic
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::process::Command;
 use std::env;
index b14cdfc193fa86524846801f9b082977d99cf2a2..94a0b596e4a7114da6e971c7cfdace2b857ad092 100644 (file)
@@ -5,6 +5,7 @@
 // no-prefer-dynamic
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::process::Command;
 use std::env;
index 3f6e489bb83275f6f7b7bbee03806579e91ea459..4ca4b407bd4ff2b70ca60e3aed042874bc8efcec 100644 (file)
@@ -2,7 +2,7 @@
 // This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results
 // in a runtime panic.
 
-#![feature(never_type, maybe_uninit)]
+#![feature(never_type)]
 
 use std::{mem, panic};
 
index dfcef59aa57825851f827159fb833cf12dfdfbb3..64ee7319fdde5aa8dc9267c3f9c68e34eb3aa5f4 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-cloudabi no files or I/O
 // ignore-wasm32-bare no files or I/O
 // ignore-emscripten no files
+// ignore-sgx no files
 
 use std::fs;
 use std::io;
index 9c47a734d7b84c9ea050387e254c99b8b64baf3f..65130a1a9f2c095714065eb21451e0daa528e0eb 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
+// ignore-sgx no processes
 
 use std::{env, process};
 
index 1ff0fbbdd08df68da13c68c320fe45247e33089c..a7779c55f1f9256a12c70bd42ec6d35560393813 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::process::Command;
 use std::env;
index ecc7b72c0f3ee850a55976e54bf11b1a71bbce67..da3b4ca85c2a3076c8d16b54376ca58380b63608 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(unused_imports)]
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::process::{self, Command, Stdio};
index 9c2aa871e0dc5aad5989a746cbd4635a79ee09d1..32cbb6ac85ac86d73ffb0e19726c2f761b2c4742 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::process::Command;
 use std::env;
index 2fe9f33de38b7341e9b205d42e6438fe7f583e1b..182cf1748fec68e1d28fca99c4b652c13bb50c85 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::io::ErrorKind;
 use std::process::Command;
index e3508cb4e8fc9a542ae7f0d444a25047a65c0782..edd3cb26ec362919f6a46752d35ae51df5463d44 100644 (file)
@@ -9,6 +9,7 @@
 
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::io::prelude::*;
 use std::io;
index e2e17b7fb66c177a0b7bf82e695b22bfb2d5275f..f9b2da7e401eea35abcc32a60c357d331f4a8773 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::io;
index 3b7b96d0d02070883a1a4128e313c1b5e77e821c..41a036958bfeab27fbda9acb11d285694a098e9f 100644 (file)
@@ -2,6 +2,7 @@
 #![allow(dead_code)]
 // ignore-cloudabi stdout does not map to file descriptor 1 by default
 // ignore-wasm32-bare no libc
+// ignore-sgx no libc
 
 #![feature(rustc_private)]
 
index 7f8a0f01dde04396a4ba622e977af1e6d8ad65dd..ab1bf3a5b91d6574b8933ee0a8ca8d4e8bc9a25a 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi spawning processes is not supported
 // ignore-emscripten spawning processes is not supported
+// ignore-sgx no processes
 
 #![feature(start)]
 
index ce485d771f01dda936a903ee169b0824e741798b..e90efface687bc6dcf57016e66737ec92bf48b79 100644 (file)
@@ -1,6 +1,7 @@
 #![allow(unused_imports)]
 // ignore-cloudabi can't run commands
 // ignore-emscripten can't run commands
+// ignore-sgx no processes
 
 #![feature(rustc_private)]
 
index d11f3f5b5e66c69c25ead9cb9f0b00b3da698f25..6f2fa2a370dfeef78849f9700264edbbd30056d7 100644 (file)
@@ -5,6 +5,7 @@
 // ignore-cloudabi no signal handling support
 // ignore-wasm32-bare no libc
 // ignore-windows
+// ignore-sgx no libc
 
 #![feature(rustc_private)]
 extern crate libc;
index 9e1e55ad54d8a289dd1e91bf64b98aedf9e3bfdb..c22c0352286dc964a2a2a568fcfe61280b178b53 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 // ignore-windows
 
 use std::env;
index 2ded71670d29a4f0c862e747b230f1e0c1046ef5..6c5bbd45a3c35e512c21998d132cfb5fb1802489 100644 (file)
@@ -4,6 +4,7 @@
 
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::io::prelude::*;
index 5842a7fcdf7e34bdec77b925382ef7c47403c763..6d7688191b7f1047edbf5a93f190ee2a8ad17666 100644 (file)
@@ -4,6 +4,7 @@
 #![allow(overflowing_literals)]
 
 // ignore-emscripten
+// ignore-sgx no processes
 
 #![feature(repr_simd, target_feature, cfg_target_feature)]
 #![feature(avx512_target_feature)]
index f0411876c8a0ac35bb4f5bbddba0ebb47acee603..7128b3cc7c3ad02617d619536cd810a694efee5a 100644 (file)
@@ -1,4 +1,5 @@
 // ignore-emscripten no threads support
+// ignore-sgx no thread sleep support
 
 use std::thread::{self, sleep};
 use std::time::Duration;
index 2705950b014243cdf0336e8376039a82cf344548..1274f032a3e298fdaac584eecdd6c1dbc7a83d09 100644 (file)
@@ -9,6 +9,7 @@
 // ignore-wasm
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 // ignore-musl FIXME #31506
 // ignore-pretty
 // compile-flags: -C lto
index ff264421cfbcf9aa656ad6f0543ac28681da6e2e..92a0cc3a07b5211d629e9d23f5ed435f0e126a97 100644 (file)
@@ -9,6 +9,7 @@
 // ignore-wasm
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 // ignore-musl FIXME #31506
 
 use std::mem;
index 281c6a17aa997ceb1df44fddee45f6c2016f487f..1824162b8bac65c95774025655190314251b584d 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 use std::env;
 use std::io::prelude::*;
index 07e60114018929b6694724f30891b994c7ec7b77..c4e9e9ea5ee1ab26118b791834086a427cec8dea 100644 (file)
@@ -55,6 +55,15 @@ pub fn size() -> usize { 16 }
     }
 }
 
+#[cfg(target_env = "sgx")]
+mod m {
+    #[cfg(target_arch = "x86_64")]
+    pub mod m {
+        pub fn align() -> usize { 8 }
+        pub fn size() -> usize { 16 }
+    }
+}
+
 #[cfg(target_os = "windows")]
 mod m {
     #[cfg(target_arch = "x86")]
index d4476ab0a310f02862b45737c7b5fe77b7d73420..391cbbdd42daff667066eca48bcfe11311264cd7 100644 (file)
@@ -3,6 +3,7 @@
 // ignore-emscripten no threads or sockets support
 // ignore-netbsd system ulimit (Too many open files)
 // ignore-openbsd system ulimit (Too many open files)
+// ignore-sgx no thread sleep support
 
 use std::io::prelude::*;
 use std::net::{TcpListener, TcpStream};
index 981ac1663560248d2359a9a57f9eb090caa99535..15e10dc250f19b87ac710c86aa023e19481ca9bb 100644 (file)
@@ -2,6 +2,7 @@
 
 // ignore-cloudabi networking not available
 // ignore-wasm32-bare networking not available
+// ignore-sgx ToSocketAddrs cannot be used for DNS Resolution
 
 use std::net::ToSocketAddrs;
 
index 05871ba7d4c606bf5c3532922d2b118014b369ef..97caddde41214756ea60c807dff1418f8aa721c3 100644 (file)
@@ -1,6 +1,7 @@
 #![allow(stable_features)]
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 #![feature(process_try_wait)]
 
diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs
new file mode 100644 (file)
index 0000000..bd84b46
--- /dev/null
@@ -0,0 +1,51 @@
+// run-pass
+#![allow(dead_code)]
+
+// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations.
+//
+// For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no
+// bit-value that an `Option<U>` could reuse as `None`; this test makes sure that isn't done.
+//
+// Secondly, this tests the status quo (not a guarantee; subject to change!) to not apply such
+// optimizations to types containing unions even if they're theoretically possible. (discussion:
+// https://github.com/rust-lang/rust/issues/36394)
+//
+// Notably this nails down part of the behavior that `MaybeUninit` assumes: that a
+// `Option<MaybeUninit<&u8>>` does not take advantage of non-zero optimization, and thus is a safe
+// construct.
+
+use std::mem::{size_of, transmute};
+
+union U1<A: Copy> {
+    a: A,
+}
+
+union U2<A: Copy, B: Copy> {
+    a: A,
+    b: B,
+}
+
+// Option<E> uses a value other than 0 and 1 as None
+#[derive(Clone,Copy)]
+enum E {
+    A = 0,
+    B = 1,
+}
+
+fn main() {
+    // Unions do not participate in niche-filling/non-zero optimization...
+    assert!(size_of::<Option<U2<&u8, u8>>>() > size_of::<U2<&u8, u8>>());
+    assert!(size_of::<Option<U2<&u8, ()>>>() > size_of::<U2<&u8, ()>>());
+    assert!(size_of::<Option<U2<u8, E>>>() > size_of::<U2<u8, E>>());
+
+    // ...even when theoretically possible:
+    assert!(size_of::<Option<U1<&u8>>>() > size_of::<U1<&u8>>());
+    assert!(size_of::<Option<U2<&u8, &u8>>>() > size_of::<U2<&u8, &u8>>());
+
+    // The unused bits of the () variant can have any value.
+    let zeroed: U2<&u8, ()> = unsafe { transmute(std::ptr::null::<u8>()) };
+
+    if let None = Some(zeroed) {
+        panic!()
+    }
+}
index e9869866a9bfcae54614f040270396c9c6f24dd4..1f32bd00a037ce991199cc5e396429eb90b0c3f4 100644 (file)
@@ -1,5 +1,6 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 #![feature(rustc_private)]
 
index 1b6ffc4c2bfdac4fc16bb37596f5a0a3661d2647..cd9450a5697c6a8af03cd85354cfc56efad75507 100644 (file)
@@ -1,5 +1,5 @@
 // ignore-wasm32-bare no libc to test ffi with
-
+// ignore-sgx no libc
 // GetLastError doesn't seem to work with stack switching
 
 #[cfg(windows)]
index aa3f539ba32a314c3961181b4e54fabbbf807e67..4b2a91e9c812722f4a6f66beb1692e8ea56037a6 100644 (file)
@@ -1,6 +1,4 @@
-//~ ERROR Missing code example in this documentation
-
-#![deny(missing_doc_code_examples)]
+#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation
 
 /// Some docs.
 //~^ ERROR Missing code example in this documentation
index 208bdedf24ddb6b10aebd044bdfc6b5118fb770e..23c07c4d32d64359d43a4a4ead40dbac4ba40050 100644 (file)
@@ -1,25 +1,35 @@
 error: Missing code example in this documentation
+  --> $DIR/doc-without-codeblock.rs:1:1
+   |
+LL | / #![deny(missing_doc_code_examples)]
+LL | |
+LL | | /// Some docs.
+LL | |
+...  |
+LL | |     pub fn bar() {}
+LL | | }
+   | |_^
    |
 note: lint level defined here
-  --> $DIR/doc-without-codeblock.rs:3:9
+  --> $DIR/doc-without-codeblock.rs:1:9
    |
 LL | #![deny(missing_doc_code_examples)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:5:1
+  --> $DIR/doc-without-codeblock.rs:3:1
    |
 LL | /// Some docs.
    | ^^^^^^^^^^^^^^
 
 error: Missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:9:1
+  --> $DIR/doc-without-codeblock.rs:7:1
    |
 LL | /// And then, the princess died.
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: Missing code example in this documentation
-  --> $DIR/doc-without-codeblock.rs:12:5
+  --> $DIR/doc-without-codeblock.rs:10:5
    |
 LL |     /// Or maybe not because she saved herself!
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
new file mode 100644 (file)
index 0000000..ffe0ddc
--- /dev/null
@@ -0,0 +1,40 @@
+#![deny(missing_docs)]
+#![deny(missing_doc_code_examples)]
+
+//! crate level doc
+//! ```
+//! println!("hello"):
+//! ```
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+fn test() {
+}
+
+#[allow(missing_docs)]
+mod module1 { //~ ERROR
+}
+
+#[allow(missing_doc_code_examples)]
+/// doc
+mod module2 {
+
+  /// doc
+  pub fn test() {}
+}
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+pub mod module3 {
+
+  /// doc
+  //~^ ERROR
+  pub fn test() {}
+}
diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr
new file mode 100644 (file)
index 0000000..97a52a1
--- /dev/null
@@ -0,0 +1,21 @@
+error: Missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:19:1
+   |
+LL | / mod module1 {
+LL | | }
+   | |_^
+   |
+note: lint level defined here
+  --> $DIR/lint-missing-doc-code-example.rs:2:9
+   |
+LL | #![deny(missing_doc_code_examples)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Missing code example in this documentation
+  --> $DIR/lint-missing-doc-code-example.rs:37:3
+   |
+LL |   /// doc
+   |   ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/rustdoc/async-move-doctest.rs b/src/test/rustdoc/async-move-doctest.rs
new file mode 100644 (file)
index 0000000..4272313
--- /dev/null
@@ -0,0 +1,14 @@
+// compile-flags:--test
+// edition:2018
+
+// prior to setting the default edition for the doctest pre-parser, this doctest would fail due to
+// a fatal parsing error
+// see https://github.com/rust-lang/rust/issues/59313
+
+//! ```
+//! #![feature(async_await)]
+//!
+//! fn foo() {
+//!     drop(async move {});
+//! }
+//! ```
index eb0e3f065c7b3b50a4066fb4ed0b3cf7689e0039..6ecdad3ec0000aa04592ec1b0354e132198d5113 100644 (file)
@@ -8,8 +8,8 @@ pub extern "C" fn f() {}
 #[export_name = "bar"]
 pub extern "C" fn g() {}
 
-// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[repr(i64)]'
-// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[must_use]'
+// @has foo/enum.Foo.html '//*[@class="docblock attributes top-attr"]' '#[repr(i64)]'
+// @has foo/enum.Foo.html '//*[@class="docblock attributes top-attr"]' '#[must_use]'
 #[repr(i64)]
 #[must_use]
 pub enum Foo {
diff --git a/src/test/rustdoc/generic-const.rs b/src/test/rustdoc/generic-const.rs
new file mode 100644 (file)
index 0000000..d6794ac
--- /dev/null
@@ -0,0 +1,30 @@
+#![feature(const_generics)]
+#![crate_name = "foo"]
+
+// ignore-tidy-linelength
+
+pub enum Order {
+    Sorted,
+    Unsorted,
+}
+
+// @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
+// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<const ORDER: Order, T> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<const ORDER: Order, T> Sync for VSet<T, ORDER>'
+pub struct VSet<T, const ORDER: Order> {
+    inner: Vec<T>,
+}
+
+// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, { Order::Sorted }>'
+impl <T> VSet<T, {Order::Sorted}> {
+    pub fn new() -> Self {
+        Self { inner: Vec::new() }
+    }
+}
+
+// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, { Order::Unsorted }>'
+impl <T> VSet<T, {Order::Unsorted}> {
+    pub fn new() -> Self {
+        Self { inner: Vec::new() }
+    }
+}
diff --git a/src/test/rustdoc/intra-link-libstd-re-export.rs b/src/test/rustdoc/intra-link-libstd-re-export.rs
new file mode 100644 (file)
index 0000000..6f23929
--- /dev/null
@@ -0,0 +1,3 @@
+#![deny(intra_doc_link_resolution_failure)]
+
+pub use std::*;
index fb1be7397e65d659875e7231a18fc77e3d81c5bb..018716ad45af344f5fafd908b9b6cbe97004379d 100644 (file)
@@ -11,4 +11,4 @@
 pub fn dummy() {}
 
 // ensure that `extern crate foo;` was inserted into code snips automatically:
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D&edition=2015"]' "Run"
index 1b76e6c885349c6bec037c1912f8ac89455f90f6..9971c7b4297a25d9162d580f6bb0097a279a028e 100644 (file)
@@ -24,6 +24,6 @@
 //! }
 //! ```
 
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run"
-// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&version=nightly"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run"
+// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&version=nightly&edition=2015"]' "Run"
index 241cc96fec04f1b6607a6627e07be1549b3be0bf..8530c9e24b2006398b535dc301c5c352a4b87ca0 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-musl
 // ignore-cloudabi
 // ignore-emscripten
-
+// ignore-sgx no dynamic libraries
 #![crate_type = "cdylib"]
 
 extern crate cdylib_dep;
diff --git a/src/test/ui/consts/std/alloc.rs b/src/test/ui/consts/std/alloc.rs
new file mode 100644 (file)
index 0000000..65ac7e4
--- /dev/null
@@ -0,0 +1,10 @@
+use std::alloc::Layout;
+
+// ok
+const LAYOUT_VALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x08) };
+
+// not ok, since alignment needs to be non-zero.
+const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
+//~^ ERROR it is undefined behavior to use this value
+
+fn main() {}
diff --git a/src/test/ui/consts/std/alloc.stderr b/src/test/ui/consts/std/alloc.stderr
new file mode 100644 (file)
index 0000000..74a8f3d
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/alloc.rs:7:1
+   |
+LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
index 0129a3f72b2422d0b7c59ef6fd6ebc1b7c778f0d..ca0a432d3396e1a446f26c91c5018a5b000d115c 100644 (file)
@@ -52,7 +52,7 @@
 //~^ WARN unused attribute
 #![path = "3800"] //~ WARN unused attribute
 #![automatically_derived] //~ WARN unused attribute
-#![no_mangle] //~ WARN unused attribute
+#![no_mangle]
 #![no_link] //~ WARN unused attribute
 // see issue-43106-gating-of-derive.rs
 #![should_panic] //~ WARN unused attribute
index dcbe13a749f69b981661308165761959c3a26d47..c7081205e148195bdc5e2007bd025d2ffaf59a3f 100644 (file)
@@ -1152,12 +1152,6 @@ warning: unused attribute
 LL | #![automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1
-   |
-LL | #![no_mangle]
-   | ^^^^^^^^^^^^^
-
 warning: unused attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1
    |
index 2d91cbc00f27d492bb11387582a0bd4b829c35c4..26150c7d4a16b77de5f4a76803006e4b48e3bf24 100644 (file)
@@ -5,10 +5,14 @@
 
 #![deny(unused_extern_crates)]
 
-extern crate core as iso1; //~ ERROR `extern crate` is not idiomatic in the new edition
-extern crate core as iso2; //~ ERROR `extern crate` is not idiomatic in the new edition
-extern crate core as iso3; //~ ERROR `extern crate` is not idiomatic in the new edition
-extern crate core as iso4; //~ ERROR `extern crate` is not idiomatic in the new edition
+// Shouldn't suggest changing to `use`, as new name
+// would no longer be added to the prelude which could cause
+// compilation errors for imports that use the new name in
+// other modules. See #57672.
+extern crate core as iso1;
+extern crate core as iso2;
+extern crate core as iso3;
+extern crate core as iso4;
 
 // Doesn't introduce its extern prelude entry, so it's still considered unused.
 extern crate core; //~ ERROR unused extern crate
index c0783feb7947d2366c5b0a51d11d6b140609023e..397bfa02902c94df7528429b07a8e60dfd17e853 100644 (file)
@@ -1,8 +1,8 @@
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/extern-crate-used.rs:8:1
+error: unused extern crate
+  --> $DIR/extern-crate-used.rs:18:1
    |
-LL | extern crate core as iso1;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+LL | extern crate core;
+   | ^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: lint level defined here
   --> $DIR/extern-crate-used.rs:6:9
@@ -10,29 +10,5 @@ note: lint level defined here
 LL | #![deny(unused_extern_crates)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/extern-crate-used.rs:9:1
-   |
-LL | extern crate core as iso2;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/extern-crate-used.rs:10:1
-   |
-LL | extern crate core as iso3;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
-
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/extern-crate-used.rs:11:1
-   |
-LL | extern crate core as iso4;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
-
-error: unused extern crate
-  --> $DIR/extern-crate-used.rs:14:1
-   |
-LL | extern crate core;
-   | ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
index 4d86a17b6f1fbab6d3669cbfb7d151925f12686f..4ea567d25ca537bd3a328a74b2abeccd3ec5fe2d 100644 (file)
@@ -3,6 +3,7 @@
 
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 #![feature(os)]
 
index 84cca5b20af472d800fcc13e5c2ce366ec000683..04b8c3aa35396374ba058fc471b989d485ae34eb 100644 (file)
@@ -4,6 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()`
 LL |     Err(5)?;
    |           ^ the trait `std::convert::From<{integer}>` is not implemented for `()`
    |
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = note: required by `std::convert::From::from`
 
 error: aborting due to previous error
index 25225ca6e7c3a31639de25945af882629937f03d..3ba2a9d40bec4352cd58acacaa3ca6dedbd1cd23 100644 (file)
@@ -6,6 +6,7 @@
 // ignore-windows
 // ignore-cloudabi
 // ignore-emscripten
+// ignore-sgx no processes
 
 use std::process::Command;
 // use std::os::unix::process::CommandExt;
index 6aee474fe7435d02a0d2b5b7caef20c84aff7afe..108c969cdaddedfb445b22efd4179943e6039805 100644 (file)
@@ -1,5 +1,5 @@
 error[E0599]: no method named `exec` found for type `&mut std::process::Command` in the current scope
-  --> $DIR/issue-39175.rs:14:39
+  --> $DIR/issue-39175.rs:15:39
    |
 LL |     Command::new("echo").arg("hello").exec();
    |                                       ^^^^
index fa4221fb3392e2f31b35eb3153562a025e229cb9..f9ea5319d54c6ad26a91e3110dad5e64e8c995e0 100644 (file)
@@ -1,6 +1,7 @@
 // FIXME https://github.com/rust-lang/rust/issues/59774
 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> ""
 // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
+// ignore-sgx no weak linkages permitted
 
 #![feature(linkage)]
 
index c72978388ebfe232b90d1ccb25c1a274a77a2d4a..8326c0bacccb64ed4b0ffc9edbe6ea28b86ca0d7 100644 (file)
@@ -1,5 +1,5 @@
 error: must have type `*const T` or `*mut T`
-  --> $DIR/linkage2.rs:8:32
+  --> $DIR/linkage2.rs:9:32
    |
 LL |     #[linkage = "extern_weak"] static foo: i32;
    |                                ^^^^^^^^^^^^^^^^
index 7e1174a273438320880e1fd9ab3be70d37d9d05b..c2deeb7dfd48b0729fb52229baa3b2b170410978 100644 (file)
@@ -2,6 +2,7 @@
 // ignore-musl - no dylibs here
 // ignore-cloudabi
 // ignore-emscripten
+// ignore-sgx no dynamic lib support
 // error-pattern:`panic_unwind` is not compiled with this crate's panic strategy
 
 // This is a test where the local crate, compiled with `panic=abort`, links to
index bed1e32a60158110c5182368ac219abdaf61c402..0127261b2b7d0a6111f68b71c1af2690c5c7819b 100644 (file)
@@ -57,6 +57,15 @@ pub enum Enum4<A, B, C, D> {
     Four(D)
 }
 
+pub union Union1<A: Copy> {
+    a: A,
+}
+
+pub union Union2<A: Copy, B: Copy> {
+    a: A,
+    b: B,
+}
+
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
     let _x: MyOption<NonZeroU32> = Default::default();
@@ -69,5 +78,13 @@ fn start(_: isize, _: *const *const u8) -> isize {
     let _e: Enum4<(), char, (), ()> = Enum4::One(());
     let _f: Enum4<(), (), bool, ()> = Enum4::One(());
     let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
+
+    // Unions do not currently participate in niche filling.
+    let _h: MyOption<Union2<NonZeroU32, u32>> = Default::default();
+
+    // ...even when theoretically possible.
+    let _i: MyOption<Union1<NonZeroU32>> = Default::default();
+    let _j: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
+
     0
 }
index 9cdb2ae4f57e0aeb99097f211545210d8c75f1c2..301edc0d086b11fee1b251fd47b5ab7ebba36190 100644 (file)
@@ -14,6 +14,21 @@ print-type-size         field `.post`: 2 bytes
 print-type-size         field `.pre`: 1 bytes
 print-type-size     variant `None`: 0 bytes
 print-type-size     end padding: 1 bytes
+print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZeroU32, u32>>`: 8 bytes, alignment: 4 bytes
+print-type-size     discriminant: 4 bytes
+print-type-size     variant `Some`: 4 bytes
+print-type-size         field `.0`: 4 bytes
+print-type-size     variant `None`: 0 bytes
 print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
 print-type-size     field `.val`: 4 bytes
 print-type-size     field `.post`: 2 bytes
@@ -36,6 +51,17 @@ print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 by
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size     variant `None`: 0 bytes
+print-type-size type: `Union1<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Union1`: 4 bytes
+print-type-size         field `.a`: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Union2`: 4 bytes
+print-type-size         field `.a`: 4 bytes
+print-type-size         field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
+print-type-size type: `Union2<std::num::NonZeroU32, u32>`: 4 bytes, alignment: 4 bytes
+print-type-size     variant `Union2`: 4 bytes
+print-type-size         field `.a`: 4 bytes
+print-type-size         field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
 print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.0`: 4 bytes
 print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
index e2a7ac349ecd5ce6f3515ce9404cc6683ea2ccb3..e885263aa80840863fe5b44eb1a8381e171ec707 100644 (file)
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
+// ignore-sgx no processes
 
 // Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
 // as well as some compile time properties we expect.
@@ -69,44 +70,44 @@ fn f<'a>(x: &'a u8) -> &'a u8 { x }
 
 fn validate_stderr(stderr: Vec<String>) {
     assert_eq!(stderr, &[
-        ":21] Unit = Unit",
+        ":22] Unit = Unit",
 
-        ":22] a = Unit",
+        ":23] a = Unit",
 
-        ":28] Point{x: 42, y: 24,} = Point {",
+        ":29] Point{x: 42, y: 24,} = Point {",
         "    x: 42,",
         "    y: 24,",
         "}",
 
-        ":29] b = Point {",
+        ":30] b = Point {",
         "    x: 42,",
         "    y: 24,",
         "}",
 
-        ":37]",
+        ":38]",
 
-        ":41] &a = NoCopy(",
+        ":42] &a = NoCopy(",
         "    1337,",
         ")",
 
-        ":41] dbg!(& a) = NoCopy(",
+        ":42] dbg!(& a) = NoCopy(",
         "    1337,",
         ")",
-        ":46] f(&42) = 42",
+        ":47] f(&42) = 42",
 
         "before",
-        ":51] { foo += 1; eprintln!(\"before\"); 7331 } = 7331",
+        ":52] { foo += 1; eprintln!(\"before\"); 7331 } = 7331",
 
-        ":59] (\"Yeah\",) = (",
+        ":60] (\"Yeah\",) = (",
         "    \"Yeah\",",
         ")",
 
-        ":62] 1 = 1",
-        ":62] 2 = 2",
+        ":63] 1 = 1",
+        ":63] 2 = 2",
 
-        ":66] 1u8 = 1",
-        ":66] 2u32 = 2",
-        ":66] \"Yeah\" = \"Yeah\"",
+        ":67] 1u8 = 1",
+        ":67] 2u32 = 2",
+        ":67] \"Yeah\" = \"Yeah\"",
     ]);
 }
 
index ddd9abbd50ed8abed5a4853db71aeb8c2c9e5199..e51ce5d1d5b83e48bfc48e65be4538175ec9178b 100644 (file)
 
 //~^ ERROR unused extern crate
 
-use edition_lint_paths as bar;
-//~^ ERROR `extern crate` is not idiomatic in the new edition
+// Shouldn't suggest changing to `use`, as `bar`
+// would no longer be added to the prelude which could cause
+// compilation errors for imports that use `bar` in other
+// modules. See #57672.
+extern crate edition_lint_paths as bar;
 
 fn main() {
     // This is not considered to *use* the `extern crate` in Rust 2018:
index 47674bc19fc044614791f543f522f0d3005ae953..debbf085d618293d1ed901a4e535cf6f21414fbc 100644 (file)
 extern crate edition_lint_paths;
 //~^ ERROR unused extern crate
 
+// Shouldn't suggest changing to `use`, as `bar`
+// would no longer be added to the prelude which could cause
+// compilation errors for imports that use `bar` in other
+// modules. See #57672.
 extern crate edition_lint_paths as bar;
-//~^ ERROR `extern crate` is not idiomatic in the new edition
 
 fn main() {
     // This is not considered to *use* the `extern crate` in Rust 2018:
index f3f9193948667173bc6d68a756c239cf7333f928..13980c70a82aa219082d4271dd59b17112c8f498 100644 (file)
@@ -11,11 +11,5 @@ LL | #![deny(rust_2018_idioms)]
    |         ^^^^^^^^^^^^^^^^
    = note: #[deny(unused_extern_crates)] implied by #[deny(rust_2018_idioms)]
 
-error: `extern crate` is not idiomatic in the new edition
-  --> $DIR/extern-crate-idiomatic-in-2018.rs:15:1
-   |
-LL | extern crate edition_lint_paths as bar;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
index 17449caf84fb41ea835e42a5c56b9378ca93d0f9..14575d18c236aa3275b669bdaae93c6bd1f1c887 100644 (file)
@@ -7,7 +7,11 @@
 #![warn(rust_2018_idioms)]
 
 
-use core as another_name;
+// Shouldn't suggest changing to `use`, as `another_name`
+// would no longer be added to the prelude which could cause
+// compilation errors for imports that use `another_name` in other
+// modules. See #57672.
+extern crate core as another_name;
 use remove_extern_crate;
 #[macro_use]
 extern crate remove_extern_crate as something_else;
index fb2217df0005d4e8c7e250a54cea76473d8ea222..0ee85f34e40d99c98bbdb9bbc1649af77bcec8b5 100644 (file)
@@ -7,6 +7,10 @@
 #![warn(rust_2018_idioms)]
 
 extern crate core;
+// Shouldn't suggest changing to `use`, as `another_name`
+// would no longer be added to the prelude which could cause
+// compilation errors for imports that use `another_name` in other
+// modules. See #57672.
 extern crate core as another_name;
 use remove_extern_crate;
 #[macro_use]
index 549693201b70346a426bb61cb7a10723abcf3716..5de0dfe961338701d99e17fa1cfac2b5d848cf08 100644 (file)
@@ -12,13 +12,7 @@ LL | #![warn(rust_2018_idioms)]
    = note: #[warn(unused_extern_crates)] implied by #[warn(rust_2018_idioms)]
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:10:1
-   |
-LL | extern crate core as another_name;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
-
-warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:28:5
+  --> $DIR/remove-extern-crate.rs:32:5
    |
 LL |     extern crate core;
    |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
diff --git a/src/test/ui/suggestions/issue-57672.rs b/src/test/ui/suggestions/issue-57672.rs
new file mode 100644 (file)
index 0000000..1773f72
--- /dev/null
@@ -0,0 +1,14 @@
+// aux-build:foo.rs
+// compile-flags:--extern foo
+// compile-pass
+// edition:2018
+
+#![deny(unused_extern_crates)]
+
+extern crate foo as foo_renamed;
+
+pub mod m {
+    pub use foo_renamed::Foo;
+}
+
+fn main() {}
index 7c7366df1dc3ed6b59eac7c13fbf3b20c8ee6f18..e1c2c6b675e9bb1d1dd2d7a2ae56d7f1b73f9801 100644 (file)
@@ -4,6 +4,7 @@ error[E0277]: `?` couldn't convert the error to `i32`
 LL |         Err("")?;
    |                ^ the trait `std::convert::From<&str>` is not implemented for `i32`
    |
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following implementations were found:
              <i32 as std::convert::From<bool>>
              <i32 as std::convert::From<i16>>
index 4465fbe14b75cd39f2f9b3265dd245f4738b9f8a..db5046f8c151af029bc24d9f3b3a59b5b8c39c55 100644 (file)
@@ -4,6 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()`
 LL |     x?;
    |      ^ the trait `std::convert::From<std::option::NoneError>` is not implemented for `()`
    |
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = note: required by `std::convert::From::from`
 
 error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
index 11194e3d050f45ff002a775f451ff6222fcd5b2c..60a609acaed3bf2b3ec6ab995bccf0f03bc26060 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 11194e3d050f45ff002a775f451ff6222fcd5b2c
+Subproject commit 60a609acaed3bf2b3ec6ab995bccf0f03bc26060
index 04986b59ea0f1afeee4df464bf31e649bbab707d..38bd3fc006dcca0ec84f395b5f1b382f3b574faf 100644 (file)
@@ -15,6 +15,7 @@
 use std::path::PathBuf;
 use std::cell::RefCell;
 
+use syntax::edition::DEFAULT_EDITION;
 use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
 
 use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, PLAYGROUND};
@@ -97,7 +98,8 @@ fn error_code_block(&self, output: &mut dyn Write, info: &ErrorMetadata,
             Some(ref desc) => {
                 let mut id_map = self.0.borrow_mut();
                 write!(output, "{}",
-                    Markdown(desc, &[], RefCell::new(&mut id_map), ErrorCodes::Yes))?
+                    Markdown(desc, &[], RefCell::new(&mut id_map),
+                             ErrorCodes::Yes, DEFAULT_EDITION))?
             },
             None => write!(output, "<p>No description.</p>\n")?,
         }
index bc0c76d861a178911f3f506196a7404eda1e690d..0c85dbf3df0f545133dca24eccfc9f0f6107c7f8 160000 (submodule)
@@ -1 +1 @@
-Subproject commit bc0c76d861a178911f3f506196a7404eda1e690d
+Subproject commit 0c85dbf3df0f545133dca24eccfc9f0f6107c7f8
index 5b8e99bb61958ca8abcb7c5eda70521726be1065..9692ca8fd82a8f96a4113dc4b88c1fb1d79c1c60 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5b8e99bb61958ca8abcb7c5eda70521726be1065
+Subproject commit 9692ca8fd82a8f96a4113dc4b88c1fb1d79c1c60