mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #65598 - Centril:rollup-vc6ht2c, r=Centril
Rollup of 5 pull requests Successful merges: - #64007 (Add check for overlapping ranges to unreachable patterns lint) - #65192 (Use structured suggestion for restricting bounds) - #65226 (BTreeSet symmetric_difference & union optimized) - #65448 (rustc_codegen_ssa: remove some unnecessary Box special-casing.) - #65505 (Rc: value -> allocation) Failed merges: r? @ghost
This commit is contained in:
commit
c49187530d
@ -2,7 +2,7 @@
|
||||
// to TreeMap
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use core::cmp::Ordering::{Less, Greater, Equal};
|
||||
use core::cmp::{max, min};
|
||||
use core::fmt::{self, Debug};
|
||||
use core::iter::{Peekable, FromIterator, FusedIterator};
|
||||
@ -109,6 +109,77 @@ pub struct Range<'a, T: 'a> {
|
||||
iter: btree_map::Range<'a, T, ()>,
|
||||
}
|
||||
|
||||
/// Core of SymmetricDifference and Union.
|
||||
/// More efficient than btree.map.MergeIter,
|
||||
/// and crucially for SymmetricDifference, nexts() reports on both sides.
|
||||
#[derive(Clone)]
|
||||
struct MergeIterInner<I>
|
||||
where I: Iterator,
|
||||
I::Item: Copy,
|
||||
{
|
||||
a: I,
|
||||
b: I,
|
||||
peeked: Option<MergeIterPeeked<I>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum MergeIterPeeked<I: Iterator> {
|
||||
A(I::Item),
|
||||
B(I::Item),
|
||||
}
|
||||
|
||||
impl<I> MergeIterInner<I>
|
||||
where I: ExactSizeIterator + FusedIterator,
|
||||
I::Item: Copy + Ord,
|
||||
{
|
||||
fn new(a: I, b: I) -> Self {
|
||||
MergeIterInner { a, b, peeked: None }
|
||||
}
|
||||
|
||||
fn nexts(&mut self) -> (Option<I::Item>, Option<I::Item>) {
|
||||
let mut a_next = match self.peeked {
|
||||
Some(MergeIterPeeked::A(next)) => Some(next),
|
||||
_ => self.a.next(),
|
||||
};
|
||||
let mut b_next = match self.peeked {
|
||||
Some(MergeIterPeeked::B(next)) => Some(next),
|
||||
_ => self.b.next(),
|
||||
};
|
||||
let ord = match (a_next, b_next) {
|
||||
(None, None) => Equal,
|
||||
(_, None) => Less,
|
||||
(None, _) => Greater,
|
||||
(Some(a1), Some(b1)) => a1.cmp(&b1),
|
||||
};
|
||||
self.peeked = match ord {
|
||||
Less => b_next.take().map(MergeIterPeeked::B),
|
||||
Equal => None,
|
||||
Greater => a_next.take().map(MergeIterPeeked::A),
|
||||
};
|
||||
(a_next, b_next)
|
||||
}
|
||||
|
||||
fn lens(&self) -> (usize, usize) {
|
||||
match self.peeked {
|
||||
Some(MergeIterPeeked::A(_)) => (1 + self.a.len(), self.b.len()),
|
||||
Some(MergeIterPeeked::B(_)) => (self.a.len(), 1 + self.b.len()),
|
||||
_ => (self.a.len(), self.b.len()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Debug for MergeIterInner<I>
|
||||
where I: Iterator + Debug,
|
||||
I::Item: Copy + Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("MergeIterInner")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the difference of `BTreeSet`s.
|
||||
///
|
||||
/// This `struct` is created by the [`difference`] method on [`BTreeSet`].
|
||||
@ -120,6 +191,7 @@ pub struct Range<'a, T: 'a> {
|
||||
pub struct Difference<'a, T: 'a> {
|
||||
inner: DifferenceInner<'a, T>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum DifferenceInner<'a, T: 'a> {
|
||||
Stitch {
|
||||
// iterate all of self and some of other, spotting matches along the way
|
||||
@ -137,21 +209,7 @@ enum DifferenceInner<'a, T: 'a> {
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.inner {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter,
|
||||
other_iter,
|
||||
} => f
|
||||
.debug_tuple("Difference")
|
||||
.field(&self_iter)
|
||||
.field(&other_iter)
|
||||
.finish(),
|
||||
DifferenceInner::Search {
|
||||
self_iter,
|
||||
other_set: _,
|
||||
} => f.debug_tuple("Difference").field(&self_iter).finish(),
|
||||
DifferenceInner::Iterate(iter) => f.debug_tuple("Difference").field(&iter).finish(),
|
||||
}
|
||||
f.debug_tuple("Difference").field(&self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,18 +221,12 @@ impl<T: fmt::Debug> fmt::Debug for Difference<'_, T> {
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SymmetricDifference<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("SymmetricDifference")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
f.debug_tuple("SymmetricDifference").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,6 +241,7 @@ impl<T: fmt::Debug> fmt::Debug for SymmetricDifference<'_, T> {
|
||||
pub struct Intersection<'a, T: 'a> {
|
||||
inner: IntersectionInner<'a, T>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum IntersectionInner<'a, T: 'a> {
|
||||
Stitch {
|
||||
// iterate similarly sized sets jointly, spotting matches along the way
|
||||
@ -206,23 +259,7 @@ enum IntersectionInner<'a, T: 'a> {
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.inner {
|
||||
IntersectionInner::Stitch {
|
||||
a,
|
||||
b,
|
||||
} => f
|
||||
.debug_tuple("Intersection")
|
||||
.field(&a)
|
||||
.field(&b)
|
||||
.finish(),
|
||||
IntersectionInner::Search {
|
||||
small_iter,
|
||||
large_set: _,
|
||||
} => f.debug_tuple("Intersection").field(&small_iter).finish(),
|
||||
IntersectionInner::Answer(answer) => {
|
||||
f.debug_tuple("Intersection").field(&answer).finish()
|
||||
}
|
||||
}
|
||||
f.debug_tuple("Intersection").field(&self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,18 +271,12 @@ impl<T: fmt::Debug> fmt::Debug for Intersection<'_, T> {
|
||||
/// [`BTreeSet`]: struct.BTreeSet.html
|
||||
/// [`union`]: struct.BTreeSet.html#method.union
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Union<'a, T: 'a> {
|
||||
a: Peekable<Iter<'a, T>>,
|
||||
b: Peekable<Iter<'a, T>>,
|
||||
}
|
||||
pub struct Union<'a, T: 'a>(MergeIterInner<Iter<'a, T>>);
|
||||
|
||||
#[stable(feature = "collection_debug", since = "1.17.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Union<'_, T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Union")
|
||||
.field(&self.a)
|
||||
.field(&self.b)
|
||||
.finish()
|
||||
f.debug_tuple("Union").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,19 +386,16 @@ impl<T: Ord> BTreeSet<T> {
|
||||
self_iter.next_back();
|
||||
DifferenceInner::Iterate(self_iter)
|
||||
}
|
||||
_ => {
|
||||
if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
DifferenceInner::Search {
|
||||
self_iter: self.iter(),
|
||||
other_set: other,
|
||||
}
|
||||
} else {
|
||||
DifferenceInner::Stitch {
|
||||
self_iter: self.iter(),
|
||||
other_iter: other.iter().peekable(),
|
||||
}
|
||||
_ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
DifferenceInner::Search {
|
||||
self_iter: self.iter(),
|
||||
other_set: other,
|
||||
}
|
||||
}
|
||||
_ => DifferenceInner::Stitch {
|
||||
self_iter: self.iter(),
|
||||
other_iter: other.iter().peekable(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -396,10 +424,7 @@ impl<T: Ord> BTreeSet<T> {
|
||||
pub fn symmetric_difference<'a>(&'a self,
|
||||
other: &'a BTreeSet<T>)
|
||||
-> SymmetricDifference<'a, T> {
|
||||
SymmetricDifference {
|
||||
a: self.iter().peekable(),
|
||||
b: other.iter().peekable(),
|
||||
}
|
||||
SymmetricDifference(MergeIterInner::new(self.iter(), other.iter()))
|
||||
}
|
||||
|
||||
/// Visits the values representing the intersection,
|
||||
@ -447,24 +472,22 @@ impl<T: Ord> BTreeSet<T> {
|
||||
(Greater, _) | (_, Less) => IntersectionInner::Answer(None),
|
||||
(Equal, _) => IntersectionInner::Answer(Some(self_min)),
|
||||
(_, Equal) => IntersectionInner::Answer(Some(self_max)),
|
||||
_ => {
|
||||
if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
IntersectionInner::Search {
|
||||
small_iter: self.iter(),
|
||||
large_set: other,
|
||||
}
|
||||
} else if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
|
||||
IntersectionInner::Search {
|
||||
small_iter: other.iter(),
|
||||
large_set: self,
|
||||
}
|
||||
} else {
|
||||
IntersectionInner::Stitch {
|
||||
a: self.iter(),
|
||||
b: other.iter(),
|
||||
}
|
||||
_ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
IntersectionInner::Search {
|
||||
small_iter: self.iter(),
|
||||
large_set: other,
|
||||
}
|
||||
}
|
||||
_ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
|
||||
IntersectionInner::Search {
|
||||
small_iter: other.iter(),
|
||||
large_set: self,
|
||||
}
|
||||
}
|
||||
_ => IntersectionInner::Stitch {
|
||||
a: self.iter(),
|
||||
b: other.iter(),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -489,10 +512,7 @@ impl<T: Ord> BTreeSet<T> {
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
|
||||
Union {
|
||||
a: self.iter().peekable(),
|
||||
b: other.iter().peekable(),
|
||||
}
|
||||
Union(MergeIterInner::new(self.iter(), other.iter()))
|
||||
}
|
||||
|
||||
/// Clears the set, removing all values.
|
||||
@ -1166,15 +1186,6 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> {
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Range<'_, T> {}
|
||||
|
||||
/// Compares `x` and `y`, but return `short` if x is None and `long` if y is None
|
||||
fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering) -> Ordering {
|
||||
match (x, y) {
|
||||
(None, _) => short,
|
||||
(_, None) => long,
|
||||
(Some(x1), Some(y1)) => x1.cmp(y1),
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Difference<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
@ -1261,10 +1272,7 @@ impl<T: Ord> FusedIterator for Difference<'_, T> {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for SymmetricDifference<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
SymmetricDifference {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
SymmetricDifference(self.0.clone())
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -1273,19 +1281,19 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
|
||||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
loop {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
|
||||
Less => return self.a.next(),
|
||||
Equal => {
|
||||
self.a.next();
|
||||
self.b.next();
|
||||
}
|
||||
Greater => return self.b.next(),
|
||||
let (a_next, b_next) = self.0.nexts();
|
||||
if a_next.and(b_next).is_none() {
|
||||
return a_next.or(b_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(self.a.len() + self.b.len()))
|
||||
let (a_len, b_len) = self.0.lens();
|
||||
// No checked_add, because even if a and b refer to the same set,
|
||||
// and T is an empty type, the storage overhead of sets limits
|
||||
// the number of elements to less than half the range of usize.
|
||||
(0, Some(a_len + b_len))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1311,7 +1319,7 @@ impl<T> Clone for Intersection<'_, T> {
|
||||
small_iter: small_iter.clone(),
|
||||
large_set,
|
||||
},
|
||||
IntersectionInner::Answer(answer) => IntersectionInner::Answer(answer.clone()),
|
||||
IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1365,10 +1373,7 @@ impl<T: Ord> FusedIterator for Intersection<'_, T> {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for Union<'_, T> {
|
||||
fn clone(&self) -> Self {
|
||||
Union {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
Union(self.0.clone())
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -1376,19 +1381,13 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
|
||||
type Item = &'a T;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T> {
|
||||
match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
|
||||
Less => self.a.next(),
|
||||
Equal => {
|
||||
self.b.next();
|
||||
self.a.next()
|
||||
}
|
||||
Greater => self.b.next(),
|
||||
}
|
||||
let (a_next, b_next) = self.0.nexts();
|
||||
a_next.or(b_next)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let a_len = self.a.len();
|
||||
let b_len = self.b.len();
|
||||
let (a_len, b_len) = self.0.lens();
|
||||
// No checked_add - see SymmetricDifference::size_hint.
|
||||
(max(a_len, b_len), Some(a_len + b_len))
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,9 @@
|
||||
//!
|
||||
//! The type [`Rc<T>`][`Rc`] provides shared ownership of a value of type `T`,
|
||||
//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new
|
||||
//! pointer to the same value in the heap. When the last [`Rc`] pointer to a
|
||||
//! given value is destroyed, the pointed-to value is also destroyed.
|
||||
//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a
|
||||
//! given allocation is destroyed, the value stored in that allocation (often
|
||||
//! referred to as "inner value") is also dropped.
|
||||
//!
|
||||
//! Shared references in Rust disallow mutation by default, and [`Rc`]
|
||||
//! is no exception: you cannot generally obtain a mutable reference to
|
||||
@ -21,8 +22,10 @@
|
||||
//!
|
||||
//! The [`downgrade`][downgrade] method can be used to create a non-owning
|
||||
//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
|
||||
//! to an [`Rc`], but this will return [`None`] if the value has
|
||||
//! already been dropped.
|
||||
//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has
|
||||
//! already been dropped. In other words, `Weak` pointers do not keep the value
|
||||
//! inside the allocation alive; however, they *do* keep the allocation
|
||||
//! (the backing store for the inner value) alive.
|
||||
//!
|
||||
//! A cycle between [`Rc`] pointers will never be deallocated. For this reason,
|
||||
//! [`Weak`] is used to break cycles. For example, a tree could have strong
|
||||
@ -41,13 +44,13 @@
|
||||
//! Rc::downgrade(&my_rc);
|
||||
//! ```
|
||||
//!
|
||||
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the value may have
|
||||
//! already been destroyed.
|
||||
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the inner value may have
|
||||
//! already been dropped.
|
||||
//!
|
||||
//! # Cloning references
|
||||
//!
|
||||
//! Creating a new reference from an existing reference counted pointer is done using the
|
||||
//! `Clone` trait implemented for [`Rc<T>`][`Rc`] and [`Weak<T>`][`Weak`].
|
||||
//! Creating a new reference to the same allocation as an existing reference counted pointer
|
||||
//! is done using the `Clone` trait implemented for [`Rc<T>`][`Rc`] and [`Weak<T>`][`Weak`].
|
||||
//!
|
||||
//! ```
|
||||
//! use std::rc::Rc;
|
||||
@ -93,7 +96,7 @@
|
||||
//! );
|
||||
//!
|
||||
//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc<Owner>`
|
||||
//! // value gives us a new pointer to the same `Owner` value, incrementing
|
||||
//! // gives us a new pointer to the same `Owner` allocation, incrementing
|
||||
//! // the reference count in the process.
|
||||
//! let gadget1 = Gadget {
|
||||
//! id: 1,
|
||||
@ -110,8 +113,8 @@
|
||||
//! // Despite dropping `gadget_owner`, we're still able to print out the name
|
||||
//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a
|
||||
//! // single `Rc<Owner>`, not the `Owner` it points to. As long as there are
|
||||
//! // other `Rc<Owner>` values pointing at the same `Owner`, it will remain
|
||||
//! // allocated. The field projection `gadget1.owner.name` works because
|
||||
//! // other `Rc<Owner>` pointing at the same `Owner` allocation, it will remain
|
||||
//! // live. The field projection `gadget1.owner.name` works because
|
||||
//! // `Rc<Owner>` automatically dereferences to `Owner`.
|
||||
//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
|
||||
//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
|
||||
@ -124,9 +127,9 @@
|
||||
//!
|
||||
//! If our requirements change, and we also need to be able to traverse from
|
||||
//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner`
|
||||
//! to `Gadget` introduces a cycle between the values. This means that their
|
||||
//! reference counts can never reach 0, and the values will remain allocated
|
||||
//! forever: a memory leak. In order to get around this, we can use [`Weak`]
|
||||
//! to `Gadget` introduces a cycle. This means that their
|
||||
//! reference counts can never reach 0, and the allocation will never be destroyed:
|
||||
//! a memory leak. In order to get around this, we can use [`Weak`]
|
||||
//! pointers.
|
||||
//!
|
||||
//! Rust actually makes it somewhat difficult to produce this loop in the first
|
||||
@ -193,10 +196,10 @@
|
||||
//! for gadget_weak in gadget_owner.gadgets.borrow().iter() {
|
||||
//!
|
||||
//! // `gadget_weak` is a `Weak<Gadget>`. Since `Weak` pointers can't
|
||||
//! // guarantee the value is still allocated, we need to call
|
||||
//! // guarantee the allocation still exists, we need to call
|
||||
//! // `upgrade`, which returns an `Option<Rc<Gadget>>`.
|
||||
//! //
|
||||
//! // In this case we know the value still exists, so we simply
|
||||
//! // In this case we know the allocation still exists, so we simply
|
||||
//! // `unwrap` the `Option`. In a more complicated program, you might
|
||||
//! // need graceful error handling for a `None` result.
|
||||
//!
|
||||
@ -365,7 +368,7 @@ impl<T> Rc<T> {
|
||||
unsafe { Pin::new_unchecked(Rc::new(value)) }
|
||||
}
|
||||
|
||||
/// Returns the contained value, if the `Rc` has exactly one strong reference.
|
||||
/// Returns the inner value, if the `Rc` has exactly one strong reference.
|
||||
///
|
||||
/// Otherwise, an [`Err`][result] is returned with the same `Rc` that was
|
||||
/// passed in.
|
||||
@ -446,7 +449,7 @@ impl<T> Rc<mem::MaybeUninit<T>> {
|
||||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
@ -485,7 +488,7 @@ impl<T> Rc<[mem::MaybeUninit<T>]> {
|
||||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
@ -604,7 +607,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) }
|
||||
}
|
||||
|
||||
/// Creates a new [`Weak`][weak] pointer to this value.
|
||||
/// Creates a new [`Weak`][weak] pointer to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
@ -625,7 +628,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
Weak { ptr: this.ptr }
|
||||
}
|
||||
|
||||
/// Gets the number of [`Weak`][weak] pointers to this value.
|
||||
/// Gets the number of [`Weak`][weak] pointers to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
@ -645,7 +648,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
this.weak() - 1
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Rc`) pointers to this value.
|
||||
/// Gets the number of strong (`Rc`) pointers to this allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -664,7 +667,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
}
|
||||
|
||||
/// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to
|
||||
/// this inner value.
|
||||
/// this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
#[inline]
|
||||
@ -672,14 +675,14 @@ impl<T: ?Sized> Rc<T> {
|
||||
Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value, if there are
|
||||
/// no other `Rc` or [`Weak`][weak] pointers to the same value.
|
||||
/// Returns a mutable reference into the given `Rc`, if there are
|
||||
/// no other `Rc` or [`Weak`][weak] pointers to the same allocation.
|
||||
///
|
||||
/// Returns [`None`] otherwise, because it is not safe to
|
||||
/// mutate a shared value.
|
||||
///
|
||||
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
|
||||
/// the inner value when it's shared.
|
||||
/// the inner value when there are other pointers.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
@ -710,7 +713,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value,
|
||||
/// Returns a mutable reference into the given `Rc`,
|
||||
/// without any check.
|
||||
///
|
||||
/// See also [`get_mut`], which is safe and does appropriate checks.
|
||||
@ -719,7 +722,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced
|
||||
/// Any other `Rc` or [`Weak`] pointers to the same allocation must not be dereferenced
|
||||
/// for the duration of the returned borrow.
|
||||
/// This is trivially the case if no such pointers exist,
|
||||
/// for example immediately after `Rc::new`.
|
||||
@ -745,8 +748,8 @@ impl<T: ?Sized> Rc<T> {
|
||||
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_eq", since = "1.17.0")]
|
||||
/// Returns `true` if the two `Rc`s point to the same value (not
|
||||
/// just values that compare as equal).
|
||||
/// Returns `true` if the two `Rc`s point to the same allocation
|
||||
/// (in a vein similar to [`ptr::eq`]).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -760,6 +763,8 @@ impl<T: ?Sized> Rc<T> {
|
||||
/// assert!(Rc::ptr_eq(&five, &same_five));
|
||||
/// assert!(!Rc::ptr_eq(&five, &other_five));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
this.ptr.as_ptr() == other.ptr.as_ptr()
|
||||
}
|
||||
@ -768,12 +773,12 @@ impl<T: ?Sized> Rc<T> {
|
||||
impl<T: Clone> Rc<T> {
|
||||
/// Makes a mutable reference into the given `Rc`.
|
||||
///
|
||||
/// If there are other `Rc` pointers to the same value, then `make_mut` will
|
||||
/// [`clone`] the inner value to ensure unique ownership. This is also
|
||||
/// If there are other `Rc` pointers to the same allocation, then `make_mut` will
|
||||
/// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also
|
||||
/// referred to as clone-on-write.
|
||||
///
|
||||
/// If there are no other `Rc` pointers to this value, then [`Weak`]
|
||||
/// pointers to this value will be disassociated.
|
||||
/// If there are no other `Rc` pointers to this allocation, then [`Weak`]
|
||||
/// pointers to this allocation will be disassociated.
|
||||
///
|
||||
/// See also [`get_mut`], which will fail rather than cloning.
|
||||
///
|
||||
@ -794,7 +799,7 @@ impl<T: Clone> Rc<T> {
|
||||
/// *Rc::make_mut(&mut data) += 1; // Won't clone anything
|
||||
/// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything
|
||||
///
|
||||
/// // Now `data` and `other_data` point to different values.
|
||||
/// // Now `data` and `other_data` point to different allocations.
|
||||
/// assert_eq!(*data, 8);
|
||||
/// assert_eq!(*other_data, 12);
|
||||
/// ```
|
||||
@ -837,7 +842,7 @@ impl<T: Clone> Rc<T> {
|
||||
// returned is the *only* pointer that will ever be returned to T. Our
|
||||
// reference count is guaranteed to be 1 at this point, and we required
|
||||
// the `Rc<T>` itself to be `mut`, so we're returning the only possible
|
||||
// reference to the inner value.
|
||||
// reference to the allocation.
|
||||
unsafe {
|
||||
&mut this.ptr.as_mut().value
|
||||
}
|
||||
@ -878,7 +883,7 @@ impl Rc<dyn Any> {
|
||||
|
||||
impl<T: ?Sized> Rc<T> {
|
||||
/// Allocates an `RcBox<T>` with sufficient space for
|
||||
/// a possibly-unsized value where the value has the layout provided.
|
||||
/// a possibly-unsized inner value where the value has the layout provided.
|
||||
///
|
||||
/// The function `mem_to_rcbox` is called with the data pointer
|
||||
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
|
||||
@ -908,7 +913,7 @@ impl<T: ?Sized> Rc<T> {
|
||||
inner
|
||||
}
|
||||
|
||||
/// Allocates an `RcBox<T>` with sufficient space for an unsized value
|
||||
/// Allocates an `RcBox<T>` with sufficient space for an unsized inner value
|
||||
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
|
||||
// Allocate for the `RcBox<T>` using the given value.
|
||||
Self::allocate_for_layout(
|
||||
@ -1111,7 +1116,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> {
|
||||
impl<T: ?Sized> Clone for Rc<T> {
|
||||
/// Makes a clone of the `Rc` pointer.
|
||||
///
|
||||
/// This creates another pointer to the same inner value, increasing the
|
||||
/// This creates another pointer to the same allocation, increasing the
|
||||
/// strong reference count.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1172,6 +1177,8 @@ impl<T: ?Sized + PartialEq> RcEqIdent<T> for Rc<T> {
|
||||
/// store large values, that are slow to clone, but also heavy to check for equality, causing this
|
||||
/// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to
|
||||
/// the same value, than two `&T`s.
|
||||
///
|
||||
/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> {
|
||||
#[inline]
|
||||
@ -1189,9 +1196,11 @@ impl<T: ?Sized + Eq> RcEqIdent<T> for Rc<T> {
|
||||
impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
|
||||
/// Equality for two `Rc`s.
|
||||
///
|
||||
/// Two `Rc`s are equal if their inner values are equal.
|
||||
/// Two `Rc`s are equal if their inner values are equal, even if they are
|
||||
/// stored in different allocation.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Rc`s that point to the same value are
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Rc`s that point to the same allocation are
|
||||
/// always equal.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1212,7 +1221,8 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
|
||||
///
|
||||
/// Two `Rc`s are unequal if their inner values are unequal.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Rc`s that point to the same value are
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Rc`s that point to the same allocation are
|
||||
/// never unequal.
|
||||
///
|
||||
/// # Examples
|
||||
@ -1541,17 +1551,18 @@ impl<'a, T: 'a + Clone> RcFromIter<&'a T, slice::Iter<'a, T>> for Rc<[T]> {
|
||||
}
|
||||
|
||||
/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
|
||||
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
|
||||
///
|
||||
/// Since a `Weak` reference does not count towards ownership, it will not
|
||||
/// prevent the inner value from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present and may return [`None`]
|
||||
/// when [`upgrade`]d.
|
||||
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present. Thus it may return [`None`]
|
||||
/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation
|
||||
/// itself (the backing store) from being deallocated.
|
||||
///
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the value
|
||||
/// within [`Rc`] without extending its lifetime. It is also used to prevent
|
||||
/// circular references between [`Rc`] pointers, since mutual owning references
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the allocation
|
||||
/// managed by [`Rc`] without preventing its inner value from being dropped. It is also used to
|
||||
/// prevent circular references between [`Rc`] pointers, since mutual owning references
|
||||
/// would never allow either [`Rc`] to be dropped. For example, a tree could
|
||||
/// have strong [`Rc`] pointers from parent nodes to children, and `Weak`
|
||||
/// pointers from children back to their parents.
|
||||
@ -1750,10 +1761,10 @@ pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Weak<T> {
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending
|
||||
/// the lifetime of the value if successful.
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying
|
||||
/// dropping of the inner value if successful.
|
||||
///
|
||||
/// Returns [`None`] if the value has since been dropped.
|
||||
/// Returns [`None`] if the inner value has since been dropped.
|
||||
///
|
||||
/// [`Rc`]: struct.Rc.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html
|
||||
@ -1787,7 +1798,7 @@ impl<T: ?Sized> Weak<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Rc`) pointers pointing to this value.
|
||||
/// Gets the number of strong (`Rc`) pointers pointing to this allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return 0.
|
||||
///
|
||||
@ -1801,11 +1812,11 @@ impl<T: ?Sized> Weak<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the number of `Weak` pointers pointing to this value.
|
||||
/// Gets the number of `Weak` pointers pointing to this allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return `None`. If
|
||||
/// not, the returned value is at least 1, since `self` still points to the
|
||||
/// value.
|
||||
/// allocation.
|
||||
///
|
||||
/// [`Weak::new`]: #method.new
|
||||
#[unstable(feature = "weak_counts", issue = "57977")]
|
||||
@ -1830,14 +1841,14 @@ impl<T: ?Sized> Weak<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the two `Weak`s point to the same value (not just
|
||||
/// values that compare as equal), or if both don't point to any value
|
||||
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
|
||||
/// [`ptr::eq`]), or if both don't point to any allocation
|
||||
/// (because they were created with `Weak::new()`).
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Since this compares pointers it means that `Weak::new()` will equal each
|
||||
/// other, even though they don't point to any value.
|
||||
/// other, even though they don't point to any allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1869,6 +1880,8 @@ impl<T: ?Sized> Weak<T> {
|
||||
/// let third = Rc::downgrade(&third_rc);
|
||||
/// assert!(!first.ptr_eq(&third));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
#[inline]
|
||||
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
|
||||
pub fn ptr_eq(&self, other: &Self) -> bool {
|
||||
@ -1918,7 +1931,7 @@ impl<T: ?Sized> Drop for Weak<T> {
|
||||
|
||||
#[stable(feature = "rc_weak", since = "1.4.0")]
|
||||
impl<T: ?Sized> Clone for Weak<T> {
|
||||
/// Makes a clone of the `Weak` pointer that points to the same value.
|
||||
/// Makes a clone of the `Weak` pointer that points to the same allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -45,10 +45,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
///
|
||||
/// The type `Arc<T>` provides shared ownership of a value of type `T`,
|
||||
/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces
|
||||
/// a new `Arc` instance, which points to the same value on the heap as the
|
||||
/// a new `Arc` instance, which points to the same allocation on the heap as the
|
||||
/// source `Arc`, while increasing a reference count. When the last `Arc`
|
||||
/// pointer to a given value is destroyed, the pointed-to value is also
|
||||
/// destroyed.
|
||||
/// pointer to a given allocation is destroyed, the value stored in that allocation (often
|
||||
/// referred to as "inner value") is also dropped.
|
||||
///
|
||||
/// Shared references in Rust disallow mutation by default, and `Arc` is no
|
||||
/// exception: you cannot generally obtain a mutable reference to something
|
||||
@ -61,7 +61,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference
|
||||
/// counting. This means that it is thread-safe. The disadvantage is that
|
||||
/// atomic operations are more expensive than ordinary memory accesses. If you
|
||||
/// are not sharing reference-counted values between threads, consider using
|
||||
/// are not sharing reference-counted allocations between threads, consider using
|
||||
/// [`Rc<T>`] for lower overhead. [`Rc<T>`] is a safe default, because the
|
||||
/// compiler will catch any attempt to send an [`Rc<T>`] between threads.
|
||||
/// However, a library might choose `Arc<T>` in order to give library consumers
|
||||
@ -85,8 +85,10 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
///
|
||||
/// The [`downgrade`][downgrade] method can be used to create a non-owning
|
||||
/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
|
||||
/// to an `Arc`, but this will return [`None`] if the value has already been
|
||||
/// dropped.
|
||||
/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has
|
||||
/// already been dropped. In other words, `Weak` pointers do not keep the value
|
||||
/// inside the allocation alive; however, they *do* keep the allocation
|
||||
/// (the backing store for the value) alive.
|
||||
///
|
||||
/// A cycle between `Arc` pointers will never be deallocated. For this reason,
|
||||
/// [`Weak`][weak] is used to break cycles. For example, a tree could have
|
||||
@ -121,8 +123,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||
/// Arc::downgrade(&my_arc);
|
||||
/// ```
|
||||
///
|
||||
/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the value may have
|
||||
/// already been destroyed.
|
||||
/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the inner value may have
|
||||
/// already been dropped.
|
||||
///
|
||||
/// [arc]: struct.Arc.html
|
||||
/// [weak]: struct.Weak.html
|
||||
@ -221,17 +223,18 @@ impl<T: ?Sized> Arc<T> {
|
||||
}
|
||||
|
||||
/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
|
||||
/// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
|
||||
/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
|
||||
///
|
||||
/// Since a `Weak` reference does not count towards ownership, it will not
|
||||
/// prevent the inner value from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present and may return [`None`]
|
||||
/// when [`upgrade`]d.
|
||||
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
|
||||
/// guarantees about the value still being present. Thus it may return [`None`]
|
||||
/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation
|
||||
/// itself (the backing store) from being deallocated.
|
||||
///
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the value
|
||||
/// within [`Arc`] without extending its lifetime. It is also used to prevent
|
||||
/// circular references between [`Arc`] pointers, since mutual owning references
|
||||
/// A `Weak` pointer is useful for keeping a temporary reference to the allocation
|
||||
/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to
|
||||
/// prevent circular references between [`Arc`] pointers, since mutual owning references
|
||||
/// would never allow either [`Arc`] to be dropped. For example, a tree could
|
||||
/// have strong [`Arc`] pointers from parent nodes to children, and `Weak`
|
||||
/// pointers from children back to their parents.
|
||||
@ -345,7 +348,7 @@ impl<T> Arc<T> {
|
||||
unsafe { Pin::new_unchecked(Arc::new(data)) }
|
||||
}
|
||||
|
||||
/// Returns the contained value, if the `Arc` has exactly one strong reference.
|
||||
/// Returns the inner value, if the `Arc` has exactly one strong reference.
|
||||
///
|
||||
/// Otherwise, an [`Err`][result] is returned with the same `Arc` that was
|
||||
/// passed in.
|
||||
@ -426,7 +429,7 @@ impl<T> Arc<mem::MaybeUninit<T>> {
|
||||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
@ -465,7 +468,7 @@ impl<T> Arc<[mem::MaybeUninit<T>]> {
|
||||
/// # Safety
|
||||
///
|
||||
/// As with [`MaybeUninit::assume_init`],
|
||||
/// it is up to the caller to guarantee that the value
|
||||
/// it is up to the caller to guarantee that the inner value
|
||||
/// really is in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized
|
||||
/// causes immediate undefined behavior.
|
||||
@ -584,7 +587,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) }
|
||||
}
|
||||
|
||||
/// Creates a new [`Weak`][weak] pointer to this value.
|
||||
/// Creates a new [`Weak`][weak] pointer to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
@ -628,7 +631,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the number of [`Weak`][weak] pointers to this value.
|
||||
/// Gets the number of [`Weak`][weak] pointers to this allocation.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
///
|
||||
@ -659,7 +662,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
if cnt == usize::MAX { 0 } else { cnt - 1 }
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Arc`) pointers to this value.
|
||||
/// Gets the number of strong (`Arc`) pointers to this allocation.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
@ -710,8 +713,8 @@ impl<T: ?Sized> Arc<T> {
|
||||
|
||||
#[inline]
|
||||
#[stable(feature = "ptr_eq", since = "1.17.0")]
|
||||
/// Returns `true` if the two `Arc`s point to the same value (not
|
||||
/// just values that compare as equal).
|
||||
/// Returns `true` if the two `Arc`s point to the same allocation
|
||||
/// (in a vein similar to [`ptr::eq`]).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -725,6 +728,8 @@ impl<T: ?Sized> Arc<T> {
|
||||
/// assert!(Arc::ptr_eq(&five, &same_five));
|
||||
/// assert!(!Arc::ptr_eq(&five, &other_five));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
||||
this.ptr.as_ptr() == other.ptr.as_ptr()
|
||||
}
|
||||
@ -732,7 +737,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
/// Allocates an `ArcInner<T>` with sufficient space for
|
||||
/// a possibly-unsized value where the value has the layout provided.
|
||||
/// a possibly-unsized inner value where the value has the layout provided.
|
||||
///
|
||||
/// The function `mem_to_arcinner` is called with the data pointer
|
||||
/// and must return back a (potentially fat)-pointer for the `ArcInner<T>`.
|
||||
@ -761,7 +766,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
inner
|
||||
}
|
||||
|
||||
/// Allocates an `ArcInner<T>` with sufficient space for an unsized value.
|
||||
/// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
|
||||
unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
|
||||
// Allocate for the `ArcInner<T>` using the given value.
|
||||
Self::allocate_for_layout(
|
||||
@ -903,7 +908,7 @@ impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
|
||||
impl<T: ?Sized> Clone for Arc<T> {
|
||||
/// Makes a clone of the `Arc` pointer.
|
||||
///
|
||||
/// This creates another pointer to the same inner value, increasing the
|
||||
/// This creates another pointer to the same allocation, increasing the
|
||||
/// strong reference count.
|
||||
///
|
||||
/// # Examples
|
||||
@ -965,15 +970,19 @@ impl<T: ?Sized> Receiver for Arc<T> {}
|
||||
impl<T: Clone> Arc<T> {
|
||||
/// Makes a mutable reference into the given `Arc`.
|
||||
///
|
||||
/// If there are other `Arc` or [`Weak`][weak] pointers to the same value,
|
||||
/// then `make_mut` will invoke [`clone`][clone] on the inner value to
|
||||
/// ensure unique ownership. This is also referred to as clone-on-write.
|
||||
/// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation,
|
||||
/// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value
|
||||
/// to ensure unique ownership. This is also referred to as clone-on-write.
|
||||
///
|
||||
/// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates
|
||||
/// any remaining `Weak` pointers.
|
||||
///
|
||||
/// See also [`get_mut`][get_mut], which will fail rather than cloning.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
|
||||
/// [get_mut]: struct.Arc.html#method.get_mut
|
||||
/// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -988,7 +997,7 @@ impl<T: Clone> Arc<T> {
|
||||
/// *Arc::make_mut(&mut data) += 1; // Won't clone anything
|
||||
/// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
|
||||
///
|
||||
/// // Now `data` and `other_data` point to different values.
|
||||
/// // Now `data` and `other_data` point to different allocations.
|
||||
/// assert_eq!(*data, 8);
|
||||
/// assert_eq!(*other_data, 12);
|
||||
/// ```
|
||||
@ -1048,14 +1057,14 @@ impl<T: Clone> Arc<T> {
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Arc<T> {
|
||||
/// Returns a mutable reference to the inner value, if there are
|
||||
/// no other `Arc` or [`Weak`][weak] pointers to the same value.
|
||||
/// Returns a mutable reference into the given `Arc`, if there are
|
||||
/// no other `Arc` or [`Weak`][weak] pointers to the same allocation.
|
||||
///
|
||||
/// Returns [`None`][option] otherwise, because it is not safe to
|
||||
/// mutate a shared value.
|
||||
///
|
||||
/// See also [`make_mut`][make_mut], which will [`clone`][clone]
|
||||
/// the inner value when it's shared.
|
||||
/// the inner value when there are other pointers.
|
||||
///
|
||||
/// [weak]: struct.Weak.html
|
||||
/// [option]: ../../std/option/enum.Option.html
|
||||
@ -1091,7 +1100,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner value,
|
||||
/// Returns a mutable reference into the given `Arc`,
|
||||
/// without any check.
|
||||
///
|
||||
/// See also [`get_mut`], which is safe and does appropriate checks.
|
||||
@ -1100,7 +1109,7 @@ impl<T: ?Sized> Arc<T> {
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced
|
||||
/// Any other `Arc` or [`Weak`] pointers to the same allocation must not be dereferenced
|
||||
/// for the duration of the returned borrow.
|
||||
/// This is trivially the case if no such pointers exist,
|
||||
/// for example immediately after `Arc::new`.
|
||||
@ -1424,10 +1433,10 @@ impl<T> Weak<T> {
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Weak<T> {
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending
|
||||
/// the lifetime of the value if successful.
|
||||
/// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
|
||||
/// dropping of the inner value if successful.
|
||||
///
|
||||
/// Returns [`None`] if the value has since been dropped.
|
||||
/// Returns [`None`] if the inner value has since been dropped.
|
||||
///
|
||||
/// [`Arc`]: struct.Arc.html
|
||||
/// [`None`]: ../../std/option/enum.Option.html#variant.None
|
||||
@ -1482,7 +1491,7 @@ impl<T: ?Sized> Weak<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the number of strong (`Arc`) pointers pointing to this value.
|
||||
/// Gets the number of strong (`Arc`) pointers pointing to this allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return 0.
|
||||
///
|
||||
@ -1497,17 +1506,17 @@ impl<T: ?Sized> Weak<T> {
|
||||
}
|
||||
|
||||
/// Gets an approximation of the number of `Weak` pointers pointing to this
|
||||
/// value.
|
||||
/// allocation.
|
||||
///
|
||||
/// If `self` was created using [`Weak::new`], this will return 0. If not,
|
||||
/// the returned value is at least 1, since `self` still points to the
|
||||
/// value.
|
||||
/// allocation.
|
||||
///
|
||||
/// # Accuracy
|
||||
///
|
||||
/// Due to implementation details, the returned value can be off by 1 in
|
||||
/// either direction when other threads are manipulating any `Arc`s or
|
||||
/// `Weak`s pointing to the same value.
|
||||
/// `Weak`s pointing to the same allocation.
|
||||
///
|
||||
/// [`Weak::new`]: #method.new
|
||||
#[unstable(feature = "weak_counts", issue = "57977")]
|
||||
@ -1548,14 +1557,14 @@ impl<T: ?Sized> Weak<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the two `Weak`s point to the same value (not just
|
||||
/// values that compare as equal), or if both don't point to any value
|
||||
/// Returns `true` if the two `Weak`s point to the same allocation (similar to
|
||||
/// [`ptr::eq`]), or if both don't point to any allocation
|
||||
/// (because they were created with `Weak::new()`).
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Since this compares pointers it means that `Weak::new()` will equal each
|
||||
/// other, even though they don't point to any value.
|
||||
/// other, even though they don't point to any allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1587,6 +1596,8 @@ impl<T: ?Sized> Weak<T> {
|
||||
/// let third = Arc::downgrade(&third_rc);
|
||||
/// assert!(!first.ptr_eq(&third));
|
||||
/// ```
|
||||
///
|
||||
/// [`ptr::eq`]: ../../std/ptr/fn.eq.html
|
||||
#[inline]
|
||||
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
|
||||
pub fn ptr_eq(&self, other: &Self) -> bool {
|
||||
@ -1596,7 +1607,7 @@ impl<T: ?Sized> Weak<T> {
|
||||
|
||||
#[stable(feature = "arc_weak", since = "1.4.0")]
|
||||
impl<T: ?Sized> Clone for Weak<T> {
|
||||
/// Makes a clone of the `Weak` pointer that points to the same value.
|
||||
/// Makes a clone of the `Weak` pointer that points to the same allocation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1726,6 +1737,8 @@ impl<T: ?Sized + PartialEq> ArcEqIdent<T> for Arc<T> {
|
||||
/// store large values, that are slow to clone, but also heavy to check for equality, causing this
|
||||
/// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to
|
||||
/// the same value, than two `&T`s.
|
||||
///
|
||||
/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> {
|
||||
#[inline]
|
||||
@ -1743,10 +1756,11 @@ impl<T: ?Sized + Eq> ArcEqIdent<T> for Arc<T> {
|
||||
impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
|
||||
/// Equality for two `Arc`s.
|
||||
///
|
||||
/// Two `Arc`s are equal if their inner values are equal.
|
||||
/// Two `Arc`s are equal if their inner values are equal, even if they are
|
||||
/// stored in different allocation.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Arc`s that point to the same value are
|
||||
/// always equal.
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Arc`s that point to the same allocation are always equal.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1766,8 +1780,8 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
|
||||
///
|
||||
/// Two `Arc`s are unequal if their inner values are unequal.
|
||||
///
|
||||
/// If `T` also implements `Eq`, two `Arc`s that point to the same value are
|
||||
/// never unequal.
|
||||
/// If `T` also implements `Eq` (implying reflexivity of equality),
|
||||
/// two `Arc`s that point to the same value are never unequal.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -221,6 +221,18 @@ fn test_symmetric_difference() {
|
||||
&[-2, 1, 5, 11, 14, 22]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_symmetric_difference_size_hint() {
|
||||
let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
|
||||
let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
|
||||
let mut iter = x.symmetric_difference(&y);
|
||||
assert_eq!(iter.size_hint(), (0, Some(5)));
|
||||
assert_eq!(iter.next(), Some(&1));
|
||||
assert_eq!(iter.size_hint(), (0, Some(4)));
|
||||
assert_eq!(iter.next(), Some(&3));
|
||||
assert_eq!(iter.size_hint(), (0, Some(1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union() {
|
||||
fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
|
||||
@ -235,6 +247,18 @@ fn test_union() {
|
||||
&[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_union_size_hint() {
|
||||
let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
|
||||
let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
|
||||
let mut iter = x.union(&y);
|
||||
assert_eq!(iter.size_hint(), (3, Some(5)));
|
||||
assert_eq!(iter.next(), Some(&1));
|
||||
assert_eq!(iter.size_hint(), (2, Some(4)));
|
||||
assert_eq!(iter.next(), Some(&2));
|
||||
assert_eq!(iter.size_hint(), (1, Some(2)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Only tests the simple function definition with respect to intersection
|
||||
fn test_is_disjoint() {
|
||||
@ -244,7 +268,7 @@ fn test_is_disjoint() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Also tests the trivial function definition of is_superset
|
||||
// Also implicitly tests the trivial function definition of is_superset
|
||||
fn test_is_subset() {
|
||||
fn is_subset(a: &[i32], b: &[i32]) -> bool {
|
||||
let set_a = a.iter().collect::<BTreeSet<_>>();
|
||||
|
@ -669,6 +669,12 @@ impl WhereClause {
|
||||
Some(self.span)
|
||||
}
|
||||
}
|
||||
|
||||
/// The `WhereClause` under normal circumstances points at either the predicates or the empty
|
||||
/// space where the `where` clause should be. Only of use for diagnostic suggestions.
|
||||
pub fn span_for_predicates_or_empty_place(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
}
|
||||
|
||||
/// A single predicate in a where-clause.
|
||||
@ -989,6 +995,15 @@ pub enum RangeEnd {
|
||||
Excluded,
|
||||
}
|
||||
|
||||
impl fmt::Display for RangeEnd {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
RangeEnd::Included => "..=",
|
||||
RangeEnd::Excluded => "..",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub enum PatKind {
|
||||
/// Represents a wildcard pattern (i.e., `_`).
|
||||
|
@ -80,6 +80,12 @@ declare_lint! {
|
||||
"detects unreachable patterns"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub OVERLAPPING_PATTERNS,
|
||||
Warn,
|
||||
"detects overlapping patterns"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub UNUSED_MACROS,
|
||||
Warn,
|
||||
@ -423,6 +429,7 @@ declare_lint_pass! {
|
||||
DEAD_CODE,
|
||||
UNREACHABLE_CODE,
|
||||
UNREACHABLE_PATTERNS,
|
||||
OVERLAPPING_PATTERNS,
|
||||
UNUSED_MACROS,
|
||||
WARNINGS,
|
||||
UNUSED_FEATURES,
|
||||
|
@ -715,8 +715,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
// these notes will often be of the form
|
||||
// "the type `T` can't be frobnicated"
|
||||
// which is somewhat confusing.
|
||||
err.help(&format!("consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate()));
|
||||
self.suggest_restricting_param_bound(
|
||||
&mut err,
|
||||
&trait_ref,
|
||||
obligation.cause.body_id,
|
||||
);
|
||||
} else {
|
||||
if !have_alt_message {
|
||||
// Can't show anything else useful, try to find similar impls.
|
||||
@ -960,6 +963,175 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn suggest_restricting_param_bound(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
trait_ref: &ty::PolyTraitRef<'_>,
|
||||
body_id: hir::HirId,
|
||||
) {
|
||||
let self_ty = trait_ref.self_ty();
|
||||
let (param_ty, projection) = match &self_ty.kind {
|
||||
ty::Param(_) => (true, None),
|
||||
ty::Projection(projection) => (false, Some(projection)),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let mut suggest_restriction = |generics: &hir::Generics, msg| {
|
||||
let span = generics.where_clause.span_for_predicates_or_empty_place();
|
||||
if !span.from_expansion() && span.desugaring_kind().is_none() {
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
|
||||
&format!("consider further restricting {}", msg),
|
||||
format!(
|
||||
"{} {} ",
|
||||
if !generics.where_clause.predicates.is_empty() {
|
||||
","
|
||||
} else {
|
||||
" where"
|
||||
},
|
||||
trait_ref.to_predicate(),
|
||||
),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
|
||||
// don't suggest `T: Sized + ?Sized`.
|
||||
let mut hir_id = body_id;
|
||||
while let Some(node) = self.tcx.hir().find(hir_id) {
|
||||
match node {
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Method(..), ..
|
||||
}) if param_ty && self_ty == self.tcx.types.self_param => {
|
||||
// Restricting `Self` for a single method.
|
||||
suggest_restriction(&generics, "`Self`");
|
||||
return;
|
||||
}
|
||||
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, generics, _), ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
generics,
|
||||
kind: hir::TraitItemKind::Method(..), ..
|
||||
}) |
|
||||
hir::Node::ImplItem(hir::ImplItem {
|
||||
generics,
|
||||
kind: hir::ImplItemKind::Method(..), ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, _, _), ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_, _, _, generics, ..), ..
|
||||
}) if projection.is_some() => {
|
||||
// Missing associated type bound.
|
||||
suggest_restriction(&generics, "the associated type");
|
||||
return;
|
||||
}
|
||||
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Trait(_, _, generics, ..), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Fn(_, _, generics, _), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::TyAlias(_, generics), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::TraitAlias(generics, _), span, ..
|
||||
}) |
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, ..
|
||||
}) |
|
||||
hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) |
|
||||
hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
|
||||
if param_ty => {
|
||||
// Missing generic type parameter bound.
|
||||
let restrict_msg = "consider further restricting this bound";
|
||||
let param_name = self_ty.to_string();
|
||||
for param in generics.params.iter().filter(|p| {
|
||||
¶m_name == std::convert::AsRef::<str>::as_ref(&p.name.ident().as_str())
|
||||
}) {
|
||||
if param_name.starts_with("impl ") {
|
||||
// `impl Trait` in argument:
|
||||
// `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
restrict_msg,
|
||||
// `impl CurrentTrait + MissingTrait`
|
||||
format!("{} + {}", param.name.ident(), trait_ref),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if generics.where_clause.predicates.is_empty() &&
|
||||
param.bounds.is_empty()
|
||||
{
|
||||
// If there are no bounds whatsoever, suggest adding a constraint
|
||||
// to the type parameter:
|
||||
// `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||
err.span_suggestion(
|
||||
param.span,
|
||||
"consider restricting this bound",
|
||||
format!("{}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else if !generics.where_clause.predicates.is_empty() {
|
||||
// There is a `where` clause, so suggest expanding it:
|
||||
// `fn foo<T>(t: T) where T: Debug {}` →
|
||||
// `fn foo<T>(t: T) where T: Debug, T: Trait {}`
|
||||
err.span_suggestion(
|
||||
generics.where_clause.span().unwrap().shrink_to_hi(),
|
||||
&format!(
|
||||
"consider further restricting type parameter `{}`",
|
||||
param_name,
|
||||
),
|
||||
format!(", {}", trait_ref.to_predicate()),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
} else {
|
||||
// If there is no `where` clause lean towards constraining to the
|
||||
// type parameter:
|
||||
// `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
|
||||
// `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
|
||||
let sp = param.span.with_hi(span.hi());
|
||||
let span = self.tcx.sess.source_map()
|
||||
.span_through_char(sp, ':');
|
||||
if sp != param.span && sp != span {
|
||||
// Only suggest if we have high certainty that the span
|
||||
// covers the colon in `foo<T: Trait>`.
|
||||
err.span_suggestion(span, restrict_msg, format!(
|
||||
"{} + ",
|
||||
trait_ref.to_predicate(),
|
||||
), Applicability::MachineApplicable);
|
||||
} else {
|
||||
err.span_label(param.span, &format!(
|
||||
"consider adding a `where {}` bound",
|
||||
trait_ref.to_predicate(),
|
||||
));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hir::Node::Crate => return,
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
hir_id = self.tcx.hir().get_parent_item(hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
|
||||
/// suggestion to borrow the initializer in order to use have a slice instead.
|
||||
fn suggest_borrow_on_unsized_slice(
|
||||
|
@ -168,12 +168,6 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
|
||||
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
|
||||
}
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
|
||||
let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
|
||||
assert!(bx.cx().type_is_sized(a));
|
||||
let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b)));
|
||||
(bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
|
||||
}
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
@ -196,6 +190,8 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
}
|
||||
let (lldata, llextra) = result.unwrap();
|
||||
// HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
|
||||
// FIXME(eddyb) move these out of this `match` arm, so they're always
|
||||
// applied, uniformly, no matter the source/destination types.
|
||||
(bx.bitcast(lldata, bx.cx().scalar_pair_element_backend_type(dst_layout, 0, true)),
|
||||
bx.bitcast(llextra, bx.cx().scalar_pair_element_backend_type(dst_layout, 1, true)))
|
||||
}
|
||||
@ -212,31 +208,27 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
) {
|
||||
let src_ty = src.layout.ty;
|
||||
let dst_ty = dst.layout.ty;
|
||||
let mut coerce_ptr = || {
|
||||
let (base, info) = match bx.load_operand(src).val {
|
||||
OperandValue::Pair(base, info) => {
|
||||
// fat-ptr to fat-ptr unsize preserves the vtable
|
||||
// i.e., &'a fmt::Debug+Send => &'a fmt::Debug
|
||||
// So we need to pointercast the base to ensure
|
||||
// the types match up.
|
||||
let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR);
|
||||
(bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info)
|
||||
}
|
||||
OperandValue::Immediate(base) => {
|
||||
unsize_thin_ptr(bx, base, src_ty, dst_ty)
|
||||
}
|
||||
OperandValue::Ref(..) => bug!()
|
||||
};
|
||||
OperandValue::Pair(base, info).store(bx, dst);
|
||||
};
|
||||
match (&src_ty.kind, &dst_ty.kind) {
|
||||
(&ty::Ref(..), &ty::Ref(..)) |
|
||||
(&ty::Ref(..), &ty::RawPtr(..)) |
|
||||
(&ty::RawPtr(..), &ty::RawPtr(..)) => {
|
||||
coerce_ptr()
|
||||
}
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
|
||||
coerce_ptr()
|
||||
let (base, info) = match bx.load_operand(src).val {
|
||||
OperandValue::Pair(base, info) => {
|
||||
// fat-ptr to fat-ptr unsize preserves the vtable
|
||||
// i.e., &'a fmt::Debug+Send => &'a fmt::Debug
|
||||
// So we need to pointercast the base to ensure
|
||||
// the types match up.
|
||||
// FIXME(eddyb) use `scalar_pair_element_backend_type` here,
|
||||
// like `unsize_thin_ptr` does.
|
||||
let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR);
|
||||
(bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info)
|
||||
}
|
||||
OperandValue::Immediate(base) => {
|
||||
unsize_thin_ptr(bx, base, src_ty, dst_ty)
|
||||
}
|
||||
OperandValue::Ref(..) => bug!()
|
||||
};
|
||||
OperandValue::Pair(base, info).store(bx, dst);
|
||||
}
|
||||
|
||||
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
|
||||
|
@ -255,6 +255,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
UNUSED_MUT,
|
||||
UNREACHABLE_CODE,
|
||||
UNREACHABLE_PATTERNS,
|
||||
OVERLAPPING_PATTERNS,
|
||||
UNUSED_MUST_USE,
|
||||
UNUSED_UNSAFE,
|
||||
PATH_STATEMENTS,
|
||||
|
@ -167,13 +167,14 @@ use super::{FieldPat, Pat, PatKind, PatRange};
|
||||
use super::{PatternFoldable, PatternFolder, compare_const_vals};
|
||||
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::RangeEnd;
|
||||
use rustc::hir::{RangeEnd, HirId};
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
|
||||
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
|
||||
|
||||
use rustc::mir::Field;
|
||||
use rustc::mir::interpret::{ConstValue, Scalar, truncate, AllocId, Pointer};
|
||||
use rustc::util::common::ErrorReported;
|
||||
use rustc::lint;
|
||||
|
||||
use syntax::attr::{SignedInt, UnsignedInt};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
@ -418,7 +419,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug)]
|
||||
enum Constructor<'tcx> {
|
||||
/// The constructor of all patterns that don't vary by constructor,
|
||||
/// e.g., struct patterns and fixed-length arrays.
|
||||
@ -426,13 +427,30 @@ enum Constructor<'tcx> {
|
||||
/// Enum variants.
|
||||
Variant(DefId),
|
||||
/// Literal values.
|
||||
ConstantValue(&'tcx ty::Const<'tcx>),
|
||||
ConstantValue(&'tcx ty::Const<'tcx>, Span),
|
||||
/// Ranges of literal values (`2..=5` and `2..5`).
|
||||
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd),
|
||||
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd, Span),
|
||||
/// Array patterns of length n.
|
||||
Slice(u64),
|
||||
}
|
||||
|
||||
// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
|
||||
impl<'tcx> std::cmp::PartialEq for Constructor<'tcx> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(Constructor::Single, Constructor::Single) => true,
|
||||
(Constructor::Variant(a), Constructor::Variant(b)) => a == b,
|
||||
(Constructor::ConstantValue(a, _), Constructor::ConstantValue(b, _)) => a == b,
|
||||
(
|
||||
Constructor::ConstantRange(a_start, a_end, a_ty, a_range_end, _),
|
||||
Constructor::ConstantRange(b_start, b_end, b_ty, b_range_end, _),
|
||||
) => a_start == b_start && a_end == b_end && a_ty == b_ty && a_range_end == b_range_end,
|
||||
(Constructor::Slice(a), Constructor::Slice(b)) => a == b,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Constructor<'tcx> {
|
||||
fn is_slice(&self) -> bool {
|
||||
match self {
|
||||
@ -447,15 +465,33 @@ impl<'tcx> Constructor<'tcx> {
|
||||
adt: &'tcx ty::AdtDef,
|
||||
) -> VariantIdx {
|
||||
match self {
|
||||
&Variant(id) => adt.variant_index_with_id(id),
|
||||
&Single => {
|
||||
Variant(id) => adt.variant_index_with_id(*id),
|
||||
Single => {
|
||||
assert!(!adt.is_enum());
|
||||
VariantIdx::new(0)
|
||||
}
|
||||
&ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
|
||||
ConstantValue(c, _) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
|
||||
_ => bug!("bad constructor {:?} for adt {:?}", self, adt)
|
||||
}
|
||||
}
|
||||
|
||||
fn display(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
match self {
|
||||
Constructor::ConstantValue(val, _) => format!("{}", val),
|
||||
Constructor::ConstantRange(lo, hi, ty, range_end, _) => {
|
||||
// Get the right sign on the output:
|
||||
let ty = ty::ParamEnv::empty().and(*ty);
|
||||
format!(
|
||||
"{}{}{}",
|
||||
ty::Const::from_bits(tcx, *lo, ty),
|
||||
range_end,
|
||||
ty::Const::from_bits(tcx, *hi, ty),
|
||||
)
|
||||
}
|
||||
Constructor::Slice(val) => format!("[{}]", val),
|
||||
_ => bug!("bad constructor being displayed: `{:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -484,6 +520,7 @@ pub enum WitnessPreference {
|
||||
struct PatCtxt<'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
max_slice_length: u64,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
/// A witness of non-exhaustiveness for error reporting, represented
|
||||
@ -610,8 +647,8 @@ impl<'tcx> Witness<'tcx> {
|
||||
|
||||
_ => {
|
||||
match *ctor {
|
||||
ConstantValue(value) => PatKind::Constant { value },
|
||||
ConstantRange(lo, hi, ty, end) => PatKind::Range(PatRange {
|
||||
ConstantValue(value, _) => PatKind::Constant { value },
|
||||
ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange {
|
||||
lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)),
|
||||
hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
|
||||
end,
|
||||
@ -647,7 +684,7 @@ fn all_constructors<'a, 'tcx>(
|
||||
let ctors = match pcx.ty.kind {
|
||||
ty::Bool => {
|
||||
[true, false].iter().map(|&b| {
|
||||
ConstantValue(ty::Const::from_bool(cx.tcx, b))
|
||||
ConstantValue(ty::Const::from_bool(cx.tcx, b), pcx.span)
|
||||
}).collect()
|
||||
}
|
||||
ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => {
|
||||
@ -679,15 +716,19 @@ fn all_constructors<'a, 'tcx>(
|
||||
ty::Char => {
|
||||
vec![
|
||||
// The valid Unicode Scalar Value ranges.
|
||||
ConstantRange('\u{0000}' as u128,
|
||||
'\u{D7FF}' as u128,
|
||||
cx.tcx.types.char,
|
||||
RangeEnd::Included
|
||||
ConstantRange(
|
||||
'\u{0000}' as u128,
|
||||
'\u{D7FF}' as u128,
|
||||
cx.tcx.types.char,
|
||||
RangeEnd::Included,
|
||||
pcx.span,
|
||||
),
|
||||
ConstantRange('\u{E000}' as u128,
|
||||
'\u{10FFFF}' as u128,
|
||||
cx.tcx.types.char,
|
||||
RangeEnd::Included
|
||||
ConstantRange(
|
||||
'\u{E000}' as u128,
|
||||
'\u{10FFFF}' as u128,
|
||||
cx.tcx.types.char,
|
||||
RangeEnd::Included,
|
||||
pcx.span,
|
||||
),
|
||||
]
|
||||
}
|
||||
@ -695,12 +736,12 @@ fn all_constructors<'a, 'tcx>(
|
||||
let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
|
||||
let min = 1u128 << (bits - 1);
|
||||
let max = min - 1;
|
||||
vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)]
|
||||
vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included, pcx.span)]
|
||||
}
|
||||
ty::Uint(uty) => {
|
||||
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
|
||||
let max = truncate(u128::max_value(), size);
|
||||
vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included)]
|
||||
vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included, pcx.span)]
|
||||
}
|
||||
_ => {
|
||||
if cx.is_uninhabited(pcx.ty) {
|
||||
@ -827,10 +868,11 @@ where
|
||||
///
|
||||
/// `IntRange` is never used to encode an empty range or a "range" that wraps
|
||||
/// around the (offset) space: i.e., `range.lo <= range.hi`.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
struct IntRange<'tcx> {
|
||||
pub range: RangeInclusive<u128>,
|
||||
pub ty: Ty<'tcx>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> IntRange<'tcx> {
|
||||
@ -860,6 +902,7 @@ impl<'tcx> IntRange<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: &Const<'tcx>,
|
||||
span: Span,
|
||||
) -> Option<IntRange<'tcx>> {
|
||||
if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) {
|
||||
let ty = value.ty;
|
||||
@ -877,7 +920,7 @@ impl<'tcx> IntRange<'tcx> {
|
||||
return None
|
||||
};
|
||||
let val = val ^ bias;
|
||||
Some(IntRange { range: val..=val, ty })
|
||||
Some(IntRange { range: val..=val, ty, span })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -890,6 +933,7 @@ impl<'tcx> IntRange<'tcx> {
|
||||
hi: u128,
|
||||
ty: Ty<'tcx>,
|
||||
end: &RangeEnd,
|
||||
span: Span,
|
||||
) -> Option<IntRange<'tcx>> {
|
||||
if Self::is_integral(ty) {
|
||||
// Perform a shift if the underlying types are signed,
|
||||
@ -901,7 +945,7 @@ impl<'tcx> IntRange<'tcx> {
|
||||
None
|
||||
} else {
|
||||
let offset = (*end == RangeEnd::Excluded) as u128;
|
||||
Some(IntRange { range: lo..=(hi - offset), ty })
|
||||
Some(IntRange { range: lo..=(hi - offset), ty, span })
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@ -916,8 +960,8 @@ impl<'tcx> IntRange<'tcx> {
|
||||
// Floating-point ranges are permitted and we don't want
|
||||
// to consider them when constructing integer ranges.
|
||||
match ctor {
|
||||
ConstantRange(lo, hi, ty, end) => Self::from_range(tcx, *lo, *hi, ty, end),
|
||||
ConstantValue(val) => Self::from_const(tcx, param_env, val),
|
||||
ConstantRange(lo, hi, ty, end, span) => Self::from_range(tcx, *lo, *hi, ty, end, *span),
|
||||
ConstantValue(val, span) => Self::from_const(tcx, param_env, val, *span),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -930,7 +974,7 @@ impl<'tcx> IntRange<'tcx> {
|
||||
loop {
|
||||
match pat.kind {
|
||||
box PatKind::Constant { value } => {
|
||||
return Self::from_const(tcx, param_env, value);
|
||||
return Self::from_const(tcx, param_env, value, pat.span);
|
||||
}
|
||||
box PatKind::Range(PatRange { lo, hi, end }) => {
|
||||
return Self::from_range(
|
||||
@ -939,6 +983,7 @@ impl<'tcx> IntRange<'tcx> {
|
||||
hi.eval_bits(tcx, param_env, hi.ty),
|
||||
&lo.ty,
|
||||
&end,
|
||||
pat.span,
|
||||
);
|
||||
}
|
||||
box PatKind::AscribeUserType { ref subpattern, .. } => {
|
||||
@ -965,14 +1010,15 @@ impl<'tcx> IntRange<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
r: RangeInclusive<u128>,
|
||||
span: Span,
|
||||
) -> Constructor<'tcx> {
|
||||
let bias = IntRange::signed_bias(tcx, ty);
|
||||
let (lo, hi) = r.into_inner();
|
||||
if lo == hi {
|
||||
let ty = ty::ParamEnv::empty().and(ty);
|
||||
ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty))
|
||||
ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty), span)
|
||||
} else {
|
||||
ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included)
|
||||
ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included, span)
|
||||
}
|
||||
}
|
||||
|
||||
@ -995,17 +1041,23 @@ impl<'tcx> IntRange<'tcx> {
|
||||
if lo > subrange_hi || subrange_lo > hi {
|
||||
// The pattern doesn't intersect with the subrange at all,
|
||||
// so the subrange remains untouched.
|
||||
remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi));
|
||||
remaining_ranges.push(
|
||||
Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi, self.span),
|
||||
);
|
||||
} else {
|
||||
if lo > subrange_lo {
|
||||
// The pattern intersects an upper section of the
|
||||
// subrange, so a lower section will remain.
|
||||
remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1)));
|
||||
remaining_ranges.push(
|
||||
Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1), self.span),
|
||||
);
|
||||
}
|
||||
if hi < subrange_hi {
|
||||
// The pattern intersects a lower section of the
|
||||
// subrange, so an upper section will remain.
|
||||
remaining_ranges.push(Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi));
|
||||
remaining_ranges.push(
|
||||
Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi, self.span),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1017,11 +1069,29 @@ impl<'tcx> IntRange<'tcx> {
|
||||
let (lo, hi) = (*self.range.start(), *self.range.end());
|
||||
let (other_lo, other_hi) = (*other.range.start(), *other.range.end());
|
||||
if lo <= other_hi && other_lo <= hi {
|
||||
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty })
|
||||
let span = other.span;
|
||||
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn suspicious_intersection(&self, other: &Self) -> bool {
|
||||
// `false` in the following cases:
|
||||
// 1 ---- // 1 ---------- // 1 ---- // 1 ----
|
||||
// 2 ---------- // 2 ---- // 2 ---- // 2 ----
|
||||
//
|
||||
// The following are currently `false`, but could be `true` in the future (#64007):
|
||||
// 1 --------- // 1 ---------
|
||||
// 2 ---------- // 2 ----------
|
||||
//
|
||||
// `true` in the following cases:
|
||||
// 1 ------- // 1 -------
|
||||
// 2 -------- // 2 -------
|
||||
let (lo, hi) = (*self.range.start(), *self.range.end());
|
||||
let (other_lo, other_hi) = (*other.range.start(), *other.range.end());
|
||||
(lo == other_hi || hi == other_lo)
|
||||
}
|
||||
}
|
||||
|
||||
// A request for missing constructor data in terms of either:
|
||||
@ -1127,6 +1197,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
||||
matrix: &Matrix<'p, 'tcx>,
|
||||
v: &[&Pat<'tcx>],
|
||||
witness: WitnessPreference,
|
||||
hir_id: HirId,
|
||||
) -> Usefulness<'tcx> {
|
||||
let &Matrix(ref rows) = matrix;
|
||||
debug!("is_useful({:#?}, {:#?})", matrix, v);
|
||||
@ -1149,6 +1220,10 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
||||
|
||||
assert!(rows.iter().all(|r| r.len() == v.len()));
|
||||
|
||||
let (ty, span) = rows.iter()
|
||||
.map(|r| (r[0].ty, r[0].span))
|
||||
.find(|(ty, _)| !ty.references_error())
|
||||
.unwrap_or((v[0].ty, v[0].span));
|
||||
let pcx = PatCtxt {
|
||||
// TyErr is used to represent the type of wildcard patterns matching
|
||||
// against inaccessible (private) fields of structs, so that we won't
|
||||
@ -1169,8 +1244,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
||||
// FIXME: this might lead to "unstable" behavior with macro hygiene
|
||||
// introducing uninhabited patterns for inaccessible fields. We
|
||||
// need to figure out how to model that.
|
||||
ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()).unwrap_or(v[0].ty),
|
||||
max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0])))
|
||||
ty,
|
||||
max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0]))),
|
||||
span,
|
||||
};
|
||||
|
||||
debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);
|
||||
@ -1184,9 +1260,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
||||
Useful
|
||||
} else {
|
||||
split_grouped_constructors(
|
||||
cx.tcx, cx.param_env, constructors, matrix, pcx.ty,
|
||||
cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id),
|
||||
).into_iter().map(|c|
|
||||
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)
|
||||
is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)
|
||||
).find(|result| result.is_useful()).unwrap_or(NotUseful)
|
||||
}
|
||||
} else {
|
||||
@ -1239,8 +1315,11 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
||||
(pcx.ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching);
|
||||
|
||||
if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive {
|
||||
split_grouped_constructors(cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty)
|
||||
.into_iter().map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness))
|
||||
split_grouped_constructors(
|
||||
cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty, DUMMY_SP, None,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id))
|
||||
.find(|result| result.is_useful())
|
||||
.unwrap_or(NotUseful)
|
||||
} else {
|
||||
@ -1251,7 +1330,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
match is_useful(cx, &matrix, &v[1..], witness) {
|
||||
match is_useful(cx, &matrix, &v[1..], witness, hir_id) {
|
||||
UsefulWithWitness(pats) => {
|
||||
let cx = &*cx;
|
||||
// In this case, there's at least one "free"
|
||||
@ -1344,6 +1423,7 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
|
||||
ctor: Constructor<'tcx>,
|
||||
lty: Ty<'tcx>,
|
||||
witness: WitnessPreference,
|
||||
hir_id: HirId,
|
||||
) -> Usefulness<'tcx> {
|
||||
debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
|
||||
let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty);
|
||||
@ -1361,7 +1441,7 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
|
||||
.collect()
|
||||
);
|
||||
match specialize(cx, v, &ctor, &wild_patterns) {
|
||||
Some(v) => match is_useful(cx, &matrix, &v, witness) {
|
||||
Some(v) => match is_useful(cx, &matrix, &v, witness, hir_id) {
|
||||
UsefulWithWitness(witnesses) => UsefulWithWitness(
|
||||
witnesses.into_iter()
|
||||
.map(|witness| witness.apply_constructor(cx, &ctor, lty))
|
||||
@ -1381,11 +1461,11 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
|
||||
/// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on.
|
||||
///
|
||||
/// Returns `None` in case of a catch-all, which can't be specialized.
|
||||
fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||
pat: &Pat<'tcx>,
|
||||
pcx: PatCtxt<'tcx>)
|
||||
-> Option<Vec<Constructor<'tcx>>>
|
||||
{
|
||||
fn pat_constructors<'tcx>(
|
||||
cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||
pat: &Pat<'tcx>,
|
||||
pcx: PatCtxt<'tcx>,
|
||||
) -> Option<Vec<Constructor<'tcx>>> {
|
||||
match *pat.kind {
|
||||
PatKind::AscribeUserType { ref subpattern, .. } =>
|
||||
pat_constructors(cx, subpattern, pcx),
|
||||
@ -1394,13 +1474,14 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||
PatKind::Variant { adt_def, variant_index, .. } => {
|
||||
Some(vec![Variant(adt_def.variants[variant_index].def_id)])
|
||||
}
|
||||
PatKind::Constant { value } => Some(vec![ConstantValue(value)]),
|
||||
PatKind::Constant { value } => Some(vec![ConstantValue(value, pat.span)]),
|
||||
PatKind::Range(PatRange { lo, hi, end }) =>
|
||||
Some(vec![ConstantRange(
|
||||
lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
|
||||
hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
|
||||
lo.ty,
|
||||
end,
|
||||
pat.span,
|
||||
)]),
|
||||
PatKind::Array { .. } => match pcx.ty.kind {
|
||||
ty::Array(_, length) => Some(vec![
|
||||
@ -1433,7 +1514,7 @@ fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty
|
||||
ty::Tuple(ref fs) => fs.len() as u64,
|
||||
ty::Slice(..) | ty::Array(..) => match *ctor {
|
||||
Slice(length) => length,
|
||||
ConstantValue(_) => 0,
|
||||
ConstantValue(..) => 0,
|
||||
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty)
|
||||
}
|
||||
ty::Ref(..) => 1,
|
||||
@ -1458,7 +1539,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx>(
|
||||
ty::Tuple(ref fs) => fs.into_iter().map(|t| t.expect_ty()).collect(),
|
||||
ty::Slice(ty) | ty::Array(ty, _) => match *ctor {
|
||||
Slice(length) => (0..length).map(|_| ty).collect(),
|
||||
ConstantValue(_) => vec![],
|
||||
ConstantValue(..) => vec![],
|
||||
_ => bug!("bad slice pattern {:?} {:?}", ctor, ty)
|
||||
}
|
||||
ty::Ref(_, rty, _) => vec![rty],
|
||||
@ -1556,8 +1637,8 @@ fn slice_pat_covered_by_const<'tcx>(
|
||||
// constructor is a range or constant with an integer type.
|
||||
fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> bool {
|
||||
let ty = match ctor {
|
||||
ConstantValue(value) => value.ty,
|
||||
ConstantRange(_, _, ty, _) => ty,
|
||||
ConstantValue(value, _) => value.ty,
|
||||
ConstantRange(_, _, ty, _, _) => ty,
|
||||
_ => return false,
|
||||
};
|
||||
if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.kind {
|
||||
@ -1599,12 +1680,17 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>)
|
||||
/// boundaries for each interval range, sort them, then create constructors for each new interval
|
||||
/// between every pair of boundary points. (This essentially sums up to performing the intuitive
|
||||
/// merging operation depicted above.)
|
||||
///
|
||||
/// `hir_id` is `None` when we're evaluating the wildcard pattern, do not lint for overlapping in
|
||||
/// ranges that case.
|
||||
fn split_grouped_constructors<'p, 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ctors: Vec<Constructor<'tcx>>,
|
||||
&Matrix(ref m): &Matrix<'p, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
span: Span,
|
||||
hir_id: Option<HirId>,
|
||||
) -> Vec<Constructor<'tcx>> {
|
||||
let mut split_ctors = Vec::with_capacity(ctors.len());
|
||||
|
||||
@ -1621,7 +1707,7 @@ fn split_grouped_constructors<'p, 'tcx>(
|
||||
/// Represents a border between 2 integers. Because the intervals spanning borders
|
||||
/// must be able to cover every integer, we need to be able to represent
|
||||
/// 2^128 + 1 such borders.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
enum Border {
|
||||
JustBefore(u128),
|
||||
AfterMax,
|
||||
@ -1638,16 +1724,38 @@ fn split_grouped_constructors<'p, 'tcx>(
|
||||
vec![from, to].into_iter()
|
||||
}
|
||||
|
||||
// Collect the span and range of all the intersecting ranges to lint on likely
|
||||
// incorrect range patterns. (#63987)
|
||||
let mut overlaps = vec![];
|
||||
// `borders` is the set of borders between equivalence classes: each equivalence
|
||||
// class lies between 2 borders.
|
||||
let row_borders = m.iter()
|
||||
.flat_map(|row| IntRange::from_pat(tcx, param_env, row[0]))
|
||||
.flat_map(|range| ctor_range.intersection(&range))
|
||||
.flat_map(|row| {
|
||||
IntRange::from_pat(tcx, param_env, row[0]).map(|r| (r, row.len()))
|
||||
})
|
||||
.flat_map(|(range, row_len)| {
|
||||
let intersection = ctor_range.intersection(&range);
|
||||
let should_lint = ctor_range.suspicious_intersection(&range);
|
||||
if let (Some(range), 1, true) = (&intersection, row_len, should_lint) {
|
||||
// FIXME: for now, only check for overlapping ranges on simple range
|
||||
// patterns. Otherwise with the current logic the following is detected
|
||||
// as overlapping:
|
||||
// match (10u8, true) {
|
||||
// (0 ..= 125, false) => {}
|
||||
// (126 ..= 255, false) => {}
|
||||
// (0 ..= 255, true) => {}
|
||||
// }
|
||||
overlaps.push(range.clone());
|
||||
}
|
||||
intersection
|
||||
})
|
||||
.flat_map(|range| range_borders(range));
|
||||
let ctor_borders = range_borders(ctor_range.clone());
|
||||
let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect();
|
||||
borders.sort_unstable();
|
||||
|
||||
lint_overlapping_patterns(tcx, hir_id, ctor_range, ty, overlaps);
|
||||
|
||||
// We're going to iterate through every pair of borders, making sure that each
|
||||
// represents an interval of nonnegative length, and convert each such interval
|
||||
// into a constructor.
|
||||
@ -1655,18 +1763,18 @@ fn split_grouped_constructors<'p, 'tcx>(
|
||||
match (window[0], window[1]) {
|
||||
(Border::JustBefore(n), Border::JustBefore(m)) => {
|
||||
if n < m {
|
||||
Some(IntRange { range: n..=(m - 1), ty })
|
||||
Some(IntRange { range: n..=(m - 1), ty, span })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
(Border::JustBefore(n), Border::AfterMax) => {
|
||||
Some(IntRange { range: n..=u128::MAX, ty })
|
||||
Some(IntRange { range: n..=u128::MAX, ty, span })
|
||||
}
|
||||
(Border::AfterMax, _) => None,
|
||||
}
|
||||
}) {
|
||||
split_ctors.push(IntRange::range_to_ctor(tcx, ty, range));
|
||||
split_ctors.push(IntRange::range_to_ctor(tcx, ty, range, span));
|
||||
}
|
||||
}
|
||||
// Any other constructor can be used unchanged.
|
||||
@ -1677,6 +1785,32 @@ fn split_grouped_constructors<'p, 'tcx>(
|
||||
split_ctors
|
||||
}
|
||||
|
||||
fn lint_overlapping_patterns(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
hir_id: Option<HirId>,
|
||||
ctor_range: IntRange<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
overlaps: Vec<IntRange<'tcx>>,
|
||||
) {
|
||||
if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) {
|
||||
let mut err = tcx.struct_span_lint_hir(
|
||||
lint::builtin::OVERLAPPING_PATTERNS,
|
||||
hir_id,
|
||||
ctor_range.span,
|
||||
"multiple patterns covering the same range",
|
||||
);
|
||||
err.span_label(ctor_range.span, "overlapping patterns");
|
||||
for int_range in overlaps {
|
||||
// Use the real type for user display of the ranges:
|
||||
err.span_label(int_range.span, &format!(
|
||||
"this range overlaps on `{}`",
|
||||
IntRange::range_to_ctor(tcx, ty, int_range.range, DUMMY_SP).display(tcx),
|
||||
));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn constructor_covered_by_range<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
@ -1701,13 +1835,13 @@ fn constructor_covered_by_range<'tcx>(
|
||||
};
|
||||
}
|
||||
match *ctor {
|
||||
ConstantValue(value) => {
|
||||
ConstantValue(value, _) => {
|
||||
let to = some_or_ok!(cmp_to(value));
|
||||
let end = (to == Ordering::Less) ||
|
||||
(end == RangeEnd::Included && to == Ordering::Equal);
|
||||
Ok(some_or_ok!(cmp_from(value)) && end)
|
||||
},
|
||||
ConstantRange(from, to, ty, RangeEnd::Included) => {
|
||||
ConstantRange(from, to, ty, RangeEnd::Included, _) => {
|
||||
let to = some_or_ok!(cmp_to(ty::Const::from_bits(
|
||||
tcx,
|
||||
to,
|
||||
@ -1721,7 +1855,7 @@ fn constructor_covered_by_range<'tcx>(
|
||||
ty::ParamEnv::empty().and(ty),
|
||||
))) && end)
|
||||
},
|
||||
ConstantRange(from, to, ty, RangeEnd::Excluded) => {
|
||||
ConstantRange(from, to, ty, RangeEnd::Excluded, _) => {
|
||||
let to = some_or_ok!(cmp_to(ty::Const::from_bits(
|
||||
tcx,
|
||||
to,
|
||||
@ -1915,7 +2049,7 @@ fn specialize<'p, 'a: 'p, 'tcx>(
|
||||
None
|
||||
}
|
||||
}
|
||||
ConstantValue(cv) => {
|
||||
ConstantValue(cv, _) => {
|
||||
match slice_pat_covered_by_const(
|
||||
cx.tcx, pat.span, cv, prefix, slice, suffix, cx.param_env,
|
||||
) {
|
||||
|
@ -10,6 +10,7 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef};
|
||||
use rustc::lint;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
|
||||
use rustc::hir::HirId;
|
||||
use rustc::hir::def::*;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
@ -239,7 +240,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||
.map(|pat| smallvec![pat.0])
|
||||
.collect();
|
||||
let scrut_ty = self.tables.node_type(scrut.hir_id);
|
||||
check_exhaustive(cx, scrut_ty, scrut.span, &matrix);
|
||||
check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
|
||||
})
|
||||
}
|
||||
|
||||
@ -256,7 +257,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
|
||||
expand_pattern(cx, pattern)
|
||||
]].into_iter().collect();
|
||||
|
||||
let witnesses = match check_not_useful(cx, pattern_ty, &pats) {
|
||||
let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) {
|
||||
Ok(_) => return,
|
||||
Err(err) => err,
|
||||
};
|
||||
@ -389,7 +390,7 @@ fn check_arms<'tcx>(
|
||||
for &(pat, hir_pat) in pats {
|
||||
let v = smallvec![pat];
|
||||
|
||||
match is_useful(cx, &seen, &v, LeaveOutWitness) {
|
||||
match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) {
|
||||
NotUseful => {
|
||||
match source {
|
||||
hir::MatchSource::IfDesugar { .. } |
|
||||
@ -465,9 +466,10 @@ fn check_not_useful(
|
||||
cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
matrix: &Matrix<'_, 'tcx>,
|
||||
hir_id: HirId,
|
||||
) -> Result<(), Vec<super::Pat<'tcx>>> {
|
||||
let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild };
|
||||
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) {
|
||||
match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness, hir_id) {
|
||||
NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable.
|
||||
UsefulWithWitness(pats) => Err(if pats.is_empty() {
|
||||
vec![wild_pattern]
|
||||
@ -483,8 +485,9 @@ fn check_exhaustive<'tcx>(
|
||||
scrut_ty: Ty<'tcx>,
|
||||
sp: Span,
|
||||
matrix: &Matrix<'_, 'tcx>,
|
||||
hir_id: HirId,
|
||||
) {
|
||||
let witnesses = match check_not_useful(cx, scrut_ty, matrix) {
|
||||
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
|
||||
Ok(_) => return,
|
||||
Err(err) => err,
|
||||
};
|
||||
|
@ -312,10 +312,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
|
||||
}
|
||||
PatKind::Range(PatRange { lo, hi, end }) => {
|
||||
write!(f, "{}", lo)?;
|
||||
match end {
|
||||
RangeEnd::Included => write!(f, "..=")?,
|
||||
RangeEnd::Excluded => write!(f, "..")?,
|
||||
}
|
||||
write!(f, "{}", end)?;
|
||||
write!(f, "{}", hi)
|
||||
}
|
||||
PatKind::Slice { ref prefix, ref slice, ref suffix } |
|
||||
|
@ -350,11 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
// If the span is from a macro, then it's hard to extract the text
|
||||
// and make a good suggestion, so don't bother.
|
||||
let is_desugaring = match sp.desugaring_kind() {
|
||||
Some(k) => sp.is_desugaring(k),
|
||||
None => false
|
||||
};
|
||||
let is_macro = sp.from_expansion() && !is_desugaring;
|
||||
let is_macro = sp.from_expansion() && sp.desugaring_kind().is_none();
|
||||
|
||||
// `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
|
||||
let expr = expr.peel_drop_temps();
|
||||
|
@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: Foo` is not satisfied
|
||||
LL | const Y: usize;
|
||||
| --------------- required by `Foo::Y`
|
||||
...
|
||||
LL | pub fn test<A: Foo, B: Foo>() {
|
||||
| -- help: consider further restricting this bound: `A: Foo +`
|
||||
LL | let _array = [4; <A as Foo>::Y];
|
||||
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
|
||||
|
|
||||
= help: consider adding a `where A: Foo` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: Foo` is not satisfied
|
||||
LL | const Y: usize;
|
||||
| --------------- required by `Foo::Y`
|
||||
...
|
||||
LL | pub fn test<A: Foo, B: Foo>() {
|
||||
| -- help: consider further restricting this bound: `A: Foo +`
|
||||
LL | let _array: [u32; <A as Foo>::Y];
|
||||
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
|
||||
|
|
||||
= help: consider adding a `where A: Foo` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -9,7 +9,10 @@ LL | impl Case1 for S1 {
|
||||
error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` is not an iterator
|
||||
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
|
||||
|
|
||||
LL | / fn assume_case1<T: Case1>() {
|
||||
LL | fn assume_case1<T: Case1>() {
|
||||
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::iter::Iterator`
|
||||
| _|
|
||||
| |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
@ -19,7 +22,6 @@ LL | | }
|
||||
| |_^ `<<T as Case1>::C as std::iter::Iterator>::Item` is not an iterator
|
||||
|
|
||||
= help: the trait `std::iter::Iterator` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
|
||||
= help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::iter::Iterator` bound
|
||||
|
||||
error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be sent between threads safely
|
||||
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
|
||||
@ -27,7 +29,10 @@ error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be sent be
|
||||
LL | trait Case1 {
|
||||
| ----------- required by `Case1`
|
||||
...
|
||||
LL | / fn assume_case1<T: Case1>() {
|
||||
LL | fn assume_case1<T: Case1>() {
|
||||
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send`
|
||||
| _|
|
||||
| |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
@ -37,7 +42,6 @@ LL | | }
|
||||
| |_^ `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
|
||||
= help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Send` bound
|
||||
|
||||
error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be shared between threads safely
|
||||
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
|
||||
@ -45,7 +49,10 @@ error[E0277]: `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be shared
|
||||
LL | trait Case1 {
|
||||
| ----------- required by `Case1`
|
||||
...
|
||||
LL | / fn assume_case1<T: Case1>() {
|
||||
LL | fn assume_case1<T: Case1>() {
|
||||
| ^ - help: consider further restricting the associated type: `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync`
|
||||
| _|
|
||||
| |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
@ -55,7 +62,6 @@ LL | | }
|
||||
| |_^ `<<T as Case1>::C as std::iter::Iterator>::Item` cannot be shared between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Sync` is not implemented for `<<T as Case1>::C as std::iter::Iterator>::Item`
|
||||
= help: consider adding a `where <<T as Case1>::C as std::iter::Iterator>::Item: std::marker::Sync` bound
|
||||
|
||||
error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug`
|
||||
--> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1
|
||||
|
@ -0,0 +1,29 @@
|
||||
// run-rustfix
|
||||
// Test equality constraints on associated types in a where clause.
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub trait ToInt {
|
||||
fn to_int(&self) -> isize;
|
||||
}
|
||||
|
||||
pub trait GetToInt
|
||||
{
|
||||
type R;
|
||||
|
||||
fn get(&self) -> <Self as GetToInt>::R;
|
||||
}
|
||||
|
||||
fn foo<G>(g: G) -> isize
|
||||
where G : GetToInt, <G as GetToInt>::R: ToInt
|
||||
{
|
||||
ToInt::to_int(&g.get()) //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn bar<G : GetToInt>(g: G) -> isize
|
||||
where G::R : ToInt
|
||||
{
|
||||
ToInt::to_int(&g.get()) // OK
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
// run-rustfix
|
||||
// Test equality constraints on associated types in a where clause.
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub trait ToInt {
|
||||
fn to_int(&self) -> isize;
|
||||
|
@ -1,13 +1,14 @@
|
||||
error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
|
||||
--> $DIR/associated-types-bound-failure.rs:17:19
|
||||
--> $DIR/associated-types-bound-failure.rs:19:19
|
||||
|
|
||||
LL | fn to_int(&self) -> isize;
|
||||
| -------------------------- required by `ToInt::to_int`
|
||||
...
|
||||
LL | where G : GetToInt
|
||||
| - help: consider further restricting the associated type: `, <G as GetToInt>::R: ToInt`
|
||||
LL | {
|
||||
LL | ToInt::to_int(&g.get())
|
||||
| ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
|
||||
|
|
||||
= help: consider adding a `where <G as GetToInt>::R: ToInt` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
// run-rustfix
|
||||
#![allow(unused_variables)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
}
|
||||
|
||||
trait Other {
|
||||
fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {}
|
||||
//~^ ERROR the trait bound `Self: Get` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
// run-rustfix
|
||||
#![allow(unused_variables)]
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
|
@ -1,10 +1,11 @@
|
||||
error[E0277]: the trait bound `Self: Get` is not satisfied
|
||||
--> $DIR/associated-types-for-unimpl-trait.rs:7:5
|
||||
--> $DIR/associated-types-for-unimpl-trait.rs:10:5
|
||||
|
|
||||
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: Get` bound
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
|
||||
| | |
|
||||
| | help: consider further restricting `Self`: `where Self: Get`
|
||||
| the trait `Get` is not implemented for `Self`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
|
||||
--> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:12
|
||||
|
|
||||
LL | fn f<T:Foo<isize>>(t: &T) {
|
||||
| -- help: consider further restricting this bound: `T: Foo<usize> +`
|
||||
LL | let u: <T as Foo<usize>>::Bar = t.get_bar();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo<usize>` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: Foo<usize>` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,9 +2,10 @@ error[E0277]: the trait bound `T: Get` is not satisfied
|
||||
--> $DIR/associated-types-no-suitable-bound.rs:11:5
|
||||
|
|
||||
LL | fn uhoh<T>(foo: <T as Get>::Value) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: Get` bound
|
||||
| ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | help: consider restricting this bound: `T: Get`
|
||||
| the trait `Get` is not implemented for `T`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
|
||||
--> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
|
||||
|
|
||||
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: Get` bound
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
|
||||
| | |
|
||||
| | help: consider further restricting `Self`: `where Self: Get`
|
||||
| the trait `Get` is not implemented for `Self`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
|
||||
--> $DIR/associated-types-no-suitable-supertrait.rs:17:5
|
||||
|
|
||||
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: Get` bound
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
|
||||
| | |
|
||||
| | help: consider further restricting `Self`: `where Self: Get`
|
||||
| the trait `Get` is not implemented for `Self`
|
||||
|
||||
error[E0277]: the trait bound `(T, U): Get` is not satisfied
|
||||
--> $DIR/associated-types-no-suitable-supertrait.rs:22:5
|
||||
|
@ -0,0 +1,30 @@
|
||||
// run-rustfix
|
||||
// Check that we get an error when you use `<Self as Get>::Value` in
|
||||
// the trait definition even if there is no default method.
|
||||
|
||||
trait Get {
|
||||
type Value;
|
||||
}
|
||||
|
||||
trait Other {
|
||||
fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get ;
|
||||
//~^ ERROR E0277
|
||||
}
|
||||
|
||||
impl Get for () {
|
||||
type Value = f32;
|
||||
}
|
||||
|
||||
impl Get for f64 {
|
||||
type Value = u32;
|
||||
}
|
||||
|
||||
impl Other for () {
|
||||
fn okay<U:Get>(&self, _foo: U, _bar: <Self as Get>::Value) { }
|
||||
}
|
||||
|
||||
impl Other for f64 {
|
||||
fn okay<U:Get>(&self, _foo: U, _bar: <Self as Get>::Value) { }
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -1,3 +1,4 @@
|
||||
// run-rustfix
|
||||
// Check that we get an error when you use `<Self as Get>::Value` in
|
||||
// the trait definition even if there is no default method.
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
error[E0277]: the trait bound `Self: Get` is not satisfied
|
||||
--> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:9:5
|
||||
--> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5
|
||||
|
|
||||
LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: Get` bound
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
|
||||
| | |
|
||||
| | help: consider further restricting `Self`: `where Self: Get`
|
||||
| the trait `Get` is not implemented for `Self`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
14
src/test/ui/associated-types/associated-types-unsized.fixed
Normal file
14
src/test/ui/associated-types/associated-types-unsized.fixed
Normal file
@ -0,0 +1,14 @@
|
||||
// run-rustfix
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
trait Get {
|
||||
type Value: ?Sized;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
}
|
||||
|
||||
fn foo<T:Get>(t: T) where <T as Get>::Value: std::marker::Sized {
|
||||
let x = t.get(); //~ ERROR the size for values of type
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
// run-rustfix
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
trait Get {
|
||||
type Value: ?Sized;
|
||||
fn get(&self) -> <Self as Get>::Value;
|
||||
|
@ -1,12 +1,13 @@
|
||||
error[E0277]: the size for values of type `<T as Get>::Value` cannot be known at compilation time
|
||||
--> $DIR/associated-types-unsized.rs:7:9
|
||||
--> $DIR/associated-types-unsized.rs:10:9
|
||||
|
|
||||
LL | fn foo<T:Get>(t: T) {
|
||||
| - help: consider further restricting the associated type: `where <T as Get>::Value: std::marker::Sized`
|
||||
LL | let x = t.get();
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `<T as Get>::Value`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where <T as Get>::Value: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/bad-method-typaram-kind.rs:2:7
|
||||
|
|
||||
LL | fn foo<T:'static>() {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Send +`
|
||||
LL | 1.bar::<T>();
|
||||
| ^^^ `T` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,20 +2,22 @@ error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/builtin-superkinds-double-superkind.rs:6:24
|
||||
|
|
||||
LL | impl <T: Sync+'static> Foo for (T,) { }
|
||||
| ^^^ `T` cannot be sent between threads safely
|
||||
| -- ^^^ `T` cannot be sent between threads safely
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Send +`
|
||||
|
|
||||
= help: within `(T,)`, the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
= note: required because it appears within the type `(T,)`
|
||||
|
||||
error[E0277]: `T` cannot be shared between threads safely
|
||||
--> $DIR/builtin-superkinds-double-superkind.rs:9:16
|
||||
|
|
||||
LL | impl <T: Send> Foo for (T,T) { }
|
||||
| ^^^ `T` cannot be shared between threads safely
|
||||
| -- ^^^ `T` cannot be shared between threads safely
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Sync +`
|
||||
|
|
||||
= help: within `(T, T)`, the trait `std::marker::Sync` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Sync` bound
|
||||
= note: required because it appears within the type `(T, T)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -2,10 +2,11 @@ error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/builtin-superkinds-in-metadata.rs:13:23
|
||||
|
|
||||
LL | impl <T:Sync+'static> RequiresRequiresShareAndSend for X<T> { }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely
|
||||
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Send +`
|
||||
|
|
||||
= help: within `X<T>`, the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
= note: required because it appears within the type `X<T>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -2,10 +2,11 @@ error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/builtin-superkinds-typaram-not-send.rs:5:24
|
||||
|
|
||||
LL | impl <T: Sync+'static> Foo for T { }
|
||||
| ^^^ `T` cannot be sent between threads safely
|
||||
| -- ^^^ `T` cannot be sent between threads safely
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Send +`
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
|
||||
// check-pass
|
||||
#![feature(exclusive_range_pattern)]
|
||||
#![warn(unreachable_patterns)]
|
||||
#![warn(overlapping_patterns)]
|
||||
|
||||
fn main() {
|
||||
// These cases should generate no warning.
|
||||
@ -13,7 +13,7 @@ fn main() {
|
||||
|
||||
match 10 {
|
||||
1..10 => {},
|
||||
9..=10 => {},
|
||||
9..=10 => {}, //~ WARNING multiple patterns covering the same range
|
||||
_ => {},
|
||||
}
|
||||
|
||||
@ -23,22 +23,25 @@ fn main() {
|
||||
_ => {},
|
||||
}
|
||||
|
||||
// These cases should generate an "unreachable pattern" warning.
|
||||
// These cases should generate "unreachable pattern" warnings.
|
||||
match 10 {
|
||||
1..10 => {},
|
||||
9 => {},
|
||||
9 => {}, //~ WARNING unreachable pattern
|
||||
_ => {},
|
||||
}
|
||||
|
||||
match 10 {
|
||||
1..10 => {},
|
||||
8..=9 => {},
|
||||
8..=9 => {}, //~ WARNING multiple patterns covering the same range
|
||||
_ => {},
|
||||
}
|
||||
|
||||
match 10 {
|
||||
1..10 => {},
|
||||
9..=9 => {},
|
||||
5..7 => {},
|
||||
6 => {}, //~ WARNING unreachable pattern
|
||||
1..10 => {}, //~ WARNING multiple patterns covering the same range
|
||||
9..=9 => {}, //~ WARNING unreachable pattern
|
||||
6 => {}, //~ WARNING unreachable pattern
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,17 @@
|
||||
warning: multiple patterns covering the same range
|
||||
--> $DIR/issue-43253.rs:16:9
|
||||
|
|
||||
LL | 1..10 => {},
|
||||
| ----- this range overlaps on `9i32`
|
||||
LL | 9..=10 => {},
|
||||
| ^^^^^^ overlapping patterns
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-43253.rs:4:9
|
||||
|
|
||||
LL | #![warn(overlapping_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unreachable pattern
|
||||
--> $DIR/issue-43253.rs:29:9
|
||||
|
|
||||
@ -5,7 +19,7 @@ LL | 9 => {},
|
||||
| ^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/issue-43253.rs:4:9
|
||||
--> $DIR/issue-43253.rs:3:9
|
||||
|
|
||||
LL | #![warn(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -19,6 +33,18 @@ LL | 8..=9 => {},
|
||||
warning: unreachable pattern
|
||||
--> $DIR/issue-43253.rs:41:9
|
||||
|
|
||||
LL | 6 => {},
|
||||
| ^
|
||||
|
||||
warning: unreachable pattern
|
||||
--> $DIR/issue-43253.rs:43:9
|
||||
|
|
||||
LL | 9..=9 => {},
|
||||
| ^^^^^
|
||||
|
||||
warning: unreachable pattern
|
||||
--> $DIR/issue-43253.rs:44:9
|
||||
|
|
||||
LL | 6 => {},
|
||||
| ^
|
||||
|
||||
|
@ -4,14 +4,16 @@ error[E0277]: `F` cannot be sent between threads safely
|
||||
LL | struct X<F> where F: FnOnce() + 'static + Send {
|
||||
| ---------------------------------------------- required by `X`
|
||||
...
|
||||
LL | / fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
|
||||
LL | fn foo<F>(blk: F) -> X<F> where F: FnOnce() + 'static {
|
||||
| ^ - help: consider further restricting type parameter `F`: `, F: std::marker::Send`
|
||||
| _|
|
||||
| |
|
||||
LL | |
|
||||
LL | | return X { field: blk };
|
||||
LL | | }
|
||||
| |_^ `F` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `F`
|
||||
= help: consider adding a `where F: std::marker::Send` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,11 +4,13 @@ error[E0277]: `F` cannot be shared between threads safely
|
||||
LL | fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
|
||||
| ---------------- ---- required by this bound in `take_const_owned`
|
||||
...
|
||||
LL | fn give_owned<F>(f: F) where F: FnOnce() + Send {
|
||||
| - help: consider further restricting type parameter `F`: `, F: std::marker::Sync`
|
||||
LL | take_any(f);
|
||||
LL | take_const_owned(f);
|
||||
| ^ `F` cannot be shared between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Sync` is not implemented for `F`
|
||||
= help: consider adding a `where F: std::marker::Sync` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -16,26 +16,30 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
|
||||
|
|
||||
LL | pub struct Foo<A, B>(A, B);
|
||||
| --------------------------- required by `Foo`
|
||||
LL |
|
||||
LL | impl<A, B> Foo<A, B> {
|
||||
| - help: consider restricting this bound: `A: std::marker::Sized`
|
||||
...
|
||||
LL | [5; Self::HOST_SIZE] == [6; 0]
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `A`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where A: std::marker::Sized` bound
|
||||
|
||||
error[E0277]: the size for values of type `B` cannot be known at compilation time
|
||||
--> $DIR/too_generic_eval_ice.rs:7:13
|
||||
|
|
||||
LL | pub struct Foo<A, B>(A, B);
|
||||
| --------------------------- required by `Foo`
|
||||
LL |
|
||||
LL | impl<A, B> Foo<A, B> {
|
||||
| - help: consider restricting this bound: `B: std::marker::Sized`
|
||||
...
|
||||
LL | [5; Self::HOST_SIZE] == [6; 0]
|
||||
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `B`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where B: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,23 +1,25 @@
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/dst-object-from-unsized-type.rs:8:23
|
||||
|
|
||||
LL | fn test1<T: ?Sized + Foo>(t: &T) {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
LL | let u: &dyn Foo = t;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: required for the cast to the object type `dyn Foo`
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/dst-object-from-unsized-type.rs:13:23
|
||||
|
|
||||
LL | fn test2<T: ?Sized + Foo>(t: &T) {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
LL | let v: &dyn Foo = t as &dyn Foo;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: required for the cast to the object type `dyn Foo`
|
||||
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![feature(precise_pointer_size_matching)]
|
||||
#![feature(exclusive_range_pattern)]
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
#![deny(overlapping_patterns)]
|
||||
|
||||
use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128};
|
||||
|
||||
@ -41,7 +41,8 @@ fn main() {
|
||||
match x { //~ ERROR non-exhaustive patterns
|
||||
-7 => {}
|
||||
-5..=120 => {}
|
||||
-2..=20 => {} //~ ERROR unreachable pattern
|
||||
-2..=20 => {}
|
||||
//~^ ERROR unreachable pattern
|
||||
125 => {}
|
||||
}
|
||||
|
||||
@ -135,9 +136,9 @@ fn main() {
|
||||
(125 .. 128, false) => {}
|
||||
}
|
||||
|
||||
match 0u8 { // ok
|
||||
match 0u8 {
|
||||
0 .. 2 => {}
|
||||
1 ..= 2 => {}
|
||||
1 ..= 2 => {} //~ ERROR multiple patterns covering the same range
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | 200 => {}
|
||||
| ^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/exhaustive_integer_patterns.rs:4:9
|
||||
--> $DIR/exhaustive_integer_patterns.rs:3:9
|
||||
|
|
||||
LL | #![deny(unreachable_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
@ -41,7 +41,7 @@ LL | match x {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:82:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:83:11
|
||||
|
|
||||
LL | match 0i8 {
|
||||
| ^^^ pattern `std::i8::MIN` not covered
|
||||
@ -49,7 +49,7 @@ LL | match 0i8 {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `0i16` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:90:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:91:11
|
||||
|
|
||||
LL | match 0i16 {
|
||||
| ^^^^ pattern `0i16` not covered
|
||||
@ -57,7 +57,7 @@ LL | match 0i16 {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:108:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:109:11
|
||||
|
|
||||
LL | match 0u8 {
|
||||
| ^^^ pattern `128u8..=std::u8::MAX` not covered
|
||||
@ -65,7 +65,7 @@ LL | match 0u8 {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:120:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:121:11
|
||||
|
|
||||
LL | match (0u8, Some(())) {
|
||||
| ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered
|
||||
@ -73,15 +73,29 @@ LL | match (0u8, Some(())) {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:125:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:126:11
|
||||
|
|
||||
LL | match (0u8, true) {
|
||||
| ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error: multiple patterns covering the same range
|
||||
--> $DIR/exhaustive_integer_patterns.rs:141:9
|
||||
|
|
||||
LL | 0 .. 2 => {}
|
||||
| ------ this range overlaps on `1u8`
|
||||
LL | 1 ..= 2 => {}
|
||||
| ^^^^^^^ overlapping patterns
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/exhaustive_integer_patterns.rs:4:9
|
||||
|
|
||||
LL | #![deny(overlapping_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:145:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:146:11
|
||||
|
|
||||
LL | match 0u128 {
|
||||
| ^^^^^ pattern `std::u128::MAX` not covered
|
||||
@ -89,7 +103,7 @@ LL | match 0u128 {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `5u128..=std::u128::MAX` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:149:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:150:11
|
||||
|
|
||||
LL | match 0u128 {
|
||||
| ^^^^^ pattern `5u128..=std::u128::MAX` not covered
|
||||
@ -97,13 +111,13 @@ LL | match 0u128 {
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered
|
||||
--> $DIR/exhaustive_integer_patterns.rs:153:11
|
||||
--> $DIR/exhaustive_integer_patterns.rs:154:11
|
||||
|
|
||||
LL | match 0u128 {
|
||||
| ^^^^^ pattern `0u128..=3u128` not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
error: aborting due to 14 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
||||
|
@ -6,10 +6,11 @@ LL | fn want_bar_for_any_ccx<B>(b: &B)
|
||||
LL | where B : for<'ccx> Bar<'ccx>
|
||||
| ------------------- required by this bound in `want_bar_for_any_ccx`
|
||||
...
|
||||
LL | where B : Qux
|
||||
| - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>`
|
||||
...
|
||||
LL | want_bar_for_any_ccx(b);
|
||||
| ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
|
||||
|
|
||||
= help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
|
||||
--> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
|
||||
|
|
||||
LL | where F : Foo<'x>
|
||||
| - help: consider further restricting type parameter `F`: `, for<'tcx> F: Foo<'tcx>`
|
||||
...
|
||||
LL | want_foo_for_any_tcx(f);
|
||||
| ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
|
||||
...
|
||||
@ -8,12 +11,13 @@ LL | fn want_foo_for_any_tcx<F>(f: &F)
|
||||
| --------------------
|
||||
LL | where F : for<'tcx> Foo<'tcx>
|
||||
| ------------------- required by this bound in `want_foo_for_any_tcx`
|
||||
|
|
||||
= help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound
|
||||
|
||||
error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
|
||||
--> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
|
||||
|
|
||||
LL | where B : Bar<'x>
|
||||
| - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>`
|
||||
...
|
||||
LL | want_bar_for_any_ccx(b);
|
||||
| ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
|
||||
...
|
||||
@ -21,8 +25,6 @@ LL | fn want_bar_for_any_ccx<B>(b: &B)
|
||||
| --------------------
|
||||
LL | where B : for<'ccx> Bar<'ccx>
|
||||
| ------------------- required by this bound in `want_bar_for_any_ccx`
|
||||
|
|
||||
= help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)`
|
||||
--> $DIR/issue-55872-1.rs:12:5
|
||||
|
|
||||
LL | impl<S: Default> Bar for S {
|
||||
| -- help: consider further restricting this bound: `S: std::marker::Copy +`
|
||||
LL | type E = impl Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
|
||||
|
|
||||
= help: consider adding a `where S: std::marker::Copy` bound
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
@ -13,8 +14,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T)
|
||||
|
|
||||
LL | type E = impl Copy;
|
||||
| ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
|
||||
...
|
||||
LL | fn foo<T: Default>() -> Self::E {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Copy +`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
= note: required because it appears within the type `(S, T)`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Test that codegen works correctly when there are multiple refutable
|
||||
// patterns in match expression.
|
||||
|
||||
|
||||
enum Foo {
|
||||
FooUint(usize),
|
||||
FooNullary,
|
||||
|
@ -7,13 +7,13 @@ LL | trait From<Src> {
|
||||
LL | / fn to<Dst>(
|
||||
LL | | self
|
||||
LL | | ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
|
||||
| | - help: consider further restricting `Self`: `, Self: std::marker::Sized`
|
||||
LL | | From::from(self)
|
||||
LL | | }
|
||||
| |_____^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Self`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Self: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// run-pass
|
||||
#![allow(unused_imports)]
|
||||
#![allow(unused_imports, overlapping_patterns)]
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
use m::{START, END};
|
||||
|
@ -5,9 +5,9 @@ LL | pub struct Foo<T: Bound>(T);
|
||||
| ---------------------------- required by `Foo`
|
||||
...
|
||||
LL | impl<T> Trait2 for Foo<T> {}
|
||||
| ^^^^^^ the trait `Bound` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: Bound` bound
|
||||
| - ^^^^^^ the trait `Bound` is not implemented for `T`
|
||||
| |
|
||||
| help: consider restricting this bound: `T: Bound`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
error[E0277]: `<P as Process<'_>>::Item` is not an iterator
|
||||
--> $DIR/issue-22872.rs:20:40
|
||||
|
|
||||
LL | fn push_process<P>(process: P) where P: Process<'static> {
|
||||
| - help: consider further restricting the associated type: `, <P as Process<'_>>::Item: std::iter::Iterator`
|
||||
LL | let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
|
||||
|
|
||||
= help: the trait `std::iter::Iterator` is not implemented for `<P as Process<'_>>::Item`
|
||||
= help: consider adding a `where <P as Process<'_>>::Item: std::iter::Iterator` bound
|
||||
= note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>`
|
||||
= note: required for the cast to the object type `dyn for<'b> Wrap<'b>`
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
// run-pass
|
||||
#![allow(overlapping_patterns)]
|
||||
|
||||
fn main() {
|
||||
let x = 'a';
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/issue-27060-2.rs:3:5
|
||||
|
|
||||
LL | pub struct Bad<T: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
LL | data: T,
|
||||
| ^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -2,11 +2,12 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
|
||||
--> $DIR/issue-27078.rs:5:12
|
||||
|
|
||||
LL | fn foo(self) -> &'static i32 {
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
| ^^^^ - help: consider further restricting `Self`: `where Self: std::marker::Sized`
|
||||
| |
|
||||
| doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Self`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Self: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
|
@ -4,7 +4,6 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
|
||||
LL | #[derive(Debug, Copy, Clone)]
|
||||
| ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
|
||||
|
|
||||
= help: consider adding a `where <Col as Expression>::SqlType: NotNull` bound
|
||||
= note: required because of the requirements on the impl of `IntoNullable` for `<Col as Expression>::SqlType`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -2,11 +2,12 @@ error[E0277]: the size for values of type `<Self as std::ops::Deref>::Target` ca
|
||||
--> $DIR/issue-42312.rs:4:29
|
||||
|
|
||||
LL | fn baz(_: Self::Target) where Self: Deref {}
|
||||
| ^ doesn't have a size known at compile-time
|
||||
| ^ - help: consider further restricting the associated type: `, <Self as std::ops::Deref>::Target: std::marker::Sized`
|
||||
| |
|
||||
| doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `<Self as std::ops::Deref>::Target`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where <Self as std::ops::Deref>::Target: std::marker::Sized` bound
|
||||
= note: all function arguments must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
|
@ -2,9 +2,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-43784-associated-type.rs:13:9
|
||||
|
|
||||
LL | impl<T> Complete for T {
|
||||
| ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
| - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
| |
|
||||
| help: consider restricting this bound: `T: std::marker::Copy`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,9 +2,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/issue-43784-supertrait.rs:8:9
|
||||
|
|
||||
LL | impl<T> Complete for T {}
|
||||
| ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
| - ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
| |
|
||||
| help: consider restricting this bound: `T: std::marker::Copy`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,42 +1,50 @@
|
||||
error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/kindck-impl-type-params.rs:18:13
|
||||
|
|
||||
LL | fn f<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Send`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a = &t as &dyn Gettable<T>;
|
||||
| ^^ `T` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/kindck-impl-type-params.rs:18:13
|
||||
|
|
||||
LL | fn f<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Copy`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a = &t as &dyn Gettable<T>;
|
||||
| ^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/kindck-impl-type-params.rs:25:31
|
||||
|
|
||||
LL | fn g<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Send`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a: &dyn Gettable<T> = &t;
|
||||
| ^^ `T` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/kindck-impl-type-params.rs:25:31
|
||||
|
|
||||
LL | fn g<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Copy`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a: &dyn Gettable<T> = &t;
|
||||
| ^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
|
@ -1,42 +1,50 @@
|
||||
error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/kindck-impl-type-params.rs:18:13
|
||||
|
|
||||
LL | fn f<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Send`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a = &t as &dyn Gettable<T>;
|
||||
| ^^ `T` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/kindck-impl-type-params.rs:18:13
|
||||
|
|
||||
LL | fn f<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Copy`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a = &t as &dyn Gettable<T>;
|
||||
| ^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/kindck-impl-type-params.rs:25:31
|
||||
|
|
||||
LL | fn g<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Send`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a: &dyn Gettable<T> = &t;
|
||||
| ^^ `T` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/kindck-impl-type-params.rs:25:31
|
||||
|
|
||||
LL | fn g<T>(val: T) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Copy`
|
||||
LL | let t: S<T> = S(marker::PhantomData);
|
||||
LL | let a: &dyn Gettable<T> = &t;
|
||||
| ^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
= note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
|
||||
= note: required for the cast to the object type `dyn Gettable<T>`
|
||||
|
||||
|
@ -1,39 +1,45 @@
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
//error-pattern: unreachable
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
#![deny(unreachable_patterns, overlapping_patterns)]
|
||||
|
||||
fn main() {
|
||||
match 5 {
|
||||
1 ..= 10 => { }
|
||||
5 ..= 6 => { }
|
||||
//~^ ERROR unreachable pattern
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match 5 {
|
||||
3 ..= 6 => { }
|
||||
4 ..= 6 => { }
|
||||
//~^ ERROR unreachable pattern
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match 5 {
|
||||
4 ..= 6 => { }
|
||||
4 ..= 6 => { }
|
||||
//~^ ERROR unreachable pattern
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match 'c' {
|
||||
'A' ..= 'z' => {}
|
||||
'a' ..= 'z' => {}
|
||||
//~^ ERROR unreachable pattern
|
||||
_ => {}
|
||||
};
|
||||
|
||||
match 1.0f64 {
|
||||
0.01f64 ..= 6.5f64 => {}
|
||||
0.02f64 => {}
|
||||
//~^ WARNING floating-point types cannot be used in patterns
|
||||
//~| WARNING floating-point types cannot be used in patterns
|
||||
//~| WARNING floating-point types cannot be used in patterns
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
0.02f64 => {} //~ ERROR unreachable pattern
|
||||
//~^ WARNING floating-point types cannot be used in patterns
|
||||
//~| WARNING this was previously accepted by the compiler
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
|
@ -1,35 +1,35 @@
|
||||
error: unreachable pattern
|
||||
--> $DIR/match-range-fail-dominate.rs:12:7
|
||||
--> $DIR/match-range-fail-dominate.rs:6:7
|
||||
|
|
||||
LL | 5 ..= 6 => { }
|
||||
| ^^^^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/match-range-fail-dominate.rs:7:9
|
||||
--> $DIR/match-range-fail-dominate.rs:1:9
|
||||
|
|
||||
LL | #![deny(unreachable_patterns)]
|
||||
LL | #![deny(unreachable_patterns, overlapping_patterns)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/match-range-fail-dominate.rs:18:7
|
||||
--> $DIR/match-range-fail-dominate.rs:13:7
|
||||
|
|
||||
LL | 4 ..= 6 => { }
|
||||
| ^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/match-range-fail-dominate.rs:24:7
|
||||
--> $DIR/match-range-fail-dominate.rs:20:7
|
||||
|
|
||||
LL | 4 ..= 6 => { }
|
||||
| ^^^^^^^
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/match-range-fail-dominate.rs:30:7
|
||||
--> $DIR/match-range-fail-dominate.rs:27:7
|
||||
|
|
||||
LL | 'a' ..= 'z' => {}
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: floating-point types cannot be used in patterns
|
||||
--> $DIR/match-range-fail-dominate.rs:35:7
|
||||
--> $DIR/match-range-fail-dominate.rs:33:7
|
||||
|
|
||||
LL | 0.01f64 ..= 6.5f64 => {}
|
||||
| ^^^^^^^
|
||||
@ -39,7 +39,7 @@ LL | 0.01f64 ..= 6.5f64 => {}
|
||||
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
|
||||
|
||||
warning: floating-point types cannot be used in patterns
|
||||
--> $DIR/match-range-fail-dominate.rs:35:19
|
||||
--> $DIR/match-range-fail-dominate.rs:33:19
|
||||
|
|
||||
LL | 0.01f64 ..= 6.5f64 => {}
|
||||
| ^^^^^^
|
||||
@ -48,7 +48,7 @@ LL | 0.01f64 ..= 6.5f64 => {}
|
||||
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
|
||||
|
||||
warning: floating-point types cannot be used in patterns
|
||||
--> $DIR/match-range-fail-dominate.rs:36:7
|
||||
--> $DIR/match-range-fail-dominate.rs:40:7
|
||||
|
|
||||
LL | 0.02f64 => {}
|
||||
| ^^^^^^^
|
||||
@ -57,13 +57,13 @@ LL | 0.02f64 => {}
|
||||
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
|
||||
|
||||
error: unreachable pattern
|
||||
--> $DIR/match-range-fail-dominate.rs:36:7
|
||||
--> $DIR/match-range-fail-dominate.rs:40:7
|
||||
|
|
||||
LL | 0.02f64 => {}
|
||||
| ^^^^^^^
|
||||
|
||||
warning: floating-point types cannot be used in patterns
|
||||
--> $DIR/match-range-fail-dominate.rs:35:7
|
||||
--> $DIR/match-range-fail-dominate.rs:33:7
|
||||
|
|
||||
LL | 0.01f64 ..= 6.5f64 => {}
|
||||
| ^^^^^^^
|
||||
|
@ -5,7 +5,6 @@ LL | a == b;
|
||||
| ^^ no implementation for `&T == T`
|
||||
|
|
||||
= help: the trait `std::cmp::PartialEq<T>` is not implemented for `&T`
|
||||
= help: consider adding a `where &T: std::cmp::PartialEq<T>` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,12 +3,13 @@ error[E0277]: `T` cannot be shared between threads safely
|
||||
|
|
||||
LL | fn is_zen<T: Zen>(_: T) {}
|
||||
| ------ --- required by this bound in `is_zen`
|
||||
...
|
||||
LL |
|
||||
LL | fn not_sync<T>(x: Guard<T>) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Sync`
|
||||
LL | is_zen(x)
|
||||
| ^ `T` cannot be shared between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Sync` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Sync` bound
|
||||
= note: required because of the requirements on the impl of `Zen` for `&T`
|
||||
= note: required because it appears within the type `std::marker::PhantomData<&T>`
|
||||
= note: required because it appears within the type `Guard<'_, T>`
|
||||
@ -19,11 +20,12 @@ error[E0277]: `T` cannot be shared between threads safely
|
||||
LL | fn is_zen<T: Zen>(_: T) {}
|
||||
| ------ --- required by this bound in `is_zen`
|
||||
...
|
||||
LL | fn nested_not_sync<T>(x: Nested<Guard<T>>) {
|
||||
| - help: consider restricting this bound: `T: std::marker::Sync`
|
||||
LL | is_zen(x)
|
||||
| ^ `T` cannot be shared between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Sync` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Sync` bound
|
||||
= note: required because of the requirements on the impl of `Zen` for `&T`
|
||||
= note: required because it appears within the type `std::marker::PhantomData<&T>`
|
||||
= note: required because it appears within the type `Guard<'_, T>`
|
||||
|
@ -8,7 +8,7 @@
|
||||
#![feature(precise_pointer_size_matching)]
|
||||
#![feature(exclusive_range_pattern)]
|
||||
|
||||
#![deny(unreachable_patterns)]
|
||||
#![deny(unreachable_patterns, overlapping_patterns)]
|
||||
|
||||
use std::{usize, isize};
|
||||
|
||||
|
@ -3,7 +3,7 @@ pub fn main() {
|
||||
let i = 5;
|
||||
match &&&&i {
|
||||
1 ..= 3 => panic!(),
|
||||
3 ..= 8 => {},
|
||||
4 ..= 8 => {},
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@ error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied
|
||||
--> $DIR/specialization-wfcheck.rs:7:17
|
||||
|
|
||||
LL | default impl<U> Foo<'static, U> for () {}
|
||||
| ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U`
|
||||
|
|
||||
= help: consider adding a `where U: std::cmp::Eq` bound
|
||||
| - ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U`
|
||||
| |
|
||||
| help: consider restricting this bound: `U: std::cmp::Eq`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -0,0 +1,25 @@
|
||||
// Running rustfix would cause the same suggestion to be applied multiple times, which results in
|
||||
// invalid code.
|
||||
|
||||
trait Parent {
|
||||
type Ty;
|
||||
type Assoc: Child<Self::Ty>;
|
||||
}
|
||||
|
||||
trait Child<T> {}
|
||||
|
||||
struct ChildWrapper<T>(T);
|
||||
|
||||
impl<A, T> Child<A> for ChildWrapper<T> where T: Child<A> {}
|
||||
|
||||
struct ParentWrapper<T>(T);
|
||||
|
||||
impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
||||
//~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
//~| ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
type Ty = A;
|
||||
type Assoc = ChildWrapper<T::Assoc>;
|
||||
//~^ ERROR the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,43 @@
|
||||
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:17:1
|
||||
|
|
||||
LL | trait Parent {
|
||||
| ------------ required by `Parent`
|
||||
...
|
||||
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
||||
| ^ - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
|
||||
| _|
|
||||
| |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | type Ty = A;
|
||||
LL | | type Assoc = ChildWrapper<T::Assoc>;
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
|
||||
|
||||
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:17:28
|
||||
|
|
||||
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
||||
| ^^^^^^ - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
|
||||
| |
|
||||
| the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `Child<A>` for `ChildWrapper<<T as Parent>::Assoc>`
|
||||
|
||||
error[E0277]: the trait bound `<T as Parent>::Assoc: Child<A>` is not satisfied
|
||||
--> $DIR/missing-assoc-type-bound-restriction.rs:21:5
|
||||
|
|
||||
LL | trait Parent {
|
||||
| ------------ required by `Parent`
|
||||
...
|
||||
LL | impl<A, T: Parent<Ty = A>> Parent for ParentWrapper<T> {
|
||||
| - help: consider further restricting the associated type: `where <T as Parent>::Assoc: Child<A>`
|
||||
...
|
||||
LL | type Assoc = ChildWrapper<T::Assoc>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child<A>` is not implemented for `<T as Parent>::Assoc`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
31
src/test/ui/suggestions/restrict-type-argument.rs
Normal file
31
src/test/ui/suggestions/restrict-type-argument.rs
Normal file
@ -0,0 +1,31 @@
|
||||
fn is_send<T: Send>(val: T) {}
|
||||
|
||||
fn use_impl_sync(val: impl Sync) {
|
||||
is_send(val); //~ ERROR `impl Sync` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn use_where<S>(val: S) where S: Sync {
|
||||
is_send(val); //~ ERROR `S` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn use_bound<S: Sync>(val: S) {
|
||||
is_send(val); //~ ERROR `S` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn use_bound_2<
|
||||
S // Make sure we can synthezise a correct suggestion span for this case
|
||||
:
|
||||
Sync
|
||||
>(val: S) {
|
||||
is_send(val); //~ ERROR `S` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn use_bound_and_where<S: Sync>(val: S) where S: std::fmt::Debug {
|
||||
is_send(val); //~ ERROR `S` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn use_unbound<S>(val: S) {
|
||||
is_send(val); //~ ERROR `S` cannot be sent between threads safely
|
||||
}
|
||||
|
||||
fn main() {}
|
83
src/test/ui/suggestions/restrict-type-argument.stderr
Normal file
83
src/test/ui/suggestions/restrict-type-argument.stderr
Normal file
@ -0,0 +1,83 @@
|
||||
error[E0277]: `impl Sync` cannot be sent between threads safely
|
||||
--> $DIR/restrict-type-argument.rs:4:13
|
||||
|
|
||||
LL | fn is_send<T: Send>(val: T) {}
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
LL |
|
||||
LL | fn use_impl_sync(val: impl Sync) {
|
||||
| --------- help: consider further restricting this bound: `impl Sync + std::marker::Send`
|
||||
LL | is_send(val);
|
||||
| ^^^ `impl Sync` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `impl Sync`
|
||||
|
||||
error[E0277]: `S` cannot be sent between threads safely
|
||||
--> $DIR/restrict-type-argument.rs:8:13
|
||||
|
|
||||
LL | fn is_send<T: Send>(val: T) {}
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
...
|
||||
LL | fn use_where<S>(val: S) where S: Sync {
|
||||
| - help: consider further restricting type parameter `S`: `, S: std::marker::Send`
|
||||
LL | is_send(val);
|
||||
| ^^^ `S` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `S`
|
||||
|
||||
error[E0277]: `S` cannot be sent between threads safely
|
||||
--> $DIR/restrict-type-argument.rs:12:13
|
||||
|
|
||||
LL | fn is_send<T: Send>(val: T) {}
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
...
|
||||
LL | fn use_bound<S: Sync>(val: S) {
|
||||
| -- help: consider further restricting this bound: `S: std::marker::Send +`
|
||||
LL | is_send(val);
|
||||
| ^^^ `S` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `S`
|
||||
|
||||
error[E0277]: `S` cannot be sent between threads safely
|
||||
--> $DIR/restrict-type-argument.rs:20:13
|
||||
|
|
||||
LL | fn is_send<T: Send>(val: T) {}
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
...
|
||||
LL | / S // Make sure we can synthezise a correct suggestion span for this case
|
||||
LL | | :
|
||||
| |_____- help: consider further restricting this bound: `S: std::marker::Send +`
|
||||
...
|
||||
LL | is_send(val);
|
||||
| ^^^ `S` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `S`
|
||||
|
||||
error[E0277]: `S` cannot be sent between threads safely
|
||||
--> $DIR/restrict-type-argument.rs:24:13
|
||||
|
|
||||
LL | fn is_send<T: Send>(val: T) {}
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
...
|
||||
LL | fn use_bound_and_where<S: Sync>(val: S) where S: std::fmt::Debug {
|
||||
| - help: consider further restricting type parameter `S`: `, S: std::marker::Send`
|
||||
LL | is_send(val);
|
||||
| ^^^ `S` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `S`
|
||||
|
||||
error[E0277]: `S` cannot be sent between threads safely
|
||||
--> $DIR/restrict-type-argument.rs:28:13
|
||||
|
|
||||
LL | fn is_send<T: Send>(val: T) {}
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
...
|
||||
LL | fn use_unbound<S>(val: S) {
|
||||
| - help: consider restricting this bound: `S: std::marker::Send`
|
||||
LL | is_send(val);
|
||||
| ^^^ `S` cannot be sent between threads safely
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `S`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -4,9 +4,10 @@ error[E0277]: the trait bound `T: Foo` is not satisfied
|
||||
LL | trait A<T: Foo> {}
|
||||
| --------------- required by `A`
|
||||
LL | trait B<T> = A<T>;
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: Foo` bound
|
||||
| ^^^^^^^^-^^^^^^^^^
|
||||
| | |
|
||||
| | help: consider restricting this bound: `T: Foo`
|
||||
| the trait `Foo` is not implemented for `T`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,9 +5,9 @@ LL | struct Foo<T:Trait> {
|
||||
| ------------------- required by `Foo`
|
||||
...
|
||||
LL | impl<T> Foo<T> {
|
||||
| ^^^^^^ the trait `Trait` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: Trait` bound
|
||||
| - ^^^^^^ the trait `Trait` is not implemented for `T`
|
||||
| |
|
||||
| help: consider restricting this bound: `T: Trait`
|
||||
|
||||
error[E0277]: the trait bound `isize: Trait` is not satisfied
|
||||
--> $DIR/trait-bounds-on-structs-and-enums.rs:19:5
|
||||
@ -33,10 +33,10 @@ error[E0277]: the trait bound `U: Trait` is not satisfied
|
||||
LL | struct Foo<T:Trait> {
|
||||
| ------------------- required by `Foo`
|
||||
...
|
||||
LL | struct Badness<U> {
|
||||
| - help: consider restricting this bound: `U: Trait`
|
||||
LL | b: Foo<U>,
|
||||
| ^^^^^^^^^ the trait `Trait` is not implemented for `U`
|
||||
|
|
||||
= help: consider adding a `where U: Trait` bound
|
||||
|
||||
error[E0277]: the trait bound `V: Trait` is not satisfied
|
||||
--> $DIR/trait-bounds-on-structs-and-enums.rs:31:21
|
||||
@ -44,10 +44,10 @@ error[E0277]: the trait bound `V: Trait` is not satisfied
|
||||
LL | enum Bar<T:Trait> {
|
||||
| ----------------- required by `Bar`
|
||||
...
|
||||
LL | enum MoreBadness<V> {
|
||||
| - help: consider restricting this bound: `V: Trait`
|
||||
LL | EvenMoreBadness(Bar<V>),
|
||||
| ^^^^^^ the trait `Trait` is not implemented for `V`
|
||||
|
|
||||
= help: consider adding a `where V: Trait` bound
|
||||
|
||||
error[E0277]: the trait bound `i32: Trait` is not satisfied
|
||||
--> $DIR/trait-bounds-on-structs-and-enums.rs:35:5
|
||||
|
@ -1,6 +1,9 @@
|
||||
error[E0277]: the size for values of type `U` cannot be known at compilation time
|
||||
--> $DIR/trait-suggest-where-clause.rs:9:20
|
||||
|
|
||||
LL | fn check<T: Iterator, U: ?Sized>() {
|
||||
| -- help: consider further restricting this bound: `U: std::marker::Sized +`
|
||||
LL | // suggest a where-clause, if needed
|
||||
LL | mem::size_of::<U>();
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
@ -11,11 +14,13 @@ LL | pub const fn size_of<T>() -> usize {
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `U`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where U: std::marker::Sized` bound
|
||||
|
||||
error[E0277]: the size for values of type `U` cannot be known at compilation time
|
||||
--> $DIR/trait-suggest-where-clause.rs:12:5
|
||||
|
|
||||
LL | fn check<T: Iterator, U: ?Sized>() {
|
||||
| -- help: consider further restricting this bound: `U: std::marker::Sized +`
|
||||
...
|
||||
LL | mem::size_of::<Misc<U>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
@ -26,7 +31,6 @@ LL | pub const fn size_of<T>() -> usize {
|
||||
|
|
||||
= help: within `Misc<U>`, the trait `std::marker::Sized` is not implemented for `U`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where U: std::marker::Sized` bound
|
||||
= note: required because it appears within the type `Misc<U>`
|
||||
|
||||
error[E0277]: the trait bound `u64: std::convert::From<T>` is not satisfied
|
||||
@ -35,7 +39,6 @@ error[E0277]: the trait bound `u64: std::convert::From<T>` is not satisfied
|
||||
LL | <u64 as From<T>>::from;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<T>` is not implemented for `u64`
|
||||
|
|
||||
= help: consider adding a `where u64: std::convert::From<T>` bound
|
||||
= note: required by `std::convert::From::from`
|
||||
|
||||
error[E0277]: the trait bound `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
|
||||
@ -44,7 +47,6 @@ error[E0277]: the trait bound `u64: std::convert::From<<T as std::iter::Iterator
|
||||
LL | <u64 as From<<T as Iterator>::Item>>::from;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented for `u64`
|
||||
|
|
||||
= help: consider adding a `where u64: std::convert::From<<T as std::iter::Iterator>::Item>` bound
|
||||
= note: required by `std::convert::From::from`
|
||||
|
||||
error[E0277]: the trait bound `Misc<_>: std::convert::From<T>` is not satisfied
|
||||
|
@ -7,10 +7,10 @@ LL | c.same_as(22)
|
||||
error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
|
||||
--> $DIR/traits-repeated-supertrait-ambig.rs:30:7
|
||||
|
|
||||
LL | fn with_trait<C:CompareToInts>(c: &C) -> bool {
|
||||
| -- help: consider further restricting this bound: `C: CompareTo<i32> +`
|
||||
LL | c.same_as(22)
|
||||
| ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
|
||||
|
|
||||
= help: consider adding a `where C: CompareTo<i32>` bound
|
||||
|
||||
error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
|
||||
--> $DIR/traits-repeated-supertrait-ambig.rs:34:5
|
||||
@ -27,10 +27,10 @@ error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
|
||||
LL | fn same_as(&self, t: T) -> bool;
|
||||
| -------------------------------- required by `CompareTo::same_as`
|
||||
...
|
||||
LL | fn with_ufcs2<C:CompareToInts>(c: &C) -> bool {
|
||||
| -- help: consider further restricting this bound: `C: CompareTo<i32> +`
|
||||
LL | CompareTo::same_as(c, 22)
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
|
||||
|
|
||||
= help: consider adding a `where C: CompareTo<i32>` bound
|
||||
|
||||
error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied
|
||||
--> $DIR/traits-repeated-supertrait-ambig.rs:42:23
|
||||
|
@ -9,8 +9,10 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
|
||||
|
|
||||
LL | type Underconstrained<T: Trait> = impl 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
|
||||
...
|
||||
LL | fn underconstrain<T>(_: T) -> Underconstrained<T> {
|
||||
| - help: consider restricting this bound: `T: Trait`
|
||||
|
|
||||
= help: consider adding a `where T: Trait` bound
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -15,9 +15,11 @@ error[E0277]: `U` doesn't implement `std::fmt::Debug`
|
||||
|
|
||||
LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
||||
...
|
||||
LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
|
||||
| - help: consider restricting this bound: `U: std::fmt::Debug`
|
||||
|
|
||||
= help: the trait `std::fmt::Debug` is not implemented for `U`
|
||||
= help: consider adding a `where U: std::fmt::Debug` bound
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: `V` doesn't implement `std::fmt::Debug`
|
||||
@ -25,9 +27,11 @@ error[E0277]: `V` doesn't implement `std::fmt::Debug`
|
||||
|
|
||||
LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
|
||||
...
|
||||
LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
|
||||
| - help: consider restricting this bound: `V: std::fmt::Debug`
|
||||
|
|
||||
= help: the trait `std::fmt::Debug` is not implemented for `V`
|
||||
= help: consider adding a `where V: std::fmt::Debug` bound
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -52,9 +52,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
LL | trait Super<T: Copy> { }
|
||||
| -------------------- required by `Super`
|
||||
LL | trait Base<T = String>: Super<T> { }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
||||
= help: consider adding a `where T: std::marker::Copy` bound
|
||||
| ^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| | |
|
||||
| | help: consider restricting this bound: `T: std::marker::Copy`
|
||||
| the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
||||
error[E0277]: cannot add `u8` to `i32`
|
||||
--> $DIR/type-check-defaults.rs:24:66
|
||||
|
@ -4,10 +4,10 @@ error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
|
||||
LL | fn op(_: T) -> Self;
|
||||
| -------------------- required by `Tr::op`
|
||||
...
|
||||
LL | fn test<U>(u: U) -> Self {
|
||||
| - help: consider further restricting `Self`: `where Self: Tr<U>`
|
||||
LL | Tr::op(u)
|
||||
| ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: Tr<U>` bound
|
||||
|
||||
error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
|
||||
--> $DIR/type-params-in-different-spaces-2.rs:16:9
|
||||
@ -15,10 +15,10 @@ error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
|
||||
LL | fn op(_: T) -> Self;
|
||||
| -------------------- required by `Tr::op`
|
||||
...
|
||||
LL | fn test<U>(u: U) -> Self {
|
||||
| - help: consider further restricting `Self`: `where Self: Tr<U>`
|
||||
LL | Tr::op(u)
|
||||
| ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: Tr<U>` bound
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
// run-rustfix
|
||||
// Test that we do not consider associated types to be sendable without
|
||||
// some applicable trait bound (and we don't ICE).
|
||||
#![allow(dead_code)]
|
||||
|
||||
trait Trait {
|
||||
type AssocType;
|
||||
fn dummy(&self) { }
|
||||
}
|
||||
fn bar<T:Trait+Send>() where <T as Trait>::AssocType: std::marker::Send {
|
||||
is_send::<T::AssocType>(); //~ ERROR E0277
|
||||
}
|
||||
|
||||
fn is_send<T:Send>() {
|
||||
}
|
||||
|
||||
fn main() { }
|
@ -1,5 +1,7 @@
|
||||
// run-rustfix
|
||||
// Test that we do not consider associated types to be sendable without
|
||||
// some applicable trait bound (and we don't ICE).
|
||||
#![allow(dead_code)]
|
||||
|
||||
trait Trait {
|
||||
type AssocType;
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0277]: `<T as Trait>::AssocType` cannot be sent between threads safely
|
||||
--> $DIR/typeck-default-trait-impl-assoc-type.rs:9:5
|
||||
--> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5
|
||||
|
|
||||
LL | fn bar<T:Trait+Send>() {
|
||||
| - help: consider further restricting the associated type: `where <T as Trait>::AssocType: std::marker::Send`
|
||||
LL | is_send::<T::AssocType>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ `<T as Trait>::AssocType` cannot be sent between threads safely
|
||||
...
|
||||
@ -8,7 +10,6 @@ LL | fn is_send<T:Send>() {
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `<T as Trait>::AssocType`
|
||||
= help: consider adding a `where <T as Trait>::AssocType: std::marker::Send` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0277]: `T` cannot be sent between threads safely
|
||||
--> $DIR/typeck-default-trait-impl-send-param.rs:5:15
|
||||
|
|
||||
LL | fn foo<T>() {
|
||||
| - help: consider restricting this bound: `T: std::marker::Send`
|
||||
LL | is_send::<T>()
|
||||
| ^ `T` cannot be sent between threads safely
|
||||
...
|
||||
@ -8,7 +10,6 @@ LL | fn is_send<T:Send>() {
|
||||
| ------- ---- required by this bound in `is_send`
|
||||
|
|
||||
= help: the trait `std::marker::Send` is not implemented for `T`
|
||||
= help: consider adding a `where T: std::marker::Send` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,34 +1,37 @@
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/union-sized-field.rs:4:5
|
||||
|
|
||||
LL | union Foo<T: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
LL | value: T,
|
||||
| ^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: no field of a union may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/union-sized-field.rs:9:5
|
||||
|
|
||||
LL | struct Foo2<T: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
LL | value: T,
|
||||
| ^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: only the last field of a struct may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/union-sized-field.rs:15:11
|
||||
|
|
||||
LL | enum Foo3<T: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
LL | Value(T),
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
@ -4,11 +4,12 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim
|
||||
LL | fn bar<T: Sized>() { }
|
||||
| --- - required by this bound in `bar`
|
||||
LL | fn foo<T: ?Sized>() { bar::<T>() }
|
||||
| ^ doesn't have a size known at compile-time
|
||||
| -- ^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,11 +5,12 @@ LL | enum Foo<U> { FooSome(U), FooNone }
|
||||
| ----------- required by `Foo`
|
||||
LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
|
||||
LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,45 +1,53 @@
|
||||
error[E0277]: the size for values of type `W` cannot be known at compilation time
|
||||
--> $DIR/unsized-enum2.rs:23:8
|
||||
|
|
||||
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `W: std::marker::Sized +`
|
||||
LL | // parameter
|
||||
LL | VA(W),
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `W`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where W: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized-enum2.rs:25:8
|
||||
|
|
||||
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
...
|
||||
LL | VB{x: X},
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `Y` cannot be known at compilation time
|
||||
--> $DIR/unsized-enum2.rs:27:15
|
||||
|
|
||||
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `Y: std::marker::Sized +`
|
||||
...
|
||||
LL | VC(isize, Y),
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Y`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Y: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `Z` cannot be known at compilation time
|
||||
--> $DIR/unsized-enum2.rs:29:18
|
||||
|
|
||||
LL | enum E<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `Z: std::marker::Sized +`
|
||||
...
|
||||
LL | VD{u: isize, x: Z},
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Z`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Z: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
|
@ -5,11 +5,12 @@ LL | struct S5<Y>(Y);
|
||||
| ---------------- required by `S5`
|
||||
LL |
|
||||
LL | impl<X: ?Sized> S5<X> {
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,11 +5,12 @@ LL | struct Foo<T> { data: T }
|
||||
| ------------- required by `Foo`
|
||||
LL | fn foo1<T>() { not_sized::<Foo<T>>() } // Hunky dory.
|
||||
LL | fn foo2<T: ?Sized>() { not_sized::<Foo<T>>() }
|
||||
| ^^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/unsized-struct.rs:13:24
|
||||
@ -18,11 +19,12 @@ LL | fn is_sized<T:Sized>() { }
|
||||
| -------- - required by this bound in `is_sized`
|
||||
...
|
||||
LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
|
||||
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `T: std::marker::Sized +`
|
||||
|
|
||||
= help: within `Bar<T>`, the trait `std::marker::Sized` is not implemented for `T`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where T: std::marker::Sized` bound
|
||||
= note: required because it appears within the type `Bar<T>`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -5,11 +5,12 @@ LL | struct S5<Y>(Y);
|
||||
| ---------------- required by `S5`
|
||||
LL |
|
||||
LL | impl<X: ?Sized> T3<X> for S5<X> {
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,11 +2,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
|
||||
--> $DIR/unsized-trait-impl-trait-arg.rs:8:17
|
||||
|
|
||||
LL | impl<X: ?Sized> T2<X> for S4<X> {
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized3.rs:7:13
|
||||
|
|
||||
LL | fn f1<X: ?Sized>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f2::<X>(x);
|
||||
| ^ doesn't have a size known at compile-time
|
||||
...
|
||||
@ -9,11 +11,12 @@ LL | fn f2<X>(x: &X) {
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized3.rs:18:13
|
||||
|
|
||||
LL | fn f3<X: ?Sized + T>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f4::<X>(x);
|
||||
| ^ doesn't have a size known at compile-time
|
||||
...
|
||||
@ -22,7 +25,6 @@ LL | fn f4<X: T>(x: &X) {
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized3.rs:33:8
|
||||
@ -30,35 +32,38 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
|
||||
LL | fn f5<Y>(x: &Y) {}
|
||||
| -- - required by this bound in `f5`
|
||||
...
|
||||
LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f5(x1);
|
||||
| ^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `S<X>`, the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: required because it appears within the type `S<X>`
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized3.rs:40:8
|
||||
|
|
||||
LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f5(&(*x1, 34));
|
||||
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `S<X>`, the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: required because it appears within the type `S<X>`
|
||||
= note: only the last element of a tuple may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized3.rs:45:9
|
||||
|
|
||||
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f5(&(32, *x1));
|
||||
| ^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `({integer}, S<X>)`, the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: required because it appears within the type `S<X>`
|
||||
= note: required because it appears within the type `({integer}, S<X>)`
|
||||
= note: tuples must have a statically known size to be initialized
|
||||
@ -69,12 +74,13 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
|
||||
LL | fn f5<Y>(x: &Y) {}
|
||||
| -- - required by this bound in `f5`
|
||||
...
|
||||
LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f5(&(32, *x1));
|
||||
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: within `({integer}, S<X>)`, the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: required because it appears within the type `S<X>`
|
||||
= note: required because it appears within the type `({integer}, S<X>)`
|
||||
|
||||
|
@ -1,23 +1,26 @@
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized5.rs:4:5
|
||||
|
|
||||
LL | struct S1<X: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f1: X,
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: only the last field of a struct may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized5.rs:10:5
|
||||
|
|
||||
LL | struct S2<X: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | f: isize,
|
||||
LL | g: X,
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: only the last field of a struct may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
@ -43,23 +46,25 @@ LL | f: [u8],
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized5.rs:25:8
|
||||
|
|
||||
LL | enum E<X: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | V1(X, isize),
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized5.rs:29:8
|
||||
|
|
||||
LL | enum F<X: ?Sized> {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | V2{f1: X, f: isize},
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: no field of an enum variant may have a dynamically sized type
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
@ -1,129 +1,148 @@
|
||||
error[E0277]: the size for values of type `Y` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:9:9
|
||||
|
|
||||
LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `Y: std::marker::Sized +`
|
||||
...
|
||||
LL | let y: Y;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Y`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Y: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:7:12
|
||||
|
|
||||
LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | let _: W; // <-- this is OK, no bindings created, no initializer.
|
||||
LL | let _: (isize, (X, isize));
|
||||
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: only the last element of a tuple may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `Z` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:11:12
|
||||
|
|
||||
LL | fn f1<W: ?Sized, X: ?Sized, Y: ?Sized, Z: ?Sized>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `Z: std::marker::Sized +`
|
||||
...
|
||||
LL | let y: (isize, (Z, usize));
|
||||
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Z`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Z: std::marker::Sized` bound
|
||||
= note: only the last element of a tuple may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:15:9
|
||||
|
|
||||
LL | fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | let y: X;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `Y` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:17:12
|
||||
|
|
||||
LL | fn f2<X: ?Sized, Y: ?Sized>(x: &X) {
|
||||
| -- help: consider further restricting this bound: `Y: std::marker::Sized +`
|
||||
...
|
||||
LL | let y: (isize, (Y, isize));
|
||||
| ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Y`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Y: std::marker::Sized` bound
|
||||
= note: only the last element of a tuple may have a dynamically sized type
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:22:9
|
||||
|
|
||||
LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | let y: X = *x1;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:24:9
|
||||
|
|
||||
LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
...
|
||||
LL | let y = *x2;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:26:10
|
||||
|
|
||||
LL | fn f3<X: ?Sized>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
...
|
||||
LL | let (y, z) = (*x3, 4);
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:30:9
|
||||
|
|
||||
LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
LL | let y: X = *x1;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:32:9
|
||||
|
|
||||
LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
...
|
||||
LL | let y = *x2;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error[E0277]: the size for values of type `X` cannot be known at compilation time
|
||||
--> $DIR/unsized6.rs:34:10
|
||||
|
|
||||
LL | fn f4<X: ?Sized + T>(x1: Box<X>, x2: Box<X>, x3: Box<X>) {
|
||||
| -- help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
...
|
||||
LL | let (y, z) = (*x3, 4);
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
@ -131,11 +150,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
|
||||
--> $DIR/unsized6.rs:38:18
|
||||
|
|
||||
LL | fn g1<X: ?Sized>(x: X) {}
|
||||
| ^ doesn't have a size known at compile-time
|
||||
| -- ^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
@ -143,11 +163,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
|
||||
--> $DIR/unsized6.rs:40:22
|
||||
|
|
||||
LL | fn g2<X: ?Sized + T>(x: X) {}
|
||||
| ^ doesn't have a size known at compile-time
|
||||
| -- ^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
|
@ -2,11 +2,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
|
||||
--> $DIR/unsized7.rs:12:21
|
||||
|
|
||||
LL | impl<X: ?Sized + T> T1<X> for S3<X> {
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
| -- ^^^^^ doesn't have a size known at compile-time
|
||||
| |
|
||||
| help: consider further restricting this bound: `X: std::marker::Sized +`
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `X`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where X: std::marker::Sized` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -6,12 +6,11 @@ LL | trait ExtraCopy<T:Copy> { }
|
||||
LL |
|
||||
LL | / enum SomeEnum<T,U>
|
||||
LL | | where T: ExtraCopy<U>
|
||||
| | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy`
|
||||
LL | | {
|
||||
LL | | SomeVariant(T,U)
|
||||
LL | | }
|
||||
| |_^ the trait `std::marker::Copy` is not implemented for `U`
|
||||
|
|
||||
= help: consider adding a `where U: std::marker::Copy` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,10 +4,11 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
|
||||
LL | struct IsCopy<T:Copy> {
|
||||
| --------------------- required by `IsCopy`
|
||||
...
|
||||
LL | enum AnotherEnum<A> {
|
||||
| - help: consider restricting this bound: `A: std::marker::Copy`
|
||||
LL | AnotherVariant {
|
||||
LL | f: IsCopy<A>
|
||||
| ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
|
||||
|
|
||||
= help: consider adding a `where A: std::marker::Copy` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied
|
||||
LL | struct IsCopy<T:Copy> {
|
||||
| --------------------- required by `IsCopy`
|
||||
...
|
||||
LL | enum SomeEnum<A> {
|
||||
| - help: consider restricting this bound: `A: std::marker::Copy`
|
||||
LL | SomeVariant(IsCopy<A>)
|
||||
| ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A`
|
||||
|
|
||||
= help: consider adding a `where A: std::marker::Copy` bound
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -4,12 +4,13 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied
|
||||
LL | trait ExtraCopy<T:Copy> { }
|
||||
| ----------------------- required by `ExtraCopy`
|
||||
LL |
|
||||
LL | / fn foo<T,U>() where T: ExtraCopy<U>
|
||||
LL | fn foo<T,U>() where T: ExtraCopy<U>
|
||||
| ^ - help: consider further restricting type parameter `U`: `, U: std::marker::Copy`
|
||||
| _|
|
||||
| |
|
||||
LL | | {
|
||||
LL | | }
|
||||
| |_^ the trait `std::marker::Copy` is not implemented for `U`
|
||||
|
|
||||
= help: consider adding a `where U: std::marker::Copy` bound
|
||||
|
||||
error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time
|
||||
--> $DIR/wf-fn-where-clause.rs:12:1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user