From 4ced370f7c03dad99c74ceb4b86a0538b970690a Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Wed, 28 Sep 2022 15:11:27 +0200 Subject: [PATCH 01/12] Make `missing_copy_implementations` more cautious --- compiler/rustc_lint/src/builtin.rs | 34 +++++++++++++++++- ...lint-missing-copy-implementations-allow.rs | 35 +++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/lint/lint-missing-copy-implementations-allow.rs diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 93d81125f4885..1ea41098413f8 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -46,6 +46,7 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::List; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef}; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; @@ -53,7 +54,8 @@ use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, InnerSpan, Span}; use rustc_target::abi::{Abi, VariantIdx}; -use rustc_trait_selection::traits::{self, misc::can_type_implement_copy}; +use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt}; +use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult}; use crate::nonstandard_style::{method_context, MethodLateContext}; @@ -750,10 +752,40 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { if def.has_dtor(cx.tcx) { return; } + + // If the type contains a raw pointer, it may represent something like a handle, + // and recommending Copy might be a bad idea. + for field in def.all_fields() { + let did = field.did; + if cx.tcx.type_of(did).is_unsafe_ptr() { + return; + } + } let param_env = ty::ParamEnv::empty(); if ty.is_copy_modulo_regions(cx.tcx, param_env) { return; } + + // We shouldn't recommend implementing `Copy` on stateful things, + // such as iterators. + if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) { + if cx.tcx.infer_ctxt().enter(|infer_ctxt| { + infer_ctxt.type_implements_trait(iter_trait, ty, List::empty(), param_env) + == EvaluationResult::EvaluatedToOk + }) { + return; + } + } + + // Default value of clippy::trivially_copy_pass_by_ref + const MAX_SIZE: u64 = 256; + + if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) { + if size > MAX_SIZE { + return; + } + } + if can_type_implement_copy( cx.tcx, param_env, diff --git a/src/test/ui/lint/lint-missing-copy-implementations-allow.rs b/src/test/ui/lint/lint-missing-copy-implementations-allow.rs new file mode 100644 index 0000000000000..051a905aed643 --- /dev/null +++ b/src/test/ui/lint/lint-missing-copy-implementations-allow.rs @@ -0,0 +1,35 @@ +// check-pass +#![deny(missing_copy_implementations)] + +// Don't recommend implementing Copy on something stateful like an iterator. +pub struct MyIterator { + num: u8, +} + +impl Iterator for MyIterator { + type Item = u8; + + fn next(&mut self) -> Option { + todo!() + } +} + +pub struct Handle { + inner: *mut (), +} + +pub struct Handle2 { + inner: *const (), +} + +pub enum MaybeHandle { + Ptr(*mut ()), +} + +pub union UnionHandle { + ptr: *mut (), +} + +pub struct Array([u8; 2048]); + +fn main() {} From b209ff27f32425e0d3a6ae704669a617f2f2235a Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Sat, 19 Nov 2022 13:31:51 +0100 Subject: [PATCH 02/12] Update trait check --- compiler/rustc_lint/src/builtin.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 1ea41098413f8..4a0da9927c62d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -769,10 +769,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { // We shouldn't recommend implementing `Copy` on stateful things, // such as iterators. if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) { - if cx.tcx.infer_ctxt().enter(|infer_ctxt| { - infer_ctxt.type_implements_trait(iter_trait, ty, List::empty(), param_env) - == EvaluationResult::EvaluatedToOk - }) { + if cx.tcx.infer_ctxt().build().type_implements_trait( + iter_trait, + ty, + List::empty(), + param_env, + ) == EvaluationResult::EvaluatedToOk + { return; } } From 34277fcddc41e924ffed7ddacb573d240854cff0 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Tue, 29 Nov 2022 16:50:28 +0100 Subject: [PATCH 03/12] Rebase --- compiler/rustc_lint/src/builtin.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 4a0da9927c62d..5d1fb516357d5 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -46,7 +46,6 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::List; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef}; use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason}; use rustc_span::edition::Edition; @@ -769,12 +768,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { // We shouldn't recommend implementing `Copy` on stateful things, // such as iterators. if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) { - if cx.tcx.infer_ctxt().build().type_implements_trait( - iter_trait, - ty, - List::empty(), - param_env, - ) == EvaluationResult::EvaluatedToOk + if cx.tcx.infer_ctxt().build().type_implements_trait(iter_trait, [ty], param_env) + == EvaluationResult::EvaluatedToOk { return; } From 17766c1636dcf27278601b5e154dbc300376e378 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Tue, 6 Dec 2022 18:43:19 +0100 Subject: [PATCH 04/12] Skip test on s390x as LLD does not support the platform test/run-make/issue-71519 requires use of lld as linker, but lld does not currently support the s390x architecture. --- src/test/run-make/issue-71519/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-make/issue-71519/Makefile b/src/test/run-make/issue-71519/Makefile index 16d9a56e6bf78..57497f5205384 100644 --- a/src/test/run-make/issue-71519/Makefile +++ b/src/test/run-make/issue-71519/Makefile @@ -2,6 +2,7 @@ include ../../run-make-fulldeps/tools.mk # ignore-msvc # needs-rust-lld +# ignore-s390x lld does not yet support s390x as target all: RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt $(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt From 58e60ac211aa7555b949016cb795989ccedd8939 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 8 Dec 2022 01:42:45 -0800 Subject: [PATCH 05/12] Make `VecDeque::from_iter` O(1) from `vec(_deque)::IntoIter` --- .../src/collections/vec_deque/into_iter.rs | 4 ++ .../alloc/src/collections/vec_deque/mod.rs | 45 ++++++++++++++----- .../collections/vec_deque/spec_from_iter.rs | 33 ++++++++++++++ library/alloc/src/vec/into_iter.rs | 27 +++++++++++ library/alloc/tests/vec_deque.rs | 26 +++++++++++ 5 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 library/alloc/src/collections/vec_deque/spec_from_iter.rs diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs index 55f6138cd0f31..e54880e865230 100644 --- a/library/alloc/src/collections/vec_deque/into_iter.rs +++ b/library/alloc/src/collections/vec_deque/into_iter.rs @@ -25,6 +25,10 @@ impl IntoIter { pub(super) fn new(inner: VecDeque) -> Self { IntoIter { inner } } + + pub(super) fn into_vecdeque(self) -> VecDeque { + self.inner + } } #[stable(feature = "collection_debug", since = "1.17.0")] diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4866c53e7d521..8fee44d6f932b 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -55,6 +55,10 @@ use self::spec_extend::SpecExtend; mod spec_extend; +use self::spec_from_iter::SpecFromIter; + +mod spec_from_iter; + #[cfg(test)] mod tests; @@ -586,6 +590,35 @@ impl VecDeque { VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) } } + /// For use by `vec::IntoIter::into_vecdeque` + /// + /// # Safety + /// + /// All the usual requirements on the allocated memory like in + /// `Vec::from_raw_parts_in`, but takes a *range* of elements that are + /// initialized rather than only supporting `0..len`. Requires that + /// `initialized.start` ≤ `initialized.end` ≤ `capacity`. + #[inline] + pub(crate) unsafe fn from_contiguous_raw_parts_in( + ptr: *mut T, + initialized: Range, + capacity: usize, + alloc: A, + ) -> Self { + debug_assert!(initialized.start <= initialized.end); + debug_assert!(initialized.end <= capacity); + + // SAFETY: Our safety precondition guarantees the range length won't wrap, + // and that the allocation is valid for use in `RawVec`. + unsafe { + VecDeque { + head: initialized.start, + len: initialized.end.unchecked_sub(initialized.start), + buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), + } + } + } + /// Provides a reference to the element at the given index. /// /// Element at index 0 is the front of the queue. @@ -2699,18 +2732,8 @@ impl IndexMut for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for VecDeque { - #[inline] fn from_iter>(iter: I) -> VecDeque { - // Since converting is O(1) now, might as well re-use that logic - // (including things like the `vec::IntoIter`→`Vec` specialization) - // especially as that could save us some monomorphiziation work - // if one uses the same iterators (like slice ones) with both. - return from_iter_via_vec(iter.into_iter()); - - #[inline] - fn from_iter_via_vec(iter: impl Iterator) -> VecDeque { - Vec::from_iter(iter).into() - } + SpecFromIter::spec_from_iter(iter.into_iter()) } } diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs new file mode 100644 index 0000000000000..7650492ebdad1 --- /dev/null +++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs @@ -0,0 +1,33 @@ +use super::{IntoIter, VecDeque}; + +/// Specialization trait used for `VecDeque::from_iter` +pub(super) trait SpecFromIter { + fn spec_from_iter(iter: I) -> Self; +} + +impl SpecFromIter for VecDeque +where + I: Iterator, +{ + default fn spec_from_iter(iterator: I) -> Self { + // Since converting is O(1) now, just re-use the `Vec` logic for + // anything where we can't do something extra-special for `VecDeque`, + // especially as that could save us some monomorphiziation work + // if one uses the same iterators (like slice ones) with both. + crate::vec::Vec::from_iter(iterator).into() + } +} + +impl SpecFromIter> for VecDeque { + #[inline] + fn spec_from_iter(iterator: crate::vec::IntoIter) -> Self { + iterator.into_vecdeque() + } +} + +impl SpecFromIter> for VecDeque { + #[inline] + fn spec_from_iter(iterator: IntoIter) -> Self { + iterator.into_vecdeque() + } +} diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 02cc7691a82db..41e2fb9b2f0d9 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -1,6 +1,7 @@ #[cfg(not(no_global_oom_handling))] use super::AsVecIntoIter; use crate::alloc::{Allocator, Global}; +use crate::collections::VecDeque; use crate::raw_vec::RawVec; use core::array; use core::fmt; @@ -132,6 +133,32 @@ impl IntoIter { pub(crate) fn forget_remaining_elements(&mut self) { self.ptr = self.end; } + + #[inline] + pub(crate) fn into_vecdeque(self) -> VecDeque { + // Keep our `Drop` impl from dropping the elements and the allocator + let mut this = ManuallyDrop::new(self); + + // SAFETY: This allocation originally came from a `Vec`, so it passes + // all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`, + // so the `sub_ptr`s below cannot wrap, and will produce a well-formed + // range. `end` ≤ `buf + cap`, so the range will be in-bounds. + // Taking `alloc` is ok because nothing else is going to look at it, + // since our `Drop` impl isn't going to run so there's no more code. + unsafe { + let buf = this.buf.as_ptr(); + let initialized = if T::IS_ZST { + // All the pointers are the same for ZSTs, so it's fine to + // say that they're all at the beginning of the "allocation". + 0..this.len() + } else { + this.ptr.sub_ptr(buf)..this.end.sub_ptr(buf) + }; + let cap = this.cap; + let alloc = ManuallyDrop::take(&mut this.alloc); + VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc) + } + } } #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")] diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index d04de5a074b7f..823061d400f30 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1736,3 +1736,29 @@ fn test_resize_keeps_reserved_space_from_item() { d.resize(1, v); assert_eq!(d[0].capacity(), 1234); } + +#[test] +fn test_collect_from_into_iter_keeps_allocation() { + let mut v = Vec::with_capacity(13); + v.extend(0..7); + check(v.into_iter()); + + let mut v = VecDeque::with_capacity(13); + v.extend(0..7); + check(v.into_iter()); + + fn check(mut it: impl Iterator) { + assert_eq!(it.next(), Some(0)); + assert_eq!(it.next(), Some(1)); + let mut v: VecDeque = it.collect(); + assert_eq!(v.capacity(), 13); + assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.push_front(7); + assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.push_front(8); + assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + v.push_front(9); + assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice())); + assert_eq!(v.capacity(), 13); + } +} From 98ae83daae67e9e7663b8345eced1de8c667271f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 8 Dec 2022 10:35:46 -0800 Subject: [PATCH 06/12] Mangle "main" as "__main_void" on wasm32-wasi On wasm, the age-old C trick of having a main function which can either have no arguments or argc+argv doesn't work, because wasm requires caller and callee signatures to match. WASI's current strategy is to have compilers mangle main's name to indicate which signature they're using. Rust uses the no-argument form, which should be mangled as `__main_void`. This is needed on wasm32-wasi as of #105395. --- compiler/rustc_target/src/spec/wasm32_wasi.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs index 6f0bbf0672d44..a0476d542e642 100644 --- a/compiler/rustc_target/src/spec/wasm32_wasi.rs +++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs @@ -104,6 +104,10 @@ pub fn target() -> Target { // `args::args()` makes the WASI API calls itself. options.main_needs_argc_argv = false; + // And, WASI mangles the name of "main" to distinguish between different + // signatures. + options.entry_name = "__main_void".into(); + Target { llvm_target: "wasm32-wasi".into(), pointer_width: 32, From 5626df9c9098fc83518e3bc4cef06e449279ac3c Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sun, 4 Dec 2022 18:46:57 +0000 Subject: [PATCH 07/12] Add `rustc_on_unimplemented` to `Sum` and `Product` trait. --- library/core/src/iter/traits/accum.rs | 8 +++++ src/test/ui/on-unimplemented/sum.rs | 9 ++++++ src/test/ui/on-unimplemented/sum.stderr | 39 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 src/test/ui/on-unimplemented/sum.rs create mode 100644 src/test/ui/on-unimplemented/sum.stderr diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 84d83ee39699f..e31669b392420 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -10,6 +10,10 @@ use crate::num::Wrapping; /// [`sum()`]: Iterator::sum /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] +#[rustc_on_unimplemented( + message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`", + label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator`" +)] pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// "summing up" the items. @@ -27,6 +31,10 @@ pub trait Sum: Sized { /// [`product()`]: Iterator::product /// [`FromIterator`]: iter::FromIterator #[stable(feature = "iter_arith_traits", since = "1.12.0")] +#[rustc_on_unimplemented( + message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator", + label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator`" +)] pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// multiplying the items. diff --git a/src/test/ui/on-unimplemented/sum.rs b/src/test/ui/on-unimplemented/sum.rs new file mode 100644 index 0000000000000..4f1c521d9fe8e --- /dev/null +++ b/src/test/ui/on-unimplemented/sum.rs @@ -0,0 +1,9 @@ +// + +fn main() { + vec![(), ()].iter().sum::(); + //~^ ERROR + + vec![(), ()].iter().product::(); + //~^ ERROR +} diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr new file mode 100644 index 0000000000000..0c99e63f0e518 --- /dev/null +++ b/src/test/ui/on-unimplemented/sum.stderr @@ -0,0 +1,39 @@ +error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()` + --> $DIR/sum.rs:4:5 + | +LL | vec![(), ()].iter().sum::(); + | ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call + | | + | value of type `i32` cannot be made by summing a `std::iter::Iterator` + | + = help: the trait `Sum<&()>` is not implemented for `i32` + = help: the following other types implement trait `Sum`: + > + +note: required by a bound in `std::iter::Iterator::sum` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | S: Sum, + | ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum` + +error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator + --> $DIR/sum.rs:7:5 + | +LL | vec![(), ()].iter().product::(); + | ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call + | | + | value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator` + | + = help: the trait `Product<&()>` is not implemented for `i32` + = help: the following other types implement trait `Product`: + > + +note: required by a bound in `std::iter::Iterator::product` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | P: Product, + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::product` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 90da11d9afbc258ffa7bea146a6f0e0a09ae583d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 8 Dec 2022 17:38:07 -0700 Subject: [PATCH 08/12] rustdoc: remove no-op mobile CSS `#sidebar-toggle { text-align }` Since 8b001b4da0716936e0ca32303cc0e3c5e53e42f8 make the sidebar toggle a flex container, and already centers its content in desktop mode, this rule doesn't do anything. --- src/librustdoc/html/static/css/rustdoc.css | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 111361796075b..22e7558b2fa0e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1748,7 +1748,6 @@ in storage.js top: 100px; width: 30px; font-size: 1.5rem; - text-align: center; padding: 0; z-index: 10; border-top-right-radius: 3px; From 6648134434fe4ac69132852e6d58f15578bfc022 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 8 Dec 2022 22:08:55 -0800 Subject: [PATCH 09/12] Apply review feedback; Fix no_global_oom_handling build --- library/alloc/src/collections/vec_deque/mod.rs | 3 +++ library/alloc/src/vec/into_iter.rs | 2 ++ library/alloc/tests/vec_deque.rs | 16 +++++++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 8fee44d6f932b..4b9bd74d3924f 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -590,6 +590,9 @@ impl VecDeque { VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) } } + /// Creates a `VecDeque` from a raw allocation, when the initialized + /// part of that allocation forms a *contiguous* subslice thereof. + /// /// For use by `vec::IntoIter::into_vecdeque` /// /// # Safety diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 41e2fb9b2f0d9..6bcde6d899ce8 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -1,6 +1,7 @@ #[cfg(not(no_global_oom_handling))] use super::AsVecIntoIter; use crate::alloc::{Allocator, Global}; +#[cfg(not(no_global_oom_handling))] use crate::collections::VecDeque; use crate::raw_vec::RawVec; use core::array; @@ -134,6 +135,7 @@ impl IntoIter { self.ptr = self.end; } + #[cfg(not(no_global_oom_handling))] #[inline] pub(crate) fn into_vecdeque(self) -> VecDeque { // Keep our `Drop` impl from dropping the elements and the allocator diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index 823061d400f30..0b8f5281b785c 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1741,22 +1741,32 @@ fn test_resize_keeps_reserved_space_from_item() { fn test_collect_from_into_iter_keeps_allocation() { let mut v = Vec::with_capacity(13); v.extend(0..7); - check(v.into_iter()); + check(v.as_ptr(), v.last().unwrap(), v.into_iter()); let mut v = VecDeque::with_capacity(13); v.extend(0..7); - check(v.into_iter()); + check(&v[0], &v[v.len() - 1], v.into_iter()); - fn check(mut it: impl Iterator) { + fn check(buf: *const i32, last: *const i32, mut it: impl Iterator) { assert_eq!(it.next(), Some(0)); assert_eq!(it.next(), Some(1)); + let mut v: VecDeque = it.collect(); assert_eq!(v.capacity(), 13); + assert_eq!(v.as_slices().0.as_ptr(), buf.wrapping_add(2)); + assert_eq!(&v[v.len() - 1] as *const _, last); + assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice())); v.push_front(7); assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); v.push_front(8); assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice())); + + // Now that we've adding thing in place of the two that we removed from + // the front of the iterator, we're back to matching the buffer pointer. + assert_eq!(v.as_slices().0.as_ptr(), buf); + assert_eq!(&v[v.len() - 1] as *const _, last); + v.push_front(9); assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice())); assert_eq!(v.capacity(), 13); From f41576bd3de548d0f46e534662c13d93b273847b Mon Sep 17 00:00:00 2001 From: Ikko Ashimine Date: Fri, 9 Dec 2022 18:09:32 +0900 Subject: [PATCH 10/12] Fix typo in apple_base.rs erronous -> erroneous --- compiler/rustc_target/src/spec/apple_base.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 7f8160b5dec62..fc6a2edabb763 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -204,7 +204,7 @@ pub fn macos_llvm_target(arch: Arch) -> String { fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow]> { // Apple platforms only officially support macOS as a host for any compilation. // - // If building for macOS, we go ahead and remove any erronous environment state + // If building for macOS, we go ahead and remove any erroneous environment state // that's only applicable to cross-OS compilation. Always leave anything for the // host OS alone though. if os == "macos" { From d60967bef29b4b9ad5c145f216a582da28b22505 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 9 Dec 2022 10:40:49 -0700 Subject: [PATCH 11/12] rustdoc: make stability badge CSS more consistent * They all get rounded corners now. A test case has been added for this, too. * There are now broadly two kinds of stability badge, where there used to be three: item-info "fat badge", and the "thin badge" in both item tables and in docblocks (which got merged). The fat badges can have icons, while the thin badges can't. --- src/librustdoc/html/static/css/rustdoc.css | 35 ++++++---------- src/librustdoc/html/static/css/themes/ayu.css | 5 --- src/test/rustdoc-gui/stab-badge.goml | 41 +++++++++++++++++++ 3 files changed, 54 insertions(+), 27 deletions(-) create mode 100644 src/test/rustdoc-gui/stab-badge.goml diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index afcb402240205..37f115e3d9efc 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -212,7 +212,7 @@ pre.rust a, .mobile-topbar h2 a, h1 a, .search-results a, -.item-left .stab, +.stab, .result-name .primitive > i, .result-name .keyword > i { color: var(--main-color); } @@ -960,22 +960,29 @@ so that we can apply CSS-filters to change the arrow color in themes */ } .item-info .stab { - width: fit-content; /* This min-height is needed to unify the height of the stab elements because some of them have emojis. */ min-height: 36px; display: flex; - align-items: center; - white-space: pre-wrap; -} -.stab { padding: 3px; margin-bottom: 5px; +} +.item-left .stab { + margin-left: 0.3125em; +} +.stab { + padding: 0 2px; font-size: 0.875rem; font-weight: normal; color: var(--main-color); background-color: var(--stab-background-color); + width: fit-content; + align-items: center; + white-space: pre-wrap; + border-radius: 3px; + display: inline-flex; + vertical-align: text-bottom; } .stab.portability > code { @@ -988,12 +995,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ margin-right: 0.3rem; } -/* This is to prevent the `.stab` elements to overflow the .docblock elements. */ -.docblock .stab { - padding: 0 0.125em; - margin-bottom: 0; -} - /* Black one-pixel outline around emoji shapes */ .emoji { text-shadow: @@ -1003,16 +1004,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ 0 -1px 0 black; } -.item-left .stab { - border-radius: 3px; - display: inline-block; - line-height: 1.2; - margin-bottom: 0; - margin-left: 0.3125em; - padding: 2px; - vertical-align: text-bottom; -} - .module-item.unstable, .import-item.unstable { opacity: 0.65; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 0436fe0138edc..eba845bf5a915 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -160,11 +160,6 @@ body.source .example-wrap pre.rust a { background: #333; } -.module-item .stab, -.import-item .stab { - color: #000; -} - .result-name .primitive > i, .result-name .keyword > i { color: #788797; } diff --git a/src/test/rustdoc-gui/stab-badge.goml b/src/test/rustdoc-gui/stab-badge.goml new file mode 100644 index 0000000000000..aaed8440a40bd --- /dev/null +++ b/src/test/rustdoc-gui/stab-badge.goml @@ -0,0 +1,41 @@ +// All stability badges should have rounded corners and colored backgrounds. +goto: "file://" + |DOC_PATH| + "/test_docs/index.html" +show-text: true +define-function: ( + "check-badge", + (theme, background, color), + [ + ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), + ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), + ("assert", (".docblock .stab")), + ("assert", (".item-table .stab")), + ("assert-css", (".stab", { + "border-radius": "3px", + "color": |color|, + "background-color": |background|, + })), + ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"), + ("assert", (".item-info .stab")), + ("assert-css", (".stab", { + "border-radius": "3px", + "color": |color|, + "background-color": |background|, + })), + ] +) + +call-function: ("check-badge", { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background": "rgb(49, 69, 89)", +}) +call-function: ("check-badge", { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background": "rgb(49, 69, 89)", +}) +call-function: ("check-badge", { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background": "rgb(255, 245, 214)", +}) From b3b17bde31103fbf98f17cc7107e167f2c28172c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 9 Dec 2022 10:44:11 -0800 Subject: [PATCH 12/12] Tweak `rustc_must_implement_one_of` diagnostic output --- compiler/rustc_hir_analysis/src/collect.rs | 19 ++++++++----------- .../rustc_must_implement_one_of_duplicates.rs | 8 ++++---- ...tc_must_implement_one_of_duplicates.stderr | 16 ++++++++-------- .../rustc_must_implement_one_of_misuse.rs | 14 +++++++------- .../rustc_must_implement_one_of_misuse.stderr | 18 +++++++++--------- 5 files changed, 36 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 945361ef43a4e..18f08ff6677cd 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -955,7 +955,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { .struct_span_err( attr.span, "the `#[rustc_must_implement_one_of]` attribute must be \ - used with at least 2 args", + used with at least 2 args", ) .emit(); @@ -987,7 +987,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { tcx.sess .struct_span_err( item.span, - "This function doesn't have a default implementation", + "function doesn't have a default implementation", ) .span_note(attr_span, "required by this annotation") .emit(); @@ -999,17 +999,17 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { } Some(item) => { tcx.sess - .struct_span_err(item.span, "Not a function") + .struct_span_err(item.span, "not a function") .span_note(attr_span, "required by this annotation") .note( - "All `#[rustc_must_implement_one_of]` arguments \ - must be associated function names", + "all `#[rustc_must_implement_one_of]` arguments must be associated \ + function names", ) .emit(); } None => { tcx.sess - .struct_span_err(ident.span, "Function not found in this trait") + .struct_span_err(ident.span, "function not found in this trait") .emit(); } } @@ -1027,11 +1027,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { for ident in &*list { if let Some(dup) = set.insert(ident.name, ident.span) { tcx.sess - .struct_span_err(vec![dup, ident.span], "Functions names are duplicated") - .note( - "All `#[rustc_must_implement_one_of]` arguments \ - must be unique", - ) + .struct_span_err(vec![dup, ident.span], "functions names are duplicated") + .note("all `#[rustc_must_implement_one_of]` arguments must be unique") .emit(); no_dups = false; diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs index 56e8fcff0fce5..8db5fa615c08d 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs @@ -1,15 +1,15 @@ #![feature(rustc_attrs)] #[rustc_must_implement_one_of(a, a)] -//~^ Functions names are duplicated +//~^ functions names are duplicated trait Trait { fn a() {} } #[rustc_must_implement_one_of(b, a, a, c, b, c)] -//~^ Functions names are duplicated -//~| Functions names are duplicated -//~| Functions names are duplicated +//~^ functions names are duplicated +//~| functions names are duplicated +//~| functions names are duplicated trait Trait1 { fn a() {} fn b() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr index 777beba618277..cd1476a6eb81b 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr @@ -1,34 +1,34 @@ -error: Functions names are duplicated +error: functions names are duplicated --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31 | LL | #[rustc_must_implement_one_of(a, a)] | ^ ^ | - = note: All `#[rustc_must_implement_one_of]` arguments must be unique + = note: all `#[rustc_must_implement_one_of]` arguments must be unique -error: Functions names are duplicated +error: functions names are duplicated --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34 | LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] | ^ ^ | - = note: All `#[rustc_must_implement_one_of]` arguments must be unique + = note: all `#[rustc_must_implement_one_of]` arguments must be unique -error: Functions names are duplicated +error: functions names are duplicated --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31 | LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] | ^ ^ | - = note: All `#[rustc_must_implement_one_of]` arguments must be unique + = note: all `#[rustc_must_implement_one_of]` arguments must be unique -error: Functions names are duplicated +error: functions names are duplicated --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40 | LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] | ^ ^ | - = note: All `#[rustc_must_implement_one_of]` arguments must be unique + = note: all `#[rustc_must_implement_one_of]` arguments must be unique error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs index 1f896da94db57..b1b91966c8d88 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -1,12 +1,12 @@ #![feature(rustc_attrs)] #[rustc_must_implement_one_of(a, b)] -//~^ Function not found in this trait -//~| Function not found in this trait +//~^ function not found in this trait +//~| function not found in this trait trait Tr0 {} #[rustc_must_implement_one_of(a, b)] -//~^ Function not found in this trait +//~^ function not found in this trait trait Tr1 { fn a() {} } @@ -23,16 +23,16 @@ trait Tr3 {} #[rustc_must_implement_one_of(A, B)] trait Tr4 { - const A: u8 = 1; //~ Not a function + const A: u8 = 1; //~ not a function - type B; //~ Not a function + type B; //~ not a function } #[rustc_must_implement_one_of(a, b)] trait Tr5 { - fn a(); //~ This function doesn't have a default implementation + fn a(); //~ function doesn't have a default implementation - fn b(); //~ This function doesn't have a default implementation + fn b(); //~ function doesn't have a default implementation } #[rustc_must_implement_one_of(abc, xyz)] diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr index 869184f0d1a69..38e692521ca23 100644 --- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -22,19 +22,19 @@ LL | LL | struct Struct {} | ---------------- not a trait -error: Function not found in this trait +error: function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 | LL | #[rustc_must_implement_one_of(a, b)] | ^ -error: Function not found in this trait +error: function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 | LL | #[rustc_must_implement_one_of(a, b)] | ^ -error: Function not found in this trait +error: function not found in this trait --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 | LL | #[rustc_must_implement_one_of(a, b)] @@ -46,7 +46,7 @@ error: the `#[rustc_must_implement_one_of]` attribute must be used with at least LL | #[rustc_must_implement_one_of(a)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Not a function +error: not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 | LL | const A: u8 = 1; @@ -57,9 +57,9 @@ note: required by this annotation | LL | #[rustc_must_implement_one_of(A, B)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names + = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names -error: Not a function +error: not a function --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5 | LL | type B; @@ -70,9 +70,9 @@ note: required by this annotation | LL | #[rustc_must_implement_one_of(A, B)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names + = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names -error: This function doesn't have a default implementation +error: function doesn't have a default implementation --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5 | LL | fn a(); @@ -84,7 +84,7 @@ note: required by this annotation LL | #[rustc_must_implement_one_of(a, b)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: This function doesn't have a default implementation +error: function doesn't have a default implementation --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5 | LL | fn b();