Skip to content

Commit a000811

Browse files
committed
Auto merge of rust-lang#105512 - matthiaskrgr:rollup-i74avrf, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang#102406 (Make `missing_copy_implementations` more cautious) - rust-lang#105265 (Add `rustc_on_unimplemented` to `Sum` and `Product` trait.) - rust-lang#105385 (Skip test on s390x as LLD does not support the platform) - rust-lang#105453 (Make `VecDeque::from_iter` O(1) from `vec(_deque)::IntoIter`) - rust-lang#105468 (Mangle "main" as "__main_void" on wasm32-wasi) - rust-lang#105480 (rustdoc: remove no-op mobile CSS `#sidebar-toggle { text-align }`) - rust-lang#105489 (Fix typo in apple_base.rs) - rust-lang#105504 (rustdoc: make stability badge CSS more consistent) - rust-lang#105506 (Tweak `rustc_must_implement_one_of` diagnostic output) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0d5573e + 376b0bc commit a000811

File tree

21 files changed

+357
-80
lines changed

21 files changed

+357
-80
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
955955
.struct_span_err(
956956
attr.span,
957957
"the `#[rustc_must_implement_one_of]` attribute must be \
958-
used with at least 2 args",
958+
used with at least 2 args",
959959
)
960960
.emit();
961961

