mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #71230 - Dylan-DPC:rollup-rofigbv, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #70578 (Add long error explanation for E0657) - #70910 (Hides default fns inside Fuse impl to avoid exposing it to any crate) - #71164 (reword Miri validity errors: undefined -> uninitialized) - #71182 (Add some regression tests) - #71206 (Miri error messages: avoid try terminology) - #71220 (Dogfood or_patterns in the standard library) - #71225 (Fix typo in Default trait docs: Provides -> Provide) Failed merges: r? @ghost
This commit is contained in:
commit
861996e138
@ -2058,12 +2058,7 @@ where
|
||||
(Excluded(s), Excluded(e)) if s == e => {
|
||||
panic!("range start and end are equal and excluded in BTreeMap")
|
||||
}
|
||||
(Included(s), Included(e))
|
||||
| (Included(s), Excluded(e))
|
||||
| (Excluded(s), Included(e))
|
||||
| (Excluded(s), Excluded(e))
|
||||
if s > e =>
|
||||
{
|
||||
(Included(s) | Excluded(s), Included(e) | Excluded(e)) if s > e => {
|
||||
panic!("range start is greater than range end in BTreeMap")
|
||||
}
|
||||
_ => {}
|
||||
|
@ -103,6 +103,7 @@
|
||||
#![feature(new_uninit)]
|
||||
#![feature(nll)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(pattern)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_offset_from)]
|
||||
|
@ -858,7 +858,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn le(&self, other: &Rhs) -> bool {
|
||||
matches!(self.partial_cmp(other), Some(Less) | Some(Equal))
|
||||
matches!(self.partial_cmp(other), Some(Less | Equal))
|
||||
}
|
||||
|
||||
/// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
|
||||
@ -895,7 +895,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
#[must_use]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn ge(&self, other: &Rhs) -> bool {
|
||||
matches!(self.partial_cmp(other), Some(Greater) | Some(Equal))
|
||||
matches!(self.partial_cmp(other), Some(Greater | Equal))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
///
|
||||
/// ## How can I implement `Default`?
|
||||
///
|
||||
/// Provides an implementation for the `default()` method that returns the value of
|
||||
/// Provide an implementation for the `default()` method that returns the value of
|
||||
/// your type that should be the default:
|
||||
///
|
||||
/// ```
|
||||
|
@ -44,6 +44,19 @@ macro_rules! fuse {
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
|
||||
// Implementing this as a directly-expanded macro helps codegen performance.
|
||||
macro_rules! unchecked {
|
||||
($self:ident) => {
|
||||
match $self {
|
||||
Fuse { iter: Some(iter) } => iter,
|
||||
// SAFETY: the specialized iterator never sets `None`
|
||||
Fuse { iter: None } => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Any implementation here is made internal to avoid exposing default fns outside this trait
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Fuse<I>
|
||||
where
|
||||
@ -51,6 +64,193 @@ where
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
FuseImpl::next(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
FuseImpl::nth(self, n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
FuseImpl::last(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
FuseImpl::count(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
FuseImpl::size_hint(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
FuseImpl::try_fold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
FuseImpl::fold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
FuseImpl::find(self, predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> DoubleEndedIterator for Fuse<I>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
FuseImpl::next_back(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
|
||||
FuseImpl::nth_back(self, n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
FuseImpl::try_rfold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
FuseImpl::rfold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
FuseImpl::rfind(self, predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Fuse<I>
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
FuseImpl::len(self)
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
FuseImpl::is_empty(self)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<I> TrustedRandomAccess for Fuse<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
|
||||
match self.iter {
|
||||
Some(ref mut iter) => iter.get_unchecked(i),
|
||||
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
|
||||
None => intrinsics::unreachable(),
|
||||
}
|
||||
}
|
||||
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
}
|
||||
|
||||
// Fuse specialization trait
|
||||
#[doc(hidden)]
|
||||
trait FuseImpl<I> {
|
||||
type Item;
|
||||
|
||||
// Functions specific to any normal Iterators
|
||||
fn next(&mut self) -> Option<Self::Item>;
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item>;
|
||||
fn last(self) -> Option<Self::Item>;
|
||||
fn count(self) -> usize;
|
||||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>;
|
||||
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc;
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool;
|
||||
|
||||
// Functions specific to DoubleEndedIterators
|
||||
fn next_back(&mut self) -> Option<Self::Item>
|
||||
where
|
||||
I: DoubleEndedIterator;
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item>
|
||||
where
|
||||
I: DoubleEndedIterator;
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
I: DoubleEndedIterator;
|
||||
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
I: DoubleEndedIterator;
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator;
|
||||
|
||||
// Functions specific to ExactSizeIterator
|
||||
fn len(&self) -> usize
|
||||
where
|
||||
I: ExactSizeIterator;
|
||||
fn is_empty(&self) -> bool
|
||||
where
|
||||
I: ExactSizeIterator;
|
||||
}
|
||||
|
||||
// General Fuse impl
|
||||
#[doc(hidden)]
|
||||
impl<I> FuseImpl<I> for Fuse<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
default fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
fuse!(self.iter.next())
|
||||
@ -117,20 +317,20 @@ where
|
||||
{
|
||||
fuse!(self.iter.find(predicate))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> DoubleEndedIterator for Fuse<I>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
default fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.next_back())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
|
||||
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.nth_back(n))
|
||||
}
|
||||
|
||||
@ -140,6 +340,7 @@ where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
if let Some(ref mut iter) = self.iter {
|
||||
acc = iter.try_rfold(acc, fold)?;
|
||||
@ -152,6 +353,7 @@ where
|
||||
default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
if let Some(iter) = self.iter {
|
||||
acc = iter.rfold(acc, fold);
|
||||
@ -163,24 +365,27 @@ where
|
||||
default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.rfind(predicate))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Fuse<I>
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
default fn len(&self) -> usize {
|
||||
#[inline]
|
||||
default fn len(&self) -> usize
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
match self.iter {
|
||||
Some(ref iter) => iter.len(),
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
default fn is_empty(&self) -> bool {
|
||||
#[inline]
|
||||
default fn is_empty(&self) -> bool
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
match self.iter {
|
||||
Some(ref iter) => iter.is_empty(),
|
||||
None => true,
|
||||
@ -188,20 +393,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
|
||||
// Implementing this as a directly-expanded macro helps codegen performance.
|
||||
macro_rules! unchecked {
|
||||
($self:ident) => {
|
||||
match $self {
|
||||
Fuse { iter: Some(iter) } => iter,
|
||||
// SAFETY: the specialized iterator never sets `None`
|
||||
Fuse { iter: None } => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> Iterator for Fuse<I>
|
||||
#[doc(hidden)]
|
||||
impl<I> FuseImpl<I> for Fuse<I>
|
||||
where
|
||||
I: FusedIterator,
|
||||
{
|
||||
@ -255,20 +448,20 @@ where
|
||||
{
|
||||
unchecked!(self).find(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> DoubleEndedIterator for Fuse<I>
|
||||
where
|
||||
I: DoubleEndedIterator + FusedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
fn next_back(&mut self) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
|
||||
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).nth_back(n)
|
||||
}
|
||||
|
||||
@ -278,6 +471,7 @@ where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).try_rfold(init, fold)
|
||||
}
|
||||
@ -286,6 +480,7 @@ where
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).rfold(init, fold)
|
||||
}
|
||||
@ -294,38 +489,24 @@ where
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).rfind(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Fuse<I>
|
||||
where
|
||||
I: ExactSizeIterator + FusedIterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
#[inline]
|
||||
fn len(&self) -> usize
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
unchecked!(self).len()
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
unchecked!(self).is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<I> TrustedRandomAccess for Fuse<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
unsafe fn get_unchecked(&mut self, i: usize) -> I::Item {
|
||||
match self.iter {
|
||||
Some(ref mut iter) => iter.get_unchecked(i),
|
||||
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
|
||||
None => intrinsics::unreachable(),
|
||||
}
|
||||
}
|
||||
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
}
|
||||
|
@ -3109,7 +3109,7 @@ pub trait Iterator {
|
||||
Self::Item: PartialOrd<I::Item>,
|
||||
Self: Sized,
|
||||
{
|
||||
matches!(self.partial_cmp(other), Some(Ordering::Less) | Some(Ordering::Equal))
|
||||
matches!(self.partial_cmp(other), Some(Ordering::Less | Ordering::Equal))
|
||||
}
|
||||
|
||||
/// Determines if the elements of this `Iterator` are lexicographically
|
||||
@ -3149,7 +3149,7 @@ pub trait Iterator {
|
||||
Self::Item: PartialOrd<I::Item>,
|
||||
Self: Sized,
|
||||
{
|
||||
matches!(self.partial_cmp(other), Some(Ordering::Greater) | Some(Ordering::Equal))
|
||||
matches!(self.partial_cmp(other), Some(Ordering::Greater | Ordering::Equal))
|
||||
}
|
||||
|
||||
/// Checks if the elements of this iterator are sorted.
|
||||
|
@ -105,6 +105,7 @@
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(no_core)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
@ -54,7 +54,7 @@ pub fn parse_decimal(s: &str) -> ParseResult<'_> {
|
||||
|
||||
match s.first() {
|
||||
None => Valid(Decimal::new(integral, b"", 0)),
|
||||
Some(&b'e') | Some(&b'E') => {
|
||||
Some(&b'e' | &b'E') => {
|
||||
if integral.is_empty() {
|
||||
return Invalid; // No digits before 'e'
|
||||
}
|
||||
@ -70,7 +70,7 @@ pub fn parse_decimal(s: &str) -> ParseResult<'_> {
|
||||
|
||||
match s.first() {
|
||||
None => Valid(Decimal::new(integral, fractional, 0)),
|
||||
Some(&b'e') | Some(&b'E') => parse_exp(integral, fractional, &s[1..]),
|
||||
Some(&b'e' | &b'E') => parse_exp(integral, fractional, &s[1..]),
|
||||
_ => Invalid, // Trailing junk after fractional part
|
||||
}
|
||||
}
|
||||
|
@ -422,14 +422,14 @@ fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static
|
||||
"+"
|
||||
}
|
||||
}
|
||||
(_, Sign::Minus) | (_, Sign::MinusRaw) => {
|
||||
(_, Sign::Minus | Sign::MinusRaw) => {
|
||||
if negative {
|
||||
"-"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
(_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => {
|
||||
(_, Sign::MinusPlus | Sign::MinusPlusRaw) => {
|
||||
if negative {
|
||||
"-"
|
||||
} else {
|
||||
|
@ -366,6 +366,7 @@ E0644: include_str!("./error_codes/E0644.md"),
|
||||
E0646: include_str!("./error_codes/E0646.md"),
|
||||
E0647: include_str!("./error_codes/E0647.md"),
|
||||
E0648: include_str!("./error_codes/E0648.md"),
|
||||
E0657: include_str!("./error_codes/E0657.md"),
|
||||
E0658: include_str!("./error_codes/E0658.md"),
|
||||
E0659: include_str!("./error_codes/E0659.md"),
|
||||
E0660: include_str!("./error_codes/E0660.md"),
|
||||
@ -597,7 +598,6 @@ E0751: include_str!("./error_codes/E0751.md"),
|
||||
// used in argument position
|
||||
E0640, // infer outlives requirements
|
||||
// E0645, // trait aliases not finished
|
||||
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
|
||||
E0667, // `impl Trait` in projections
|
||||
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
|
||||
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
|
||||
|
57
src/librustc_error_codes/error_codes/E0657.md
Normal file
57
src/librustc_error_codes/error_codes/E0657.md
Normal file
@ -0,0 +1,57 @@
|
||||
A lifetime bound on a trait implementation was captured at an incorrect place.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0657
|
||||
trait Id<T> {}
|
||||
trait Lt<'a> {}
|
||||
|
||||
impl<'a> Lt<'a> for () {}
|
||||
impl<T> Id<T> for T {}
|
||||
|
||||
fn free_fn_capture_hrtb_in_impl_trait()
|
||||
-> Box<for<'a> Id<impl Lt<'a>>> // error!
|
||||
{
|
||||
Box::new(())
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn impl_fn_capture_hrtb_in_impl_trait()
|
||||
-> Box<for<'a> Id<impl Lt<'a>>> // error!
|
||||
{
|
||||
Box::new(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here, you have used the inappropriate lifetime in the `impl Trait`,
|
||||
The `impl Trait` can only capture lifetimes bound at the fn or impl
|
||||
level.
|
||||
|
||||
To fix this we have to define the lifetime at the function or impl
|
||||
level and use that lifetime in the `impl Trait`. For example you can
|
||||
define the lifetime at the function:
|
||||
|
||||
```
|
||||
trait Id<T> {}
|
||||
trait Lt<'a> {}
|
||||
|
||||
impl<'a> Lt<'a> for () {}
|
||||
impl<T> Id<T> for T {}
|
||||
|
||||
fn free_fn_capture_hrtb_in_impl_trait<'b>()
|
||||
-> Box<for<'a> Id<impl Lt<'b>>> // ok!
|
||||
{
|
||||
Box::new(())
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn impl_fn_capture_hrtb_in_impl_trait<'b>()
|
||||
-> Box<for<'a> Id<impl Lt<'b>>> // ok!
|
||||
{
|
||||
Box::new(())
|
||||
}
|
||||
}
|
||||
```
|
@ -305,7 +305,7 @@ impl fmt::Debug for InvalidProgramInfo<'_> {
|
||||
Layout(ref err) => write!(f, "{}", err),
|
||||
TransmuteSizeDiff(from_ty, to_ty) => write!(
|
||||
f,
|
||||
"tried to transmute from {:?} to {:?}, but their sizes differed",
|
||||
"transmuting `{}` to `{}` is not possible, because these types do not have the same size",
|
||||
from_ty, to_ty
|
||||
),
|
||||
}
|
||||
@ -431,7 +431,7 @@ impl fmt::Debug for UndefinedBehaviorInfo {
|
||||
"using uninitialized data, but this operation requires initialized memory"
|
||||
),
|
||||
DeadLocal => write!(f, "accessing a dead local variable"),
|
||||
ReadFromReturnPlace => write!(f, "tried to read from the return place"),
|
||||
ReadFromReturnPlace => write!(f, "reading from return place"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -462,9 +462,9 @@ impl fmt::Debug for UnsupportedOpInfo {
|
||||
match self {
|
||||
Unsupported(ref msg) => write!(f, "{}", msg),
|
||||
ReadForeignStatic(did) => {
|
||||
write!(f, "tried to read from foreign (extern) static {:?}", did)
|
||||
write!(f, "cannot read from foreign (extern) static {:?}", did)
|
||||
}
|
||||
NoMirFor(did) => write!(f, "could not load MIR for {:?}", did),
|
||||
NoMirFor(did) => write!(f, "no MIR body is available for {:?}", did),
|
||||
ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
|
||||
ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
|
||||
}
|
||||
|
@ -322,7 +322,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||
let value = self.ecx.read_immediate(value)?;
|
||||
// Handle wide pointers.
|
||||
// Check metadata early, for better diagnostics
|
||||
let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path);
|
||||
let place = try_validation!(
|
||||
self.ecx.ref_to_mplace(value),
|
||||
format_args!("uninitialized {}", kind),
|
||||
self.path
|
||||
);
|
||||
if place.layout.is_unsized() {
|
||||
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
||||
}
|
||||
@ -334,7 +338,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||
format_args!("invalid {} metadata: {}", kind, msg),
|
||||
self.path
|
||||
),
|
||||
_ => bug!("Unexpected error during ptr size_and_align_of: {}", err),
|
||||
_ => bug!("unexpected error during ptr size_and_align_of: {}", err),
|
||||
},
|
||||
};
|
||||
let (size, align) = size_and_align
|
||||
@ -477,10 +481,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
// We are conservative with undef for integers, but try to
|
||||
// actually enforce our current rules for raw pointers.
|
||||
// actually enforce the strict rules for raw pointers (mostly because
|
||||
// that lets us re-use `ref_to_mplace`).
|
||||
let place = try_validation!(
|
||||
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
|
||||
"undefined pointer",
|
||||
"uninitialized raw pointer",
|
||||
self.path
|
||||
);
|
||||
if place.layout.is_unsized() {
|
||||
@ -776,14 +781,14 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
// For some errors we might be able to provide extra information
|
||||
match err.kind {
|
||||
err_ub!(InvalidUndefBytes(Some(ptr))) => {
|
||||
// Some byte was undefined, determine which
|
||||
// Some byte was uninitialized, determine which
|
||||
// element that byte belongs to so we can
|
||||
// provide an index.
|
||||
let i = usize::try_from(ptr.offset.bytes() / layout.size.bytes())
|
||||
.unwrap();
|
||||
self.path.push(PathElem::ArrayElem(i));
|
||||
|
||||
throw_validation_failure!("undefined bytes", self.path)
|
||||
throw_validation_failure!("uninitialized bytes", self.path)
|
||||
}
|
||||
// Other errors shouldn't be possible
|
||||
_ => return Err(err),
|
||||
|
@ -285,6 +285,7 @@
|
||||
#![feature(never_type)]
|
||||
#![feature(nll)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(panic_unwind)]
|
||||
|
@ -260,7 +260,7 @@ impl<T> Packet<T> {
|
||||
let state = match self.state.load(Ordering::SeqCst) {
|
||||
// Each of these states means that no further activity will happen
|
||||
// with regard to abortion selection
|
||||
s @ EMPTY | s @ DATA | s @ DISCONNECTED => s,
|
||||
s @ (EMPTY | DATA | DISCONNECTED) => s,
|
||||
|
||||
// If we've got a blocked thread, then use an atomic to gain ownership
|
||||
// of it (may fail)
|
||||
|
@ -205,7 +205,7 @@ impl<T> Packet<T> {
|
||||
// Messages which actually popped from the queue shouldn't count as
|
||||
// a steal, so offset the decrement here (we already have our
|
||||
// "steal" factored into the channel count above).
|
||||
data @ Ok(..) | data @ Err(Upgraded(..)) => unsafe {
|
||||
data @ (Ok(..) | Err(Upgraded(..))) => unsafe {
|
||||
*self.queue.consumer_addition().steals.get() -= 1;
|
||||
data
|
||||
},
|
||||
|
12
src/test/ui/asm/issue-54067.rs
Normal file
12
src/test/ui/asm/issue-54067.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// check-pass
|
||||
// ignore-emscripten no llvm_asm! support
|
||||
|
||||
#![feature(llvm_asm)]
|
||||
|
||||
pub fn boot(addr: Option<u32>) {
|
||||
unsafe {
|
||||
llvm_asm!("mov sp, $0"::"r" (addr));
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
10
src/test/ui/async-await/issues/auxiliary/issue_67893.rs
Normal file
10
src/test/ui/async-await/issues/auxiliary/issue_67893.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// edition:2018
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub async fn f(_: ()) {}
|
||||
|
||||
pub async fn run() {
|
||||
let x: Arc<Mutex<()>> = unimplemented!();
|
||||
f(*x.lock().unwrap()).await;
|
||||
}
|
13
src/test/ui/async-await/issues/issue-67893.rs
Normal file
13
src/test/ui/async-await/issues/issue-67893.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// aux-build: issue_67893.rs
|
||||
// edition:2018
|
||||
// dont-check-compiler-stderr
|
||||
// FIXME(#71222): Add above flag because of the difference of stderrs on some env.
|
||||
|
||||
extern crate issue_67893;
|
||||
|
||||
fn g(_: impl Send) {}
|
||||
|
||||
fn main() {
|
||||
g(issue_67893::run())
|
||||
//~^ ERROR: `std::sync::MutexGuard<'_, ()>` cannot be sent between threads safely
|
||||
}
|
65
src/test/ui/consts/const-eval/ub-int-array.rs
Normal file
65
src/test/ui/consts/const-eval/ub-int-array.rs
Normal file
@ -0,0 +1,65 @@
|
||||
#![feature(const_transmute)]
|
||||
#![allow(const_err)] // make sure we cannot allow away the errors tested here
|
||||
|
||||
//! Test the "array of int" fast path in validity checking, and in particular whether it
|
||||
//! points at the right array element.
|
||||
|
||||
use std::mem;
|
||||
|
||||
#[repr(C)]
|
||||
union MaybeUninit<T: Copy> {
|
||||
uninit: (),
|
||||
init: T,
|
||||
}
|
||||
|
||||
const UNINIT_INT_0: [u32; 3] = unsafe {
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~| type validation failed: encountered uninitialized bytes at [0]
|
||||
[
|
||||
MaybeUninit { uninit: () }.init,
|
||||
1,
|
||||
2,
|
||||
]
|
||||
};
|
||||
const UNINIT_INT_1: [u32; 3] = unsafe {
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~| type validation failed: encountered uninitialized bytes at [1]
|
||||
mem::transmute(
|
||||
[
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
1u8,
|
||||
MaybeUninit { uninit: () }.init,
|
||||
1u8,
|
||||
1u8,
|
||||
2u8,
|
||||
2u8,
|
||||
MaybeUninit { uninit: () }.init,
|
||||
2u8,
|
||||
]
|
||||
)
|
||||
};
|
||||
const UNINIT_INT_2: [u32; 3] = unsafe {
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~| type validation failed: encountered uninitialized bytes at [2]
|
||||
mem::transmute(
|
||||
[
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
0u8,
|
||||
1u8,
|
||||
1u8,
|
||||
1u8,
|
||||
1u8,
|
||||
2u8,
|
||||
2u8,
|
||||
2u8,
|
||||
MaybeUninit { uninit: () }.init,
|
||||
]
|
||||
)
|
||||
};
|
||||
|
||||
fn main() {}
|
45
src/test/ui/consts/const-eval/ub-int-array.stderr
Normal file
45
src/test/ui/consts/const-eval/ub-int-array.stderr
Normal file
@ -0,0 +1,45 @@
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:15:1
|
||||
|
|
||||
LL | / const UNINIT_INT_0: [u32; 3] = unsafe {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | [
|
||||
... |
|
||||
LL | | ]
|
||||
LL | | };
|
||||
| |__^ type validation failed: encountered uninitialized bytes at [0]
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:24:1
|
||||
|
|
||||
LL | / const UNINIT_INT_1: [u32; 3] = unsafe {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | mem::transmute(
|
||||
... |
|
||||
LL | | )
|
||||
LL | | };
|
||||
| |__^ type validation failed: encountered uninitialized bytes at [1]
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-int-array.rs:44:1
|
||||
|
|
||||
LL | / const UNINIT_INT_2: [u32; 3] = unsafe {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | mem::transmute(
|
||||
... |
|
||||
LL | | )
|
||||
LL | | };
|
||||
| |__^ type validation failed: encountered uninitialized bytes at [2]
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
@ -6,11 +6,11 @@ use std::mem;
|
||||
|
||||
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
|
||||
//~| type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1)
|
||||
|
||||
const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
|
||||
//~| type validation failed: encountered an unaligned box (required 2 byte alignment but found 1)
|
||||
|
||||
const NULL: &u16 = unsafe { mem::transmute(0usize) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
|
@ -62,7 +62,7 @@ LL | |
|
||||
LL | | let uninit_len = MaybeUninit::<usize> { uninit: () };
|
||||
LL | | mem::transmute((42, uninit_len))
|
||||
LL | | };
|
||||
| |__^ type validation failed: encountered undefined pointer
|
||||
| |__^ type validation failed: encountered uninitialized reference
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
@ -130,7 +130,7 @@ LL | |
|
||||
LL | | let uninit_len = MaybeUninit::<usize> { uninit: () };
|
||||
LL | | mem::transmute((42, uninit_len))
|
||||
LL | | };
|
||||
| |__^ type validation failed: encountered undefined pointer
|
||||
| |__^ type validation failed: encountered uninitialized raw pointer
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
@ -27,7 +27,7 @@ LL | | unsafe { UNION.field3 },
|
||||
... |
|
||||
LL | | a: 42,
|
||||
LL | | };
|
||||
| |__^ type validation failed: encountered undefined bytes at .b[1]
|
||||
| |__^ type validation failed: encountered uninitialized bytes at .b[1]
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
@ -4,7 +4,7 @@ error: any use of this value will cause an error
|
||||
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
|
||||
| ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| tried to transmute from usize to &[u8], but their sizes differed
|
||||
| transmuting `usize` to `&[u8]` is not possible, because these types do not have the same size
|
||||
|
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
|
@ -12,3 +12,4 @@ LL | -> Box<for<'a> Id<impl Lt<'a>>>
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0657`.
|
||||
|
9
src/test/ui/intrinsics/issue-28575.rs
Normal file
9
src/test/ui/intrinsics/issue-28575.rs
Normal file
@ -0,0 +1,9 @@
|
||||
#![feature(intrinsics)]
|
||||
|
||||
extern "C" {
|
||||
pub static FOO: extern "rust-intrinsic" fn();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
FOO() //~ ERROR: use of extern static is unsafe
|
||||
}
|
11
src/test/ui/intrinsics/issue-28575.stderr
Normal file
11
src/test/ui/intrinsics/issue-28575.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0133]: use of extern static is unsafe and requires unsafe function or block
|
||||
--> $DIR/issue-28575.rs:8:5
|
||||
|
|
||||
LL | FOO()
|
||||
| ^^^ use of extern static
|
||||
|
|
||||
= note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0133`.
|
1
src/test/ui/static/auxiliary/issue_24843.rs
Normal file
1
src/test/ui/static/auxiliary/issue_24843.rs
Normal file
@ -0,0 +1 @@
|
||||
pub static TEST_STR: &'static str = "Hello world";
|
8
src/test/ui/static/issue-24843.rs
Normal file
8
src/test/ui/static/issue-24843.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// aux-build: issue_24843.rs
|
||||
// check-pass
|
||||
|
||||
extern crate issue_24843;
|
||||
|
||||
static _TEST_STR_2: &'static str = &issue_24843::TEST_STR;
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user