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:
bors 2019-10-19 14:01:35 +00:00
commit c49187530d
123 changed files with 1464 additions and 616 deletions

View File

@ -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))
}
}

View File

@ -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
///

View File

@ -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
///

View File

@ -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<_>>();

View File

@ -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., `_`).

View File

@ -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,

View File

@ -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| {
&param_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(

View File

@ -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, _)) => {

View File

@ -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,

View File

@ -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,
) {

View File

@ -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,
};

View File

@ -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 } |

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() {
}

View File

@ -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;

View File

@ -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

View File

@ -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() {
}

View File

@ -1,3 +1,6 @@
// run-rustfix
#![allow(unused_variables)]
trait Get {
type Value;
fn get(&self) -> <Self as Get>::Value;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() { }

View File

@ -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.

View File

@ -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

View 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() {
}

View File

@ -1,3 +1,6 @@
// run-rustfix
#![allow(dead_code, unused_variables)]
trait Get {
type Value: ?Sized;
fn get(&self) -> <Self as Get>::Value;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
_ => {},
}
}

View File

@ -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 => {},
| ^

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
_ => {}
}

View File

@ -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`.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -2,7 +2,6 @@
// Test that codegen works correctly when there are multiple refutable
// patterns in match expression.
enum Foo {
FooUint(usize),
FooNullary,

View File

@ -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

View File

@ -1,5 +1,5 @@
// run-pass
#![allow(unused_imports)]
#![allow(unused_imports, overlapping_patterns)]
// pretty-expanded FIXME #23616
use m::{START, END};

View File

@ -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

View File

@ -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>`

View File

@ -1,4 +1,6 @@
// run-pass
#![allow(overlapping_patterns)]
fn main() {
let x = 'a';

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>`

View File

@ -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>`

View File

@ -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
_ => {}
};
}

View File

@ -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 => {}
| ^^^^^^^

View File

@ -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

View File

@ -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>`

View File

@ -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};

View File

@ -3,7 +3,7 @@ pub fn main() {
let i = 5;
match &&&&i {
1 ..= 3 => panic!(),
3 ..= 8 => {},
4 ..= 8 => {},
_ => panic!(),
}
}

View File

@ -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

View File

@ -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() {}

View File

@ -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`.

View 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() {}

View 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`.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() { }

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>)`

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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