@@ -987,7 +987,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
987987
tcx.sess
988988
.struct_span_err(
989989
item.span,
990-
"This function doesn't have a default implementation",
990+
"function doesn't have a default implementation",
991991
)
992992
.span_note(attr_span, "required by this annotation")
993993
.emit();
@@ -999,17 +999,17 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
999999
}
10001000
Some(item) => {
10011001
tcx.sess
1002-
.struct_span_err(item.span, "Not a function")
1002+
.struct_span_err(item.span, "not a function")
10031003
.span_note(attr_span, "required by this annotation")
10041004
.note(
1005-
"All `#[rustc_must_implement_one_of]` arguments \
1006-
must be associated function names",
1005+
"all `#[rustc_must_implement_one_of]` arguments must be associated \
1006+
function names",
10071007
)
10081008
.emit();
10091009
}
10101010
None => {
10111011
tcx.sess
1012-
.struct_span_err(ident.span, "Function not found in this trait")
1012+
.struct_span_err(ident.span, "function not found in this trait")
10131013
.emit();
10141014
}
10151015
}
@@ -1027,11 +1027,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
10271027
for ident in &*list {
10281028
if let Some(dup) = set.insert(ident.name, ident.span) {
10291029
tcx.sess
1030-
.struct_span_err(vec![dup, ident.span], "Functions names are duplicated")
1031-
.note(
1032-
"All `#[rustc_must_implement_one_of]` arguments \
1033-
must be unique",
1034-
)
1030+
.struct_span_err(vec![dup, ident.span], "functions names are duplicated")
1031+
.note("all `#[rustc_must_implement_one_of]` arguments must be unique")
10351032
.emit();
10361033

10371034
no_dups = false;

compiler/rustc_lint/src/builtin.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ use rustc_span::source_map::Spanned;
5353
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5454
use rustc_span::{BytePos, InnerSpan, Span};
5555
use rustc_target::abi::{Abi, VariantIdx};
56-
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
56+
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
57+
use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
5758

5859
use crate::nonstandard_style::{method_context, MethodLateContext};
5960

@@ -750,10 +751,39 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
750751
if def.has_dtor(cx.tcx) {
751752
return;
752753
}
754+
755+
// If the type contains a raw pointer, it may represent something like a handle,
756+
// and recommending Copy might be a bad idea.
757+
for field in def.all_fields() {
758+
let did = field.did;
759+
if cx.tcx.type_of(did).is_unsafe_ptr() {
760+
return;
761+
}
762+
}
753763
let param_env = ty::ParamEnv::empty();
754764
if ty.is_copy_modulo_regions(cx.tcx, param_env) {
755765
return;
756766
}
767+
768+
// We shouldn't recommend implementing `Copy` on stateful things,
769+
// such as iterators.
770+
if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
771+
if cx.tcx.infer_ctxt().build().type_implements_trait(iter_trait, [ty], param_env)
772+
== EvaluationResult::EvaluatedToOk
773+
{
774+
return;
775+
}
776+
}
777+
778+
// Default value of clippy::trivially_copy_pass_by_ref
779+
const MAX_SIZE: u64 = 256;
780+
781+
if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
782+
if size > MAX_SIZE {
783+
return;
784+
}
785+
}
786+
757787
if can_type_implement_copy(
758788
cx.tcx,
759789
param_env,

compiler/rustc_target/src/spec/apple_base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ pub fn macos_llvm_target(arch: Arch) -> String {
204204
fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> {
205205
// Apple platforms only officially support macOS as a host for any compilation.
206206
//
207-
// If building for macOS, we go ahead and remove any erronous environment state
207+
// If building for macOS, we go ahead and remove any erroneous environment state
208208
// that's only applicable to cross-OS compilation. Always leave anything for the
209209
// host OS alone though.
210210
if os == "macos" {

compiler/rustc_target/src/spec/wasm32_wasi.rs

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ pub fn target() -> Target {
104104
// `args::args()` makes the WASI API calls itself.
105105
options.main_needs_argc_argv = false;
106106

107+
// And, WASI mangles the name of "main" to distinguish between different
108+
// signatures.
109+
options.entry_name = "__main_void".into();
110+
107111
Target {
108112
llvm_target: "wasm32-wasi".into(),
109113
pointer_width: 32,

library/alloc/src/collections/vec_deque/into_iter.rs

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ impl<T, A: Allocator> IntoIter<T, A> {
2525
pub(super) fn new(inner: VecDeque<T, A>) -> Self {
2626
IntoIter { inner }
2727
}
28+
29+
pub(super) fn into_vecdeque(self) -> VecDeque<T, A> {
30+
self.inner
31+
}
2832
}
2933

3034
#[stable(feature = "collection_debug", since = "1.17.0")]

library/alloc/src/collections/vec_deque/mod.rs

+37-11
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ use self::spec_extend::SpecExtend;
5555

5656
mod spec_extend;
5757

58+
use self::spec_from_iter::SpecFromIter;
59+
60+
mod spec_from_iter;
61+
5862
#[cfg(test)]
5963
mod tests;
6064

@@ -586,6 +590,38 @@ impl<T, A: Allocator> VecDeque<T, A> {
586590
VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) }
587591
}
588592

593+
/// Creates a `VecDeque` from a raw allocation, when the initialized
594+
/// part of that allocation forms a *contiguous* subslice thereof.
595+
///
596+
/// For use by `vec::IntoIter::into_vecdeque`
597+
///
598+
/// # Safety
599+
///
600+
/// All the usual requirements on the allocated memory like in
601+
/// `Vec::from_raw_parts_in`, but takes a *range* of elements that are
602+
/// initialized rather than only supporting `0..len`. Requires that
603+
/// `initialized.start` ≤ `initialized.end` ≤ `capacity`.
604+
#[inline]
605+
pub(crate) unsafe fn from_contiguous_raw_parts_in(
606+
ptr: *mut T,
607+
initialized: Range<usize>,
608+
capacity: usize,
609+
alloc: A,
610+
) -> Self {
611+
debug_assert!(initialized.start <= initialized.end);
612+
debug_assert!(initialized.end <= capacity);
613+
614+
// SAFETY: Our safety precondition guarantees the range length won't wrap,
615+
// and that the allocation is valid for use in `RawVec`.
616+
unsafe {
617+
VecDeque {
618+
head: initialized.start,
619+
len: initialized.end.unchecked_sub(initialized.start),
620+
buf: RawVec::from_raw_parts_in(ptr, capacity, alloc),
621+
}
622+
}
623+
}
624+
589625
/// Provides a reference to the element at the given index.
590626
///
591627
/// Element at index 0 is the front of the queue.
@@ -2699,18 +2735,8 @@ impl<T, A: Allocator> IndexMut<usize> for VecDeque<T, A> {
26992735

27002736
#[stable(feature = "rust1", since = "1.0.0")]
27012737
impl<T> FromIterator<T> for VecDeque<T> {
2702-
#[inline]
27032738
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
2704-
// Since converting is O(1) now, might as well re-use that logic
2705-
// (including things like the `vec::IntoIter`→`Vec` specialization)
2706-
// especially as that could save us some monomorphiziation work
2707-
// if one uses the same iterators (like slice ones) with both.
2708-
return from_iter_via_vec(iter.into_iter());
2709-
2710-
#[inline]
2711-
fn from_iter_via_vec<U>(iter: impl Iterator<Item = U>) -> VecDeque<U> {
2712-
Vec::from_iter(iter).into()
2713-
}
2739+
SpecFromIter::spec_from_iter(iter.into_iter())
27142740
}
27152741
}
27162742

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use super::{IntoIter, VecDeque};
2+
3+
/// Specialization trait used for `VecDeque::from_iter`
4+
pub(super) trait SpecFromIter<T, I> {
5+
fn spec_from_iter(iter: I) -> Self;
6+
}
7+
8+
impl<T, I> SpecFromIter<T, I> for VecDeque<T>
9+
where
10+
I: Iterator<Item = T>,
11+
{
12+
default fn spec_from_iter(iterator: I) -> Self {
13+
// Since converting is O(1) now, just re-use the `Vec` logic for
14+
// anything where we can't do something extra-special for `VecDeque`,
15+
// especially as that could save us some monomorphiziation work
16+
// if one uses the same iterators (like slice ones) with both.
17+
crate::vec::Vec::from_iter(iterator).into()
18+
}
19+
}
20+
21+
impl<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> {
22+
#[inline]
23+
fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self {
24+
iterator.into_vecdeque()
25+
}
26+
}
27+
28+
impl<T> SpecFromIter<T, IntoIter<T>> for VecDeque<T> {
29+
#[inline]
30+
fn spec_from_iter(iterator: IntoIter<T>) -> Self {
31+
iterator.into_vecdeque()
32+
}
33+
}

library/alloc/src/vec/into_iter.rs

+29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#[cfg(not(no_global_oom_handling))]
22
use super::AsVecIntoIter;
33
use crate::alloc::{Allocator, Global};
4+
#[cfg(not(no_global_oom_handling))]
5+
use crate::collections::VecDeque;
46
use crate::raw_vec::RawVec;
57
use core::array;
68
use core::fmt;
@@ -132,6 +134,33 @@ impl<T, A: Allocator> IntoIter<T, A> {
132134
pub(crate) fn forget_remaining_elements(&mut self) {
133135
self.ptr = self.end;
134136
}
137+
138+
#[cfg(not(no_global_oom_handling))]
139+
#[inline]
140+
pub(crate) fn into_vecdeque(self) -> VecDeque<T, A> {
141+
// Keep our `Drop` impl from dropping the elements and the allocator
142+
let mut this = ManuallyDrop::new(self);
143+
144+
// SAFETY: This allocation originally came from a `Vec`, so it passes
145+
// all those checks. We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
146+
// so the `sub_ptr`s below cannot wrap, and will produce a well-formed
147+
// range. `end` ≤ `buf + cap`, so the range will be in-bounds.
148+
// Taking `alloc` is ok because nothing else is going to look at it,
149+
// since our `Drop` impl isn't going to run so there's no more code.
150+
unsafe {
151+
let buf = this.buf.as_ptr();
152+
let initialized = if T::IS_ZST {
153+
// All the pointers are the same for ZSTs, so it's fine to
154+
// say that they're all at the beginning of the "allocation".
155+
0..this.len()
156+
} else {
157+
this.ptr.sub_ptr(buf)..this.end.sub_ptr(buf)
158+
};
159+
let cap = this.cap;
160+
let alloc = ManuallyDrop::take(&mut this.alloc);
161+
VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc)
162+
}
163+
}
135164
}
136165

137166
#[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]

library/alloc/tests/vec_deque.rs

+36
Original file line numberDiff line numberDiff line change
@@ -1736,3 +1736,39 @@ fn test_resize_keeps_reserved_space_from_item() {
17361736
d.resize(1, v);
17371737
assert_eq!(d[0].capacity(), 1234);
17381738
}
1739+
1740+
#[test]
1741+
fn test_collect_from_into_iter_keeps_allocation() {
1742+
let mut v = Vec::with_capacity(13);
1743+
v.extend(0..7);
1744+
check(v.as_ptr(), v.last().unwrap(), v.into_iter());
1745+
1746+
let mut v = VecDeque::with_capacity(13);
1747+
v.extend(0..7);
1748+
check(&v[0], &v[v.len() - 1], v.into_iter());
1749+
1750+
fn check(buf: *const i32, last: *const i32, mut it: impl Iterator<Item = i32>) {
1751+
assert_eq!(it.next(), Some(0));
1752+
assert_eq!(it.next(), Some(1));
1753+
1754+
let mut v: VecDeque<i32> = it.collect();
1755+
assert_eq!(v.capacity(), 13);
1756+
assert_eq!(v.as_slices().0.as_ptr(), buf.wrapping_add(2));
1757+
assert_eq!(&v[v.len() - 1] as *const _, last);
1758+
1759+
assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice()));
1760+
v.push_front(7);
1761+
assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
1762+
v.push_front(8);
1763+
assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
1764+
1765+
// Now that we've adding thing in place of the two that we removed from
1766+
// the front of the iterator, we're back to matching the buffer pointer.
1767+
assert_eq!(v.as_slices().0.as_ptr(), buf);
1768+
assert_eq!(&v[v.len() - 1] as *const _, last);
1769+
1770+
v.push_front(9);
1771+
assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice()));
1772+
assert_eq!(v.capacity(), 13);
1773+
}
1774+
}

library/core/src/iter/traits/accum.rs

+8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ use crate::num::Wrapping;
1010
/// [`sum()`]: Iterator::sum
1111
/// [`FromIterator`]: iter::FromIterator
1212
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
13+
#[rustc_on_unimplemented(
14+
message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
15+
label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
16+
)]
1317
pub trait Sum<A = Self>: Sized {
1418
/// Method which takes an iterator and generates `Self` from the elements by
1519
/// "summing up" the items.
@@ -27,6 +31,10 @@ pub trait Sum<A = Self>: Sized {
2731
/// [`product()`]: Iterator::product
2832
/// [`FromIterator`]: iter::FromIterator
2933
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
34+
#[rustc_on_unimplemented(
35+
message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
36+
label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
37+
)]
3038
pub trait Product<A = Self>: Sized {
3139
/// Method which takes an iterator and generates `Self` from the elements by
3240
/// multiplying the items.

0 commit comments

Comments
 (0)