Auto merge of #105512 - matthiaskrgr:rollup-i74avrf, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #102406 (Make `missing_copy_implementations` more cautious) - #105265 (Add `rustc_on_unimplemented` to `Sum` and `Product` trait.) - #105385 (Skip test on s390x as LLD does not support the platform) - #105453 (Make `VecDeque::from_iter` O(1) from `vec(_deque)::IntoIter`) - #105468 (Mangle "main" as "__main_void" on wasm32-wasi) - #105480 (rustdoc: remove no-op mobile CSS `#sidebar-toggle { text-align }`) - #105489 (Fix typo in apple_base.rs) - #105504 (rustdoc: make stability badge CSS more consistent) - #105506 (Tweak `rustc_must_implement_one_of` diagnostic output) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a000811405
@ -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;
|
||||
|
@ -53,7 +53,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 +751,39 @@ 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().build().type_implements_trait(iter_trait, [ty], 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,
|
||||
|
@ -204,7 +204,7 @@ pub fn macos_llvm_target(arch: Arch) -> String {
|
||||
fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> {
|
||||
// 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" {
|
||||
|
@ -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,
|
||||
|
@ -25,6 +25,10 @@ impl<T, A: Allocator> IntoIter<T, A> {
|
||||
pub(super) fn new(inner: VecDeque<T, A>) -> Self {
|
||||
IntoIter { inner }
|
||||
}
|
||||
|
||||
pub(super) fn into_vecdeque(self) -> VecDeque<T, A> {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
|
@ -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,38 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
||||
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
|
||||
///
|
||||
/// 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<usize>,
|
||||
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 +2735,8 @@ impl<T, A: Allocator> IndexMut<usize> for VecDeque<T, A> {
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> FromIterator<T> for VecDeque<T> {
|
||||
#[inline]
|
||||
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
|
||||
// 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<U>(iter: impl Iterator<Item = U>) -> VecDeque<U> {
|
||||
Vec::from_iter(iter).into()
|
||||
}
|
||||
SpecFromIter::spec_from_iter(iter.into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
|
33
library/alloc/src/collections/vec_deque/spec_from_iter.rs
Normal file
33
library/alloc/src/collections/vec_deque/spec_from_iter.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use super::{IntoIter, VecDeque};
|
||||
|
||||
/// Specialization trait used for `VecDeque::from_iter`
|
||||
pub(super) trait SpecFromIter<T, I> {
|
||||
fn spec_from_iter(iter: I) -> Self;
|
||||
}
|
||||
|
||||
impl<T, I> SpecFromIter<T, I> for VecDeque<T>
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
{
|
||||
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<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> {
|
||||
#[inline]
|
||||
fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self {
|
||||
iterator.into_vecdeque()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SpecFromIter<T, IntoIter<T>> for VecDeque<T> {
|
||||
#[inline]
|
||||
fn spec_from_iter(iterator: IntoIter<T>) -> Self {
|
||||
iterator.into_vecdeque()
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
#[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;
|
||||
use core::fmt;
|
||||
@ -132,6 +134,33 @@ impl<T, A: Allocator> IntoIter<T, A> {
|
||||
pub(crate) fn forget_remaining_elements(&mut self) {
|
||||
self.ptr = self.end;
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
pub(crate) fn into_vecdeque(self) -> VecDeque<T, A> {
|
||||
// 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")]
|
||||
|
@ -1736,3 +1736,39 @@ 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.as_ptr(), v.last().unwrap(), v.into_iter());
|
||||
|
||||
let mut v = VecDeque::with_capacity(13);
|
||||
v.extend(0..7);
|
||||
check(&v[0], &v[v.len() - 1], v.into_iter());
|
||||
|
||||
fn check(buf: *const i32, last: *const i32, mut it: impl Iterator<Item = i32>) {
|
||||
assert_eq!(it.next(), Some(0));
|
||||
assert_eq!(it.next(), Some(1));
|
||||
|
||||
let mut v: VecDeque<i32> = 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);
|
||||
}
|
||||
}
|
||||
|
@ -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<Item={A}>`"
|
||||
)]
|
||||
pub trait Sum<A = Self>: Sized {
|
||||
/// Method which takes an iterator and generates `Self` from the elements by
|
||||
/// "summing up" the items.
|
||||
@ -27,6 +31,10 @@ pub trait Sum<A = Self>: 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<Item={A}>`"
|
||||
)]
|
||||
pub trait Product<A = Self>: Sized {
|
||||
/// Method which takes an iterator and generates `Self` from the elements by
|
||||
/// multiplying the items.
|
||||
|
@ -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;
|
||||
@ -1742,7 +1733,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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
41
src/test/rustdoc-gui/stab-badge.goml
Normal file
41
src/test/rustdoc-gui/stab-badge.goml
Normal file
@ -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)",
|
||||
})
|
35
src/test/ui/lint/lint-missing-copy-implementations-allow.rs
Normal file
35
src/test/ui/lint/lint-missing-copy-implementations-allow.rs
Normal file
@ -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<Self::Item> {
|
||||
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() {}
|
9
src/test/ui/on-unimplemented/sum.rs
Normal file
9
src/test/ui/on-unimplemented/sum.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// <https://github.com/rust-lang/rust/issues/105184>
|
||||
|
||||
fn main() {
|
||||
vec![(), ()].iter().sum::<i32>();
|
||||
//~^ ERROR
|
||||
|
||||
vec![(), ()].iter().product::<i32>();
|
||||
//~^ ERROR
|
||||
}
|
39
src/test/ui/on-unimplemented/sum.stderr
Normal file
39
src/test/ui/on-unimplemented/sum.stderr
Normal file
@ -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::<i32>();
|
||||
| ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call
|
||||
| |
|
||||
| value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
|
||||
|
|
||||
= help: the trait `Sum<&()>` is not implemented for `i32`
|
||||
= help: the following other types implement trait `Sum<A>`:
|
||||
<i32 as Sum<&'a i32>>
|
||||
<i32 as Sum>
|
||||
note: required by a bound in `std::iter::Iterator::sum`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
LL | S: Sum<Self::Item>,
|
||||
| ^^^^^^^^^^^^^^^ 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::<i32>();
|
||||
| ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
|
||||
| |
|
||||
| value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
|
||||
|
|
||||
= help: the trait `Product<&()>` is not implemented for `i32`
|
||||
= help: the following other types implement trait `Product<A>`:
|
||||
<i32 as Product<&'a i32>>
|
||||
<i32 as Product>
|
||||
note: required by a bound in `std::iter::Iterator::product`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
|
||||
LL | P: Product<Self::Item>,
|
||||
| ^^^^^^^^^^^^^^^^^^^ 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`.
|
@ -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() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user