Document drop more.
Adds two examples to Drop and describes the recursive drop on types that contain fields.
- [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md)
- [linkage](language-features/linkage.md)
- [log_syntax](language-features/log-syntax.md)
- - [loop_break_value](language-features/loop-break-value.md)
- [macro_reexport](language-features/macro-reexport.md)
- [macro_vis_matcher](language-features/macro-vis-matcher.md)
- [main](language-features/main.md)
------------------------
+At present, literals are only accepted as the value of a key-value pair in
+attributes. What's more, only _string_ literals are accepted. This means that
+literals can only appear in forms of `#[attr(name = "value")]` or
+`#[attr = "value"]`.
+The `attr_literals` unstable feature allows other types of literals to be used
+in attributes. Here are some examples of attributes that can now be used with
+this feature enabled:
+
++```rust,ignore
++#[attr]
++#[attr(true)]
++#[attr(ident)]
++#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
++#[attr(100)]
++#[attr(enabled = true)]
++#[enabled(true)]
++#[attr("hello")]
++#[repr(C, align = 4)]
++#[repr(C, align(4))]
++```
[#31436]: https://github.com/rust-lang/rust/issues/31436
------------------------
+
+The `catch_expr` feature adds support for a `catch` expression. The `catch`
+expression creates a new scope one can use the `?` operator in.
+
+```rust
+#![feature(catch_expr)]
+
+use std::num::ParseIntError;
+
+let result: Result<i32, ParseIntError> = do catch {
+ Ok("1".parse::<i32>()?
+ + "2".parse::<i32>()?
+ + "3".parse::<i32>()?)
+};
+assert_eq!(result, Ok(6));
+
+let result: Result<i32, ParseIntError> = do catch {
+ Ok("1".parse::<i32>()?
+ + "foo".parse::<i32>()?
+ + "3".parse::<i32>()?)
+};
+assert!(result.is_err());
+```
+++ /dev/null
-# `loop_break_value`
-
-The tracking issue for this feature is: [#37339]
-
-[#37339]: https://github.com/rust-lang/rust/issues/37339
-
-Documentation to be appended to section G of the book.
-
-------------------------
-
-### Loops as expressions
-
-Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop
-never exits.
-A `loop` can instead evaluate to a useful value via *break with value*:
-
-```rust
-#![feature(loop_break_value)]
-
-// Find the first square number over 1000:
-let mut n = 1;
-let square = loop {
- if n * n > 1000 {
- break n * n;
- }
- n += 1;
-};
-```
-
-The evaluation type may be specified externally:
-
-```rust
-#![feature(loop_break_value)]
-
-// Declare that value returned is unsigned 64-bit:
-let n: u64 = loop {
- break 1;
-};
-```
-
-It is an error if types do not agree, either between a "break" value and an external requirement,
-or between multiple "break" values:
-
-```no_compile
-#![feature(loop_break_value)]
-
-loop {
- if true {
- break 1u32;
- } else {
- break 0u8; // error: types do not agree
- }
-};
-
-let n: i32 = loop {
- break 0u32; // error: type does not agree with external requirement
-};
-```
-
-#### Break: label, value
-
-Four forms of `break` are available, where EXPR is some expression which evaluates to a value:
-
-1. `break;`
-2. `break 'label;`
-3. `break EXPR;`
-4. `break 'label EXPR;`
-
-When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`.
-
-Using a label allows returning a value from an inner loop:
-
-```rust
-#![feature(loop_break_value)]
-
-let result = 'outer: loop {
- for n in 1..10 {
- if n > 4 {
- break 'outer n;
- }
- }
-};
-```
------------------------
+The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
+attribute, which allows trait definitions to add specialized notes to error
+messages when an implementation was expected but not found.
+For example:
+
+```rust,compile_fail
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an \
+ iterator over elements of type `{A}`"]
+trait MyIterator<A> {
+ fn next(&mut self) -> A;
+}
+
+fn iterate_chars<I: MyIterator<char>>(i: I) {
+ // ...
+}
+
+fn main() {
+ iterate_chars(&[1, 2, 3][..]);
+}
+```
+
+When the user compiles this, they will see the following;
+
+```txt
+error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
+ --> <anon>:14:5
+ |
+14 | iterate_chars(&[1, 2, 3][..]);
+ | ^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
+ |
+ = note: a collection of type `&[{integer}]` cannot be built from an iterator over elements of type `char`
+ = note: required by `iterate_chars`
+
+error: aborting due to previous error
+```
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<T> RangeArgument<T> for RangeInclusive<T> {
fn start(&self) -> Bound<&T> {
- match *self {
- RangeInclusive::Empty{ ref at } => Included(at),
- RangeInclusive::NonEmpty { ref start, .. } => Included(start),
- }
+ Included(&self.start)
}
fn end(&self) -> Bound<&T> {
- match *self {
- RangeInclusive::Empty{ ref at } => Excluded(at),
- RangeInclusive::NonEmpty { ref end, .. } => Included(end),
- }
+ Included(&self.end)
}
}
/// Converts `self` into a vector without clones or allocation.
///
+ /// The resulting vector can be converted back into a box via
+ /// `Vec<T>`'s `into_boxed_slice` method.
+ ///
/// # Examples
///
/// ```
#[inline]
fn next(&mut self) -> Option<A> {
- use ops::RangeInclusive::*;
-
- // this function has a sort of odd structure due to borrowck issues
- // we may need to replace self.range, so borrows of start and end need to end early
-
- let (finishing, n) = match self.range {
- Empty { .. } => return None, // empty iterators yield no values
-
- NonEmpty { ref mut start, ref mut end } => {
- let rev = self.step_by.is_negative();
-
- // march start towards (maybe past!) end and yield the old value
- if (rev && start >= end) ||
- (!rev && start <= end)
- {
- match start.step(&self.step_by) {
- Some(mut n) => {
- mem::swap(start, &mut n);
- (None, Some(n)) // yield old value, remain non-empty
- },
- None => {
- let mut n = end.clone();
- mem::swap(start, &mut n);
- (None, Some(n)) // yield old value, remain non-empty
- }
- }
- } else {
- // found range in inconsistent state (start at or past end), so become empty
- (Some(end.replace_zero()), None)
- }
- }
- };
+ let rev = self.step_by.is_negative();
- // turn into an empty iterator if we've reached the end
- if let Some(end) = finishing {
- self.range = Empty { at: end };
+ if (rev && self.range.start >= self.range.end) ||
+ (!rev && self.range.start <= self.range.end)
+ {
+ match self.range.start.step(&self.step_by) {
+ Some(n) => {
+ Some(mem::replace(&mut self.range.start, n))
+ },
+ None => {
+ let last = self.range.start.replace_one();
+ self.range.end.replace_zero();
+ self.step_by.replace_one();
+ Some(last)
+ },
+ }
+ }
+ else {
+ None
}
-
- n
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- use ops::RangeInclusive::*;
-
- match self.range {
- Empty { .. } => (0, Some(0)),
-
- NonEmpty { ref start, ref end } =>
- match Step::steps_between(start,
- end,
- &self.step_by) {
- Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
- None => (0, None)
- }
+ match Step::steps_between(&self.range.start,
+ &self.range.end,
+ &self.step_by) {
+ Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+ None => (0, None)
}
}
}
#[inline]
fn next(&mut self) -> Option<A> {
- use ops::RangeInclusive::*;
-
- // this function has a sort of odd structure due to borrowck issues
- // we may need to replace self, so borrows of self.start and self.end need to end early
-
- let (finishing, n) = match *self {
- Empty { .. } => (None, None), // empty iterators yield no values
-
- NonEmpty { ref mut start, ref mut end } => {
- if start == end {
- (Some(end.replace_one()), Some(start.replace_one()))
- } else if start < end {
- let mut n = start.add_one();
- mem::swap(&mut n, start);
-
- // if the iterator is done iterating, it will change from
- // NonEmpty to Empty to avoid unnecessary drops or clones,
- // we'll reuse either start or end (they are equal now, so
- // it doesn't matter which) to pull out end, we need to swap
- // something back in
-
- (if n == *end { Some(end.replace_one()) } else { None },
- // ^ are we done yet?
- Some(n)) // < the value to output
- } else {
- (Some(start.replace_one()), None)
- }
- }
- };
-
- // turn into an empty iterator if this is the last value
- if let Some(end) = finishing {
- *self = Empty { at: end };
+ use cmp::Ordering::*;
+
+ match self.start.partial_cmp(&self.end) {
+ Some(Less) => {
+ let n = self.start.add_one();
+ Some(mem::replace(&mut self.start, n))
+ },
+ Some(Equal) => {
+ let last = self.start.replace_one();
+ self.end.replace_zero();
+ Some(last)
+ },
+ _ => None,
}
-
- n
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- use ops::RangeInclusive::*;
-
- match *self {
- Empty { .. } => (0, Some(0)),
+ if !(self.start <= self.end) {
+ return (0, Some(0));
+ }
- NonEmpty { ref start, ref end } =>
- match Step::steps_between_by_one(start, end) {
- Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
- None => (0, None),
- }
+ match Step::steps_between_by_one(&self.start, &self.end) {
+ Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
+ None => (0, None),
}
}
}
{
#[inline]
fn next_back(&mut self) -> Option<A> {
- use ops::RangeInclusive::*;
-
- // see Iterator::next for comments
-
- let (finishing, n) = match *self {
- Empty { .. } => return None,
-
- NonEmpty { ref mut start, ref mut end } => {
- if start == end {
- (Some(start.replace_one()), Some(end.replace_one()))
- } else if start < end {
- let mut n = end.sub_one();
- mem::swap(&mut n, end);
-
- (if n == *start { Some(start.replace_one()) } else { None },
- Some(n))
- } else {
- (Some(end.replace_one()), None)
- }
- }
- };
-
- if let Some(start) = finishing {
- *self = Empty { at: start };
+ use cmp::Ordering::*;
+
+ match self.start.partial_cmp(&self.end) {
+ Some(Less) => {
+ let n = self.end.sub_one();
+ Some(mem::replace(&mut self.end, n))
+ },
+ Some(Equal) => {
+ let last = self.end.replace_zero();
+ self.start.replace_one();
+ Some(last)
+ },
+ _ => None,
}
-
- n
}
}
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
/// fn main() {
-/// assert_eq!((3...5), std::ops::RangeInclusive::NonEmpty{ start: 3, end: 5 });
+/// assert_eq!((3...5), std::ops::RangeInclusive{ start: 3, end: 5 });
/// assert_eq!(3+4+5, (3...5).sum());
///
/// let arr = [0, 1, 2, 3];
/// ```
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
-pub enum RangeInclusive<Idx> {
- /// Empty range (iteration has finished)
+pub struct RangeInclusive<Idx> {
+ /// The lower bound of the range (inclusive).
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
- Empty {
- /// The point at which iteration finished
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
- issue = "28237")]
- at: Idx
- },
- /// Non-empty range (iteration will yield value(s))
+ pub start: Idx,
+ /// The upper bound of the range (inclusive).
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
- NonEmpty {
- /// The lower bound of the range (inclusive).
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
- issue = "28237")]
- start: Idx,
- /// The upper bound of the range (inclusive).
- #[unstable(feature = "inclusive_range",
- reason = "recently added, follows RFC",
- issue = "28237")]
- end: Idx,
- },
+ pub end: Idx,
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- use self::RangeInclusive::*;
-
- match *self {
- Empty { ref at } => write!(fmt, "[empty range @ {:?}]", at),
- NonEmpty { ref start, ref end } => write!(fmt, "{:?}...{:?}", start, end),
- }
+ write!(fmt, "{:?}...{:?}", self.start, self.end)
}
}
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
- if let &RangeInclusive::NonEmpty{ref start, ref end} = self {
- (*start <= item) && (item <= *end)
- } else { false }
+ self.start <= item && item <= self.end
}
}
// Querying the contained values
/////////////////////////////////////////////////////////////////////////
- /// Returns `true` if the option is a `Some` value.
+ /// Returns `true` if the option is a [`Some`] value.
///
/// # Examples
///
/// let x: Option<u32> = None;
/// assert_eq!(x.is_some(), false);
/// ```
+ ///
+ /// [`Some`]: #variant.Some
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_some(&self) -> bool {
}
}
- /// Returns `true` if the option is a `None` value.
+ /// Returns `true` if the option is a [`None`] value.
///
/// # Examples
///
/// let x: Option<u32> = None;
/// assert_eq!(x.is_none(), true);
/// ```
+ ///
+ /// [`None`]: #variant.None
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_none(&self) -> bool {
// Getting to contained values
/////////////////////////////////////////////////////////////////////////
- /// Unwraps an option, yielding the content of a `Some`.
+ /// Unwraps an option, yielding the content of a [`Some`].
///
/// # Panics
///
/// Panics if the value is a [`None`] with a custom panic message provided by
/// `msg`.
///
+ /// [`Some`]: #variant.Some
/// [`None`]: #variant.None
///
/// # Examples
}
}
- /// Moves the value `v` out of the `Option<T>` if it is `Some(v)`.
+ /// Moves the value `v` out of the `Option<T>` if it is [`Some(v)`].
///
/// In general, because this function may panic, its use is discouraged.
- /// Instead, prefer to use pattern matching and handle the `None`
+ /// Instead, prefer to use pattern matching and handle the [`None`]
/// case explicitly.
///
/// # Panics
///
/// Panics if the self value equals [`None`].
///
+ /// [`Some(v)`]: #variant.Some
/// [`None`]: #variant.None
///
/// # Examples
}
/// Applies a function to the contained value (if any),
- /// or returns a `default` (if not).
+ /// or returns a [`default`][] (if not).
+ ///
+ /// [`default`]: ../default/trait.Default.html#tymethod.default
///
/// # Examples
///
}
/// Applies a function to the contained value (if any),
- /// or computes a `default` (if not).
+ /// or computes a [`default`][] (if not).
+ ///
+ /// [`default`]: ../default/trait.Default.html#tymethod.default
///
/// # Examples
///
}
}
- /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
- /// [`Ok(v)`] and `None` to [`Err(err)`][Err].
+ /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
+ /// [`Ok(v)`] and [`None`] to [`Err(err)`].
///
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
- /// [Err]: ../../std/result/enum.Result.html#variant.Err
+ /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
+ /// [`None`]: #variant.None
+ /// [`Some(v)`]: #variant.Some
///
/// # Examples
///
}
}
- /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
- /// [`Ok(v)`] and `None` to [`Err(err())`][Err].
+ /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
+ /// [`Ok(v)`] and [`None`] to [`Err(err())`].
///
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
- /// [Err]: ../../std/result/enum.Result.html#variant.Err
+ /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
+ /// [`None`]: #variant.None
+ /// [`Some(v)`]: #variant.Some
///
/// # Examples
///
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
- /// Returns `None` if the option is `None`, otherwise returns `optb`.
+ /// Returns [`None`] if the option is [`None`], otherwise returns `optb`.
+ ///
+ /// [`None`]: #variant.None
///
/// # Examples
///
}
}
- /// Returns `None` if the option is `None`, otherwise calls `f` with the
+ /// Returns [`None`] if the option is [`None`], otherwise calls `f` with the
/// wrapped value and returns the result.
///
/// Some languages call this operation flatmap.
///
+ /// [`None`]: #variant.None
+ ///
/// # Examples
///
/// ```
// Entry-like operations to insert if None and return a reference
/////////////////////////////////////////////////////////////////////////
- /// Inserts `v` into the option if it is `None`, then
+ /// Inserts `v` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
+ /// [`None`]: #variant.None
+ ///
/// # Examples
///
/// ```
}
}
- /// Inserts a value computed from `f` into the option if it is `None`, then
+ /// Inserts a value computed from `f` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
+ /// [`None`]: #variant.None
+ ///
/// # Examples
///
/// ```
// Misc
/////////////////////////////////////////////////////////////////////////
- /// Takes the value out of the option, leaving a `None` in its place.
+ /// Takes the value out of the option, leaving a [`None`] in its place.
+ ///
+ /// [`None`]: #variant.None
///
/// # Examples
///
impl<T: Default> Option<T> {
/// Returns the contained value or a default
///
- /// Consumes the `self` argument then, if `Some`, returns the contained
- /// value, otherwise if `None`, returns the default value for that
+ /// Consumes the `self` argument then, if [`Some`], returns the contained
+ /// value, otherwise if [`None`], returns the default value for that
/// type.
///
/// # Examples
///
/// Convert a string to an integer, turning poorly-formed strings
- /// into 0 (the default value for integers). `parse` converts
- /// a string to any other type that implements `FromStr`, returning
- /// `None` on error.
+ /// into 0 (the default value for integers). [`parse`] converts
+ /// a string to any other type that implements [`FromStr`], returning
+ /// [`None`] on error.
///
/// ```
/// let good_year_from_input = "1909";
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
+ ///
+ /// [`Some`]: #variant.Some
+ /// [`None`]: #variant.None
+ /// [`parse`]: ../../std/primitive.str.html#method.parse
+ /// [`FromStr`]: ../../std/str/trait.FromStr.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_or_default(self) -> T {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Option<T> {
- /// Returns None.
+ /// Returns [`None`].
+ ///
+ /// [`None`]: #variant.None
#[inline]
fn default() -> Option<T> { None }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
- /// Takes each element in the `Iterator`: if it is `None`, no further
- /// elements are taken, and the `None` is returned. Should no `None` occur, a
+ /// Takes each element in the [`Iterator`]: if it is [`None`], no further
+ /// elements are taken, and the [`None`] is returned. Should no [`None`] occur, a
/// container with the values of each `Option` is returned.
///
/// Here is an example which increments every integer in a vector,
/// ).collect();
/// assert!(res == Some(vec![2, 3]));
/// ```
+ ///
+ /// [`Iterator`]: ../iter/trait.Iterator.html
+ /// [`None`]: enum.Option.html#variant.None
#[inline]
fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
#[inline]
fn get(self, slice: &[T]) -> Option<&[T]> {
- match self {
- ops::RangeInclusive::Empty { .. } => Some(&[]),
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get(slice),
- }
+ if self.end == usize::max_value() { None }
+ else { (self.start..self.end + 1).get(slice) }
}
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
- match self {
- ops::RangeInclusive::Empty { .. } => Some(&mut []),
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => None,
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_mut(slice),
- }
+ if self.end == usize::max_value() { None }
+ else { (self.start..self.end + 1).get_mut(slice) }
}
#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &[],
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).get_unchecked(slice),
- }
+ (self.start..self.end + 1).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &mut [],
- ops::RangeInclusive::NonEmpty { start, end } => {
- (start..end + 1).get_unchecked_mut(slice)
- }
- }
+ (self.start..self.end + 1).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &[T]) -> &[T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &[],
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
- panic!("attempted to index slice up to maximum usize");
- },
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index(slice),
- }
+ assert!(self.end != usize::max_value(),
+ "attempted to index slice up to maximum usize");
+ (self.start..self.end + 1).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
- match self {
- ops::RangeInclusive::Empty { .. } => &mut [],
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() => {
- panic!("attempted to index slice up to maximum usize");
- },
- ops::RangeInclusive::NonEmpty { start, end } => (start..end + 1).index_mut(slice),
- }
+ assert!(self.end != usize::max_value(),
+ "attempted to index slice up to maximum usize");
+ (self.start..self.end + 1).index_mut(slice)
}
}
+#[cfg(stage0)] // The bootstrap compiler has a different `...` desugar
+fn inclusive(start: usize, end: usize) -> ops::RangeInclusive<usize> {
+ ops::RangeInclusive { start, end }
+}
+#[cfg(not(stage0))]
+fn inclusive(start: usize, end: usize) -> ops::RangeInclusive<usize> {
+ start...end
+}
+
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<T> SliceIndex<[T]> for ops::RangeToInclusive<usize> {
type Output = [T];
#[inline]
fn get(self, slice: &[T]) -> Option<&[T]> {
- (0...self.end).get(slice)
+ inclusive(0, self.end).get(slice)
}
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
- (0...self.end).get_mut(slice)
+ inclusive(0, self.end).get_mut(slice)
}
#[inline]
unsafe fn get_unchecked(self, slice: &[T]) -> &[T] {
- (0...self.end).get_unchecked(slice)
+ inclusive(0, self.end).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut [T]) -> &mut [T] {
- (0...self.end).get_unchecked_mut(slice)
+ inclusive(0, self.end).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &[T]) -> &[T] {
- (0...self.end).index(slice)
+ inclusive(0, self.end).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
- (0...self.end).index_mut(slice)
+ inclusive(0, self.end).index_mut(slice)
}
}
#[inline]
fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
- match index {
- ops::RangeInclusive::Empty { .. } => "",
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() =>
- panic!("attempted to index slice up to maximum usize"),
- ops::RangeInclusive::NonEmpty { start, end } =>
- self.index(start .. end+1)
- }
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index(index.start .. index.end+1)
}
}
+
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
#[inline]
fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
- self.index(0...index.end)
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index(.. index.end+1)
}
}
impl ops::IndexMut<ops::RangeInclusive<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
- match index {
- ops::RangeInclusive::Empty { .. } => &mut self[0..0], // `&mut ""` doesn't work
- ops::RangeInclusive::NonEmpty { end, .. } if end == usize::max_value() =>
- panic!("attempted to index str up to maximum usize"),
- ops::RangeInclusive::NonEmpty { start, end } =>
- self.index_mut(start .. end+1)
- }
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index_mut(index.start .. index.end+1)
}
}
#[unstable(feature = "inclusive_range",
impl ops::IndexMut<ops::RangeToInclusive<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
- self.index_mut(0...index.end)
+ assert!(index.end != usize::max_value(),
+ "attempted to index str up to maximum usize");
+ self.index_mut(.. index.end+1)
}
}
type Output = str;
#[inline]
fn get(self, slice: &str) -> Option<&Self::Output> {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get(slice)
+ (self.start..self.end+1).get(slice)
}
#[inline]
fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get_mut(slice)
+ (self.start..self.end+1).get_mut(slice)
}
#[inline]
unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get_unchecked(slice)
+ (self.start..self.end+1).get_unchecked(slice)
}
#[inline]
unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.get_unchecked_mut(slice)
+ (self.start..self.end+1).get_unchecked_mut(slice)
}
#[inline]
fn index(self, slice: &str) -> &Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.index(slice)
+ (self.start..self.end+1).index(slice)
}
#[inline]
fn index_mut(self, slice: &mut str) -> &mut Self::Output {
- match self {
- ops::RangeInclusive::Empty { .. } => 0..0,
- ops::RangeInclusive::NonEmpty { start, end } => start..end+1,
- }.index_mut(slice)
+ (self.start..self.end+1).index_mut(slice)
}
}
#![feature(fmt_internals)]
#![feature(iterator_step_by)]
#![feature(i128_type)]
+#![feature(inclusive_range)]
#![feature(iter_rfind)]
#![feature(libc)]
#![feature(nonzero)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use core::ops::{Range, RangeFull, RangeFrom, RangeTo};
+use core::ops::{Range, RangeFull, RangeFrom, RangeTo, RangeInclusive};
// Test the Range structs without the syntactic sugar.
// Not much to test.
let _ = RangeFull;
}
+
+#[test]
+fn test_range_inclusive() {
+ let mut r = RangeInclusive { start: 1i8, end: 2 };
+ assert_eq!(r.next(), Some(1));
+ assert_eq!(r.next(), Some(2));
+ assert_eq!(r.next(), None);
+
+ r = RangeInclusive { start: 127i8, end: 127 };
+ assert_eq!(r.next(), Some(127));
+ assert_eq!(r.next(), None);
+
+ r = RangeInclusive { start: -128i8, end: -128 };
+ assert_eq!(r.next_back(), Some(-128));
+ assert_eq!(r.next_back(), None);
+
+ // degenerate
+ r = RangeInclusive { start: 1, end: -1 };
+ assert_eq!(r.size_hint(), (0, Some(0)));
+ assert_eq!(r.next(), None);
+}
\ No newline at end of file
SymbolName(D),
SpecializationGraph(D),
ObjectSafety(D),
+ IsCopy(D),
+ IsSized(D),
+ IsFreeze(D),
+ NeedsDrop(D),
// The set of impls for a given trait. Ultimately, it would be
// nice to get more fine-grained here (e.g., to include a
// not a hotspot.
ProjectionCache { def_ids: Vec<D> },
+ ParamEnv(D),
DescribeDef(D),
DefSpan(D),
Stability(D),
// they are always absolute.
WorkProduct(ref id) => Some(WorkProduct(id.clone())),
+ IsCopy(ref d) => op(d).map(IsCopy),
+ IsSized(ref d) => op(d).map(IsSized),
+ IsFreeze(ref d) => op(d).map(IsFreeze),
+ NeedsDrop(ref d) => op(d).map(NeedsDrop),
Hir(ref d) => op(d).map(Hir),
HirBody(ref d) => op(d).map(HirBody),
MetaData(ref d) => op(d).map(MetaData),
let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
def_ids.map(|d| ProjectionCache { def_ids: d })
}
+ ParamEnv(ref d) => op(d).map(ParamEnv),
DescribeDef(ref d) => op(d).map(DescribeDef),
DefSpan(ref d) => op(d).map(DefSpan),
Stability(ref d) => op(d).map(Stability),
ExprKind::Range(ref e1, ref e2, lims) => {
use syntax::ast::RangeLimits::*;
- let (path, variant) = match (e1, e2, lims) {
- (&None, &None, HalfOpen) => ("RangeFull", None),
- (&Some(..), &None, HalfOpen) => ("RangeFrom", None),
- (&None, &Some(..), HalfOpen) => ("RangeTo", None),
- (&Some(..), &Some(..), HalfOpen) => ("Range", None),
- (&None, &Some(..), Closed) => ("RangeToInclusive", None),
- (&Some(..), &Some(..), Closed) => ("RangeInclusive", Some("NonEmpty")),
+ let path = match (e1, e2, lims) {
+ (&None, &None, HalfOpen) => "RangeFull",
+ (&Some(..), &None, HalfOpen) => "RangeFrom",
+ (&None, &Some(..), HalfOpen) => "RangeTo",
+ (&Some(..), &Some(..), HalfOpen) => "Range",
+ (&None, &Some(..), Closed) => "RangeToInclusive",
+ (&Some(..), &Some(..), Closed) => "RangeInclusive",
(_, &None, Closed) =>
panic!(self.diagnostic().span_fatal(
e.span, "inclusive range with no end")),
let is_unit = fields.is_empty();
let unstable_span = self.allow_internal_unstable("...", e.span);
let struct_path =
- iter::once("ops").chain(iter::once(path)).chain(variant)
+ iter::once("ops").chain(iter::once(path))
.collect::<Vec<_>>();
let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
let struct_path = hir::QPath::Resolved(None, P(struct_path));
// For region variables.
region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
- pub parameter_environment: ty::ParameterEnvironment<'gcx>,
+ pub param_env: ty::ParamEnv<'gcx>,
/// Caches the results of trait selection. This cache is used
/// for things that have to do with the parameters in scope.
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>);
+ Option<ty::ParamEnv<'tcx>>);
}
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(None, None, None)
}
}
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParamEnv<'tcx> {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(None, None, Some(self))
}
}
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(Some(self.0), None, Some(self.1))
}
}
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(None, Some(self.0), Some(self.1))
}
}
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
let def_id = tcx.hir.body_owner_def_id(self);
(Some(tcx.typeck_tables_of(def_id)),
None,
- Some(tcx.parameter_environment(def_id)))
+ Some(tcx.param_env(def_id)))
}
}
arena: DroplessArena,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
tables: Option<&'a ty::TypeckTables<'gcx>>,
- param_env: Option<ty::ParameterEnvironment<'gcx>>,
+ param_env: Option<ty::ParamEnv<'gcx>>,
projection_mode: Reveal,
}
int_unification_table: RefCell::new(UnificationTable::new()),
float_unification_table: RefCell::new(UnificationTable::new()),
region_vars: RegionVarBindings::new(self),
- parameter_environment: param_env.unwrap(),
+ param_env: param_env.unwrap(),
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
projection_cache: RefCell::new(traits::ProjectionCache::new()),
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
});
- let param_env = param_env.take().unwrap_or_else(|| {
- global_tcx.empty_parameter_environment()
- });
+ let param_env = param_env.take().unwrap_or_else(|| ty::ParamEnv::empty());
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
tcx: tcx,
tables: tables,
int_unification_table: RefCell::new(UnificationTable::new()),
float_unification_table: RefCell::new(UnificationTable::new()),
region_vars: RegionVarBindings::new(tcx),
- parameter_environment: param_env,
+ param_env: param_env,
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
reported_trait_errors: RefCell::new(FxHashSet()),
}
pub fn normalize_associated_type_in_env<T>(
- self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
+ self, value: &T, env: ty::ParamEnv<'tcx>
) -> T
where T: TransNormalize<'tcx>
{
return value;
}
- self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
+ self.infer_ctxt(env, Reveal::All).enter(|infcx| {
value.trans_normalize(&infcx)
})
}
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
}
- pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
- &self.parameter_environment
+ pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
+ self.param_env
}
pub fn closure_kind(&self,
#![feature(core_intrinsics)]
#![feature(i128_type)]
#![feature(libc)]
-#![feature(loop_break_value)]
#![feature(never_type)]
#![feature(nonzero)]
#![feature(quote)]
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![cfg_attr(stage0, feature(rustc_private))]
#![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
#![recursion_limit="128"]
One subtle interaction is that the results of trait lookup will vary
depending on what where clauses are in scope. Therefore, we actually
have *two* caches, a local and a global cache. The local cache is
-attached to the `ParameterEnvironment` and the global cache attached
-to the `tcx`. We use the local cache whenever the result might depend
-on the where clauses that are in scope. The determination of which
-cache to use is done by the method `pick_candidate_cache` in
-`select.rs`. At the moment, we use a very simple, conservative rule:
-if there are any where-clauses in scope, then we use the local cache.
-We used to try and draw finer-grained distinctions, but that led to a
-serious of annoying and weird bugs like #22019 and #18290. This simple
-rule seems to be pretty clearly safe and also still retains a very
-high hit rate (~95% when compiling rustc).
+attached to the `ParamEnv` and the global cache attached to the
+`tcx`. We use the local cache whenever the result might depend on the
+where clauses that are in scope. The determination of which cache to
+use is done by the method `pick_candidate_cache` in `select.rs`. At
+the moment, we use a very simple, conservative rule: if there are any
+where-clauses in scope, then we use the local cache. We used to try
+and draw finer-grained distinctions, but that led to a serious of
+annoying and weird bugs like #22019 and #18290. This simple rule seems
+to be pretty clearly safe and also still retains a very high hit rate
+(~95% when compiling rustc).
# Specialization
trait_ref.to_predicate(),
post_message);
+ let unimplemented_note = self.on_unimplemented_note(trait_ref, obligation);
+ if let Some(ref s) = unimplemented_note {
+ // If it has a custom "#[rustc_on_unimplemented]"
+ // error message, let's display it as the label!
+ err.span_label(span, s.as_str());
+ err.help(&format!("{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_ref,
+ trait_ref.self_ty()));
+ } else {
+ err.span_label(span,
+ &*format!("{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_ref,
+ trait_ref.self_ty()));
+ }
+
// Try to report a help message
if !trait_ref.has_infer_types() &&
self.predicate_can_apply(trait_ref) {
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
trait_ref.to_predicate()));
- } else if let Some(s) = self.on_unimplemented_note(trait_ref, obligation) {
- // If it has a custom "#[rustc_on_unimplemented]"
- // error message, let's display it!
- err.note(&s);
- } else {
+ } else if unimplemented_note.is_none() {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
}
- err.span_label(span,
- format!("{}the trait `{}` is not implemented for `{}`",
- pre_message,
- trait_ref,
- trait_ref.self_ty()));
err
}
/// Normalizes the parameter environment, reporting errors if they occur.
pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
region_context: DefId,
- unnormalized_env: ty::ParameterEnvironment<'tcx>,
+ unnormalized_env: ty::ParamEnv<'tcx>,
cause: ObligationCause<'tcx>)
- -> ty::ParameterEnvironment<'tcx>
+ -> ty::ParamEnv<'tcx>
{
// I'm not wild about reporting errors here; I'd prefer to
// have the errors get reported at a defined place (e.g.,
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
predicates);
- let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
+ let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
let predicates = match fully_normalize(
&infcx, cause,
- // You would really want to pass infcx.parameter_environment.caller_bounds here,
+ // You would really want to pass infcx.param_env.caller_bounds here,
// but that is an interned slice, and fully_normalize takes &T and returns T, so
// without further refactoring, a slice can't be used. Luckily, we still have the
- // predicate vector from which we created the ParameterEnvironment in infcx, so we
+ // predicate vector from which we created the ParamEnv in infcx, so we
// can pass that instead. It's roundabout and a bit brittle, but this code path
// ought to be refactored anyway, and until then it saves us from having to copy.
&predicates,
Err(errors) => {
infcx.report_fulfillment_errors(&errors);
// An unnormalized env is better than nothing.
- return infcx.parameter_environment;
+ return infcx.param_env;
}
};
// all things considered.
tcx.sess.span_err(span, &fixup_err.to_string());
// An unnormalized env is better than nothing.
- return infcx.parameter_environment;
+ return infcx.param_env;
}
};
let predicates = match tcx.lift_to_global(&predicates) {
Some(predicates) => predicates,
- None => return infcx.parameter_environment
+ None => return infcx.param_env
};
debug!("normalize_param_env_or_error: resolved predicates={:?}",
predicates);
- infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
+ ty::ParamEnv::new(tcx.intern_predicates(&predicates))
})
}
self.infcx.tcx
}
- pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
+ pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
self.infcx.param_env()
}
}
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
- let penv = tcx.parameter_environment(impl1_def_id);
+ let penv = tcx.param_env(impl1_def_id);
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
// Create a infcx, taking the predicates of impl1 as assumptions:
source_trait_ref,
target_trait_ref,
errors,
- infcx.parameter_environment.caller_bounds);
+ infcx.param_env.caller_bounds);
Err(())
}
let flags = super::flags::FlagComputation::for_sty(&st);
let ty_struct = TyS {
sty: st,
- flags: Cell::new(flags.flags),
+ flags: flags.flags,
region_depth: flags.depth,
};
ty::TyError => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)*
};
- let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
- let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
+ let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
+ let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
variant.total += 1;
total.total += 1;
}
fn add_ty(&mut self, ty: Ty) {
- self.add_flags(ty.flags.get());
+ self.add_flags(ty.flags);
self.add_depth(ty.region_depth);
}
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
fn visit_ty(&mut self, t: Ty) -> bool {
- let flags = t.flags.get();
- debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, flags, self.flags);
- flags.intersects(self.flags)
+ debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, t.flags, self.flags);
+ t.flags.intersects(self.flags)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
let ptr_layout = |pointee: Ty<'gcx>| {
let non_zero = !ty.is_unsafe_ptr();
let pointee = infcx.normalize_projections(pointee);
- if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
+ if pointee.is_sized(tcx, infcx.param_env, DUMMY_SP) {
Ok(Scalar { value: Pointer, non_zero: non_zero })
} else {
let unsized_part = tcx.struct_tail(pointee);
let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
StructKind::AlwaysSizedUnivariant
} else {
- let param_env = tcx.parameter_environment(def.did);
+ let param_env = tcx.param_env(def.did);
let fields = &def.variants[0].fields;
let last_field = &fields[fields.len()-1];
let always_sized = tcx.type_of(last_field.did)
- .is_sized(tcx, ¶m_env, DUMMY_SP);
+ .is_sized(tcx, param_env, DUMMY_SP);
if !always_sized { StructKind::MaybeUnsizedUnivariant }
else { StructKind::AlwaysSizedUnivariant }
};
// except according to those terms.
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
-use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use hir::def::Def;
use hir;
use middle::const_val;
}
}
+impl<'tcx, T: Clone + Hash + Eq + Debug> Key for ty::ParamEnvAnd<'tcx, T> {
+ fn map_crate(&self) -> CrateNum {
+ LOCAL_CRATE
+ }
+ fn default_span(&self, _: TyCtxt) -> Span {
+ DUMMY_SP
+ }
+}
+
trait Value<'tcx>: Sized {
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
}
}
}
+impl<'tcx> QueryDescription for queries::is_copy_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` is `Copy`", env.value)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::is_sized_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` is `Sized`", env.value)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` is freeze", env.value)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::needs_drop_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` needs drop", env.value)
+ }
+}
+
impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
format!("computing the supertraits of `{}`",
-> ty::trait_def::TraitImpls,
[] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
[] is_object_safe: ObjectSafety(DefId) -> bool,
+
+ [] param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
+
+ // Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
+ // `ty.is_copy()`, etc, since that will prune the environment where possible.
+ [] is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+ [] is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+ [] is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+ [] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
}
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode<DefId> {
DepNode::TraitImpls(def_id)
}
+
+fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::IsCopy(def_id)
+}
+
+fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::IsSized(def_id)
+}
+
+fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::IsFreeze(def_id)
+}
+
+fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::NeedsDrop(def_id)
+}
use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
use serialize::{self, Encodable, Encoder};
-use std::cell::{Cell, RefCell};
use std::collections::BTreeMap;
use std::cmp;
use std::fmt;
TypeFlags::HAS_TY_CLOSURE.bits |
TypeFlags::HAS_LOCAL_NAMES.bits |
TypeFlags::KEEP_IN_LOCAL_TCX.bits,
-
- // Caches for type_is_sized, type_moves_by_default
- const SIZEDNESS_CACHED = 1 << 16,
- const IS_SIZED = 1 << 17,
- const MOVENESS_CACHED = 1 << 18,
- const MOVES_BY_DEFAULT = 1 << 19,
- const FREEZENESS_CACHED = 1 << 20,
- const IS_FREEZE = 1 << 21,
- const NEEDS_DROP_CACHED = 1 << 22,
- const NEEDS_DROP = 1 << 23,
}
}
pub struct TyS<'tcx> {
pub sty: TypeVariants<'tcx>,
- pub flags: Cell<TypeFlags>,
+ pub flags: TypeFlags,
// the maximal depth of any bound regions appearing in this type.
region_depth: u32,
}
}
-/// When type checking, we use the `ParameterEnvironment` to track
-/// details about the type/lifetime parameters that are in scope.
-/// It primarily stores the bounds information.
-///
-/// Note: This information might seem to be redundant with the data in
-/// `tcx.ty_param_defs`, but it is not. That table contains the
-/// parameter definitions from an "outside" perspective, but this
-/// struct will contain the bounds for a parameter as seen from inside
-/// the function body. Currently the only real distinction is that
-/// bound lifetime parameters are replaced with free ones, but in the
-/// future I hope to refine the representation of types so as to make
-/// more distinctions clearer.
-#[derive(Clone)]
-pub struct ParameterEnvironment<'tcx> {
+/// When type checking, we use the `ParamEnv` to track
+/// details about the set of where-clauses that are in scope at this
+/// particular point.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParamEnv<'tcx> {
/// Obligations that the caller must satisfy. This is basically
/// the set of bounds on the in-scope type parameters, translated
/// into Obligations, and elaborated and normalized.
- pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
-
- /// A cache for `moves_by_default`.
- pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+ pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
+}
- /// A cache for `type_is_sized`
- pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+impl<'tcx> ParamEnv<'tcx> {
+ /// Creates a suitable environment in which to perform trait
+ /// queries on the given value. This will either be `self` *or*
+ /// the empty environment, depending on whether `value` references
+ /// type parameters that are in scope. (If it doesn't, then any
+ /// judgements should be completely independent of the context,
+ /// and hence we can safely use the empty environment so as to
+ /// enable more sharing across functions.)
+ ///
+ /// NB: This is a mildly dubious thing to do, in that a function
+ /// (or other environment) might have wacky where-clauses like
+ /// `where Box<u32>: Copy`, which are clearly never
+ /// satisfiable. The code will at present ignore these,
+ /// effectively, when type-checking the body of said
+ /// function. This preserves existing behavior in any
+ /// case. --nmatsakis
+ pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
+ assert!(!value.needs_infer());
+ if value.has_param_types() || value.has_self_ty() {
+ ParamEnvAnd {
+ param_env: self,
+ value: value,
+ }
+ } else {
+ ParamEnvAnd {
+ param_env: ParamEnv::empty(),
+ value: value,
+ }
+ }
+ }
+}
- /// A cache for `type_is_freeze`
- pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParamEnvAnd<'tcx, T> {
+ pub param_env: ParamEnv<'tcx>,
+ pub value: T,
}
-impl<'a, 'tcx> ParameterEnvironment<'tcx> {
- pub fn with_caller_bounds(&self,
- caller_bounds: &'tcx [ty::Predicate<'tcx>])
- -> ParameterEnvironment<'tcx>
- {
- ParameterEnvironment {
- caller_bounds: caller_bounds,
- is_copy_cache: RefCell::new(FxHashMap()),
- is_sized_cache: RefCell::new(FxHashMap()),
- is_freeze_cache: RefCell::new(FxHashMap()),
- }
+impl<'tcx, T> ParamEnvAnd<'tcx, T> {
+ pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
+ (self.param_env, self.value)
}
}
}
}
- /// Construct a parameter environment suitable for static contexts or other contexts where there
- /// are no free type/lifetime parameters in scope.
- pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
- ty::ParameterEnvironment {
- caller_bounds: Slice::empty(),
- is_copy_cache: RefCell::new(FxHashMap()),
- is_sized_cache: RefCell::new(FxHashMap()),
- is_freeze_cache: RefCell::new(FxHashMap()),
- }
- }
-
- /// See `ParameterEnvironment` struct def'n for details.
- pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
- //
- // Compute the bounds on Self and the type parameters.
- //
-
- let tcx = self.global_tcx();
- let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
- let predicates = bounds.predicates;
-
- // Finally, we have to normalize the bounds in the environment, in
- // case they contain any associated type projections. This process
- // can yield errors if the put in illegal associated types, like
- // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
- // report these errors right here; this doesn't actually feel
- // right to me, because constructing the environment feels like a
- // kind of a "idempotent" action, but I'm not sure where would be
- // a better place. In practice, we construct environments for
- // every fn once during type checking, and we'll abort if there
- // are any errors at that point, so after type checking you can be
- // sure that this will succeed without errors anyway.
- //
-
- let unnormalized_env = ty::ParameterEnvironment {
- caller_bounds: tcx.intern_predicates(&predicates),
- is_copy_cache: RefCell::new(FxHashMap()),
- is_sized_cache: RefCell::new(FxHashMap()),
- is_freeze_cache: RefCell::new(FxHashMap()),
- };
-
- let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
- self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
- });
- let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
- traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
- }
-
pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
}
})
}
+/// See `ParamEnv` struct def'n for details.
+fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> ParamEnv<'tcx> {
+ // Compute the bounds on Self and the type parameters.
+
+ let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
+ let predicates = bounds.predicates;
+
+ // Finally, we have to normalize the bounds in the environment, in
+ // case they contain any associated type projections. This process
+ // can yield errors if the put in illegal associated types, like
+ // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+ // report these errors right here; this doesn't actually feel
+ // right to me, because constructing the environment feels like a
+ // kind of a "idempotent" action, but I'm not sure where would be
+ // a better place. In practice, we construct environments for
+ // every fn once during type checking, and we'll abort if there
+ // are any errors at that point, so after type checking you can be
+ // sure that this will succeed without errors anyway.
+
+ let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
+
+ let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
+ tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+ });
+ let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
+ traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
+}
pub fn provide(providers: &mut ty::maps::Providers) {
+ util::provide(providers);
*providers = ty::maps::Providers {
associated_item,
associated_item_def_ids,
adt_sized_constraint,
adt_dtorck_constraint,
def_span,
+ param_env,
trait_of_item,
trait_impls_of: trait_def::trait_impls_of_provider,
relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
adt_dtorck_constraint,
trait_impls_of: trait_def::trait_impls_of_provider,
relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
+ param_env,
..*providers
};
}
use infer::InferCtxt;
use ich::{StableHashingContext, NodeIdHashingMode};
use traits::{self, Reveal};
-use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
-use ty::ParameterEnvironment;
+use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
use ty::subst::{Subst, Kind};
use ty::TypeVariants::*;
use util::common::ErrorReported;
-use util::nodemap::{FxHashMap, FxHashSet};
use middle::lang_items;
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
-use std::cell::RefCell;
use std::cmp;
use std::hash::Hash;
use std::intrinsics;
use syntax::attr::{self, SignedInt, UnsignedInt};
use syntax_pos::{Span, DUMMY_SP};
-use hir;
-
type Disr = ConstInt;
pub trait IntTypeExt {
SelfRecursive(Vec<Span>),
}
-impl<'tcx> ParameterEnvironment<'tcx> {
+impl<'tcx> ty::ParamEnv<'tcx> {
+ /// Construct a trait environment suitable for contexts where
+ /// there are no where clauses in scope.
+ pub fn empty() -> Self {
+ Self::new(ty::Slice::empty())
+ }
+
+ /// Construct a trait environment with the given set of predicates.
+ pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>) -> Self {
+ ty::ParamEnv { caller_bounds }
+ }
+
pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
self_type: Ty<'tcx>, span: Span)
-> Result<(), CopyImplementationError> {
}
impl<'a, 'tcx> ty::TyS<'tcx> {
- fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- def_id: DefId,
- cache: &RefCell<FxHashMap<Ty<'tcx>, bool>>,
- span: Span) -> bool
- {
- if self.has_param_types() || self.has_self_ty() {
- if let Some(result) = cache.borrow().get(self) {
- return *result;
- }
- }
- let result =
- tcx.infer_ctxt(param_env.clone(), Reveal::UserFacing)
- .enter(|infcx| {
- traits::type_known_to_meet_bound(&infcx, self, def_id, span)
- });
- if self.has_param_types() || self.has_self_ty() {
- cache.borrow_mut().insert(self, result);
- }
- return result;
- }
-
- // FIXME (@jroesch): I made this public to use it, not sure if should be private
- pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool {
- if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
- return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
- }
-
- assert!(!self.needs_infer());
-
- // Fast-path for primitive types
- let result = match self.sty {
- TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyNever |
- TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
- mutbl: hir::MutImmutable, ..
- }) => Some(false),
-
- TyStr | TyRef(_, TypeAndMut {
- mutbl: hir::MutMutable, ..
- }) => Some(true),
-
- TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) |
- TyClosure(..) | TyAdt(..) | TyAnon(..) |
- TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
- }.unwrap_or_else(|| {
- !self.impls_bound(tcx, param_env,
- tcx.require_lang_item(lang_items::CopyTraitLangItem),
- ¶m_env.is_copy_cache, span) });
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
- } else {
- TypeFlags::MOVENESS_CACHED
- });
- }
-
- result
+ pub fn moves_by_default(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span)
+ -> bool {
+ !tcx.at(span).is_copy_raw(param_env.and(self))
}
- #[inline]
- pub fn is_sized(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool
+ pub fn is_sized(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span)-> bool
{
- if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
- return self.flags.get().intersects(TypeFlags::IS_SIZED);
- }
-
- self.is_sized_uncached(tcx, param_env, span)
- }
-
- fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool {
- assert!(!self.needs_infer());
-
- // Fast-path for primitive types
- let result = match self.sty {
- TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
- TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
- TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
-
- TyStr | TyDynamic(..) | TySlice(_) => Some(false),
-
- TyAdt(..) | TyProjection(..) | TyParam(..) |
- TyInfer(..) | TyAnon(..) | TyError => None
- }.unwrap_or_else(|| {
- self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::SizedTraitLangItem),
- ¶m_env.is_sized_cache, span) });
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
- } else {
- TypeFlags::SIZEDNESS_CACHED
- });
- }
-
- result
+ tcx.at(span).is_sized_raw(param_env.and(self))
}
- /// Returns `true` if and only if there are no `UnsafeCell`s
- /// nested within the type (ignoring `PhantomData` or pointers).
- #[inline]
- pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool
+ pub fn is_freeze(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span)-> bool
{
- if self.flags.get().intersects(TypeFlags::FREEZENESS_CACHED) {
- return self.flags.get().intersects(TypeFlags::IS_FREEZE);
- }
-
- self.is_freeze_uncached(tcx, param_env, span)
- }
-
- fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool {
- assert!(!self.needs_infer());
-
- // Fast-path for primitive types
- let result = match self.sty {
- TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
- TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
- TyStr | TyNever => Some(true),
-
- TyArray(..) | TySlice(_) |
- TyTuple(..) | TyClosure(..) | TyAdt(..) |
- TyDynamic(..) | TyProjection(..) | TyParam(..) |
- TyInfer(..) | TyAnon(..) | TyError => None
- }.unwrap_or_else(|| {
- self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::FreezeTraitLangItem),
- ¶m_env.is_freeze_cache, span) });
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::FREEZENESS_CACHED | TypeFlags::IS_FREEZE
- } else {
- TypeFlags::FREEZENESS_CACHED
- });
- }
-
- result
+ tcx.at(span).is_freeze_raw(param_env.and(self))
}
/// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
/// (Note that this implies that if `ty` has a destructor attached,
/// then `needs_drop` will definitely return `true` for `ty`.)
#[inline]
- pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>) -> bool {
- if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
- return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
- }
-
- self.needs_drop_uncached(tcx, param_env, &mut FxHashSet())
- }
-
- fn needs_drop_inner(&'tcx self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
- stack: &mut FxHashSet<Ty<'tcx>>)
- -> bool {
- if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
- return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
- }
-
- // This should be reported as an error by `check_representable`.
- //
- // Consider the type as not needing drop in the meanwhile to avoid
- // further errors.
- if let Some(_) = stack.replace(self) {
- return false;
- }
-
- let needs_drop = self.needs_drop_uncached(tcx, param_env, stack);
-
- // "Pop" the cycle detection "stack".
- stack.remove(self);
-
- needs_drop
- }
-
- fn needs_drop_uncached(&'tcx self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
- stack: &mut FxHashSet<Ty<'tcx>>)
- -> bool {
- assert!(!self.needs_infer());
-
- let result = match self.sty {
- // Fast-path for primitive types
- ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
- ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
- ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
- ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
-
- // Issue #22536: We first query type_moves_by_default. It sees a
- // normalized version of the type, and therefore will definitely
- // know whether the type implements Copy (and thus needs no
- // cleanup/drop/zeroing) ...
- _ if !self.moves_by_default(tcx, param_env, DUMMY_SP) => false,
-
- // ... (issue #22536 continued) but as an optimization, still use
- // prior logic of asking for the structural "may drop".
-
- // FIXME(#22815): Note that this is a conservative heuristic;
- // it may report that the type "may drop" when actual type does
- // not actually have a destructor associated with it. But since
- // the type absolutely did not have the `Copy` bound attached
- // (see above), it is sound to treat it as having a destructor.
-
- // User destructors are the only way to have concrete drop types.
- ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
-
- // Can refer to a type which may drop.
- // FIXME(eddyb) check this against a ParameterEnvironment.
- ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
- ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
-
- // Structural recursion.
- ty::TyArray(ty, _) | ty::TySlice(ty) => {
- ty.needs_drop_inner(tcx, param_env, stack)
- }
-
- ty::TyClosure(def_id, ref substs) => {
- substs.upvar_tys(def_id, tcx)
- .any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
- }
-
- ty::TyTuple(ref tys, _) => {
- tys.iter().any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
- }
-
- // unions don't have destructors regardless of the child types
- ty::TyAdt(def, _) if def.is_union() => false,
-
- ty::TyAdt(def, substs) => {
- def.variants.iter().any(|v| {
- v.fields.iter().any(|f| {
- f.ty(tcx, substs).needs_drop_inner(tcx, param_env, stack)
- })
- })
- }
- };
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::NEEDS_DROP_CACHED | TypeFlags::NEEDS_DROP
- } else {
- TypeFlags::NEEDS_DROP_CACHED
- });
- }
-
- result
+ pub fn needs_drop(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>)
+ -> bool {
+ tcx.needs_drop_raw(param_env.and(self))
}
#[inline]
r
}
}
+
+fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+ let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
+ tcx.infer_ctxt(param_env, Reveal::UserFacing)
+ .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+ let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
+ tcx.infer_ctxt(param_env, Reveal::UserFacing)
+ .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+ let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
+ tcx.infer_ctxt(param_env, Reveal::UserFacing)
+ .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+
+ let needs_drop = |ty: Ty<'tcx>| -> bool {
+ match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
+ Ok(v) => v,
+ Err(_) => {
+ // Cycles should be reported as an error by `check_representable`.
+ //
+ // Consider the type as not needing drop in the meanwhile to avoid
+ // further errors.
+ false
+ }
+ }
+ };
+
+ assert!(!ty.needs_infer());
+
+ match ty.sty {
+ // Fast-path for primitive types
+ ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
+ ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
+ ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
+ ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
+
+ // Issue #22536: We first query type_moves_by_default. It sees a
+ // normalized version of the type, and therefore will definitely
+ // know whether the type implements Copy (and thus needs no
+ // cleanup/drop/zeroing) ...
+ _ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false,
+
+ // ... (issue #22536 continued) but as an optimization, still use
+ // prior logic of asking for the structural "may drop".
+
+ // FIXME(#22815): Note that this is a conservative heuristic;
+ // it may report that the type "may drop" when actual type does
+ // not actually have a destructor associated with it. But since
+ // the type absolutely did not have the `Copy` bound attached
+ // (see above), it is sound to treat it as having a destructor.
+
+ // User destructors are the only way to have concrete drop types.
+ ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
+
+ // Can refer to a type which may drop.
+ // FIXME(eddyb) check this against a ParamEnv.
+ ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
+ ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
+
+ // Structural recursion.
+ ty::TyArray(ty, _) | ty::TySlice(ty) => needs_drop(ty),
+
+ ty::TyClosure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
+
+ ty::TyTuple(ref tys, _) => tys.iter().cloned().any(needs_drop),
+
+ // unions don't have destructors regardless of the child types
+ ty::TyAdt(def, _) if def.is_union() => false,
+
+ ty::TyAdt(def, substs) =>
+ def.variants.iter().any(
+ |variant| variant.fields.iter().any(
+ |field| needs_drop(field.ty(tcx, substs)))),
+ }
+}
+
+
+pub fn provide(providers: &mut ty::maps::Providers) {
+ *providers = ty::maps::Providers {
+ is_copy_raw,
+ is_sized_raw,
+ is_freeze_raw,
+ needs_drop_raw,
+ ..*providers
+ };
+}
}
}
-impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
- }
-}
-
-impl<'tcx> fmt::Display for ty::RegionKind {
+impl fmt::Display for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if verbose() {
return write!(f, "{:?}", *self);
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
all_loans: &'a [Loan<'tcx>],
- param_env: &'a ty::ParameterEnvironment<'tcx>,
+ param_env: &'a ty::ParamEnv<'tcx>,
}
impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
dfcx_loans: dfcx_loans,
move_data: move_data,
all_loans: all_loans,
- param_env: &infcx.parameter_environment
+ param_env: &infcx.param_env
};
euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx).consume_body(body);
}
_ => return
}
let id = src.item_id();
- let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
- let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
+ let param_env = tcx.param_env(tcx.hir.local_def_id(id));
+ let move_data = MoveData::gather_moves(mir, tcx, param_env);
let elaborate_patch = {
let mir = &*mir;
let env = MoveDataParamEnv {
self.ctxt.tcx
}
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.ctxt.param_env()
}
impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data }
- fn param_env(&self) -> &'b ty::ParameterEnvironment<'tcx> {
- &self.env.param_env
+
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.env.param_env
}
fn initialization_data_at(&self, loc: Location) -> InitializationData {
// except according to those terms.
-use rustc::ty::{self, TyCtxt, ParameterEnvironment};
+use rustc::ty::{self, TyCtxt};
use rustc::mir::*;
use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::indexed_vec::{IndexVec};
struct MoveDataBuilder<'a, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &'a ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
data: MoveData<'tcx>,
}
impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
fn new(mir: &'a Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &'a ParameterEnvironment<'tcx>)
+ param_env: ty::ParamEnv<'tcx>)
-> Self {
let mut move_paths = IndexVec::new();
let mut path_map = IndexVec::new();
impl<'a, 'tcx> MoveData<'tcx> {
pub fn gather_moves(mir: &Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>)
+ param_env: ty::ParamEnv<'tcx>)
-> Self {
gather_moves(mir, tcx, param_env)
}
fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>)
+ param_env: ty::ParamEnv<'tcx>)
-> MoveData<'tcx> {
let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
pub struct MoveDataParamEnv<'tcx> {
move_data: MoveData<'tcx>,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
}
pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
// steals it, but it forces the `borrowck` query.
let mir = &tcx.mir_validated(def_id).borrow();
- let param_env = tcx.parameter_environment(def_id);
- let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
+ let param_env = tcx.param_env(def_id);
+ let move_data = MoveData::gather_moves(mir, tcx, param_env);
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
let flow_inits =
let ty = lvalue.ty(mir, tcx).to_ty(tcx);
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
- if ty.needs_drop(tcx, &ctxt.param_env) {
+ if ty.needs_drop(tcx, ctxt.param_env) {
each_child(child);
} else {
debug!("on_all_drop_children_bits - skipping")
where F: FnMut(MovePathIndex, DropFlagState)
{
let move_data = &ctxt.move_data;
- let param_env = &ctxt.param_env;
+ let param_env = ctxt.param_env;
debug!("drop_flag_effects_for_location({:?})", loc);
// first, move out of the RHS
lp: &LoanPath<'tcx>,
the_move: &move_data::Move,
moved_lp: &LoanPath<'tcx>,
- _param_env: &ty::ParameterEnvironment<'tcx>) {
+ _param_env: &ty::ParamEnv<'tcx>) {
let (verb, verb_participle) = match use_kind {
MovedInUse => ("use", "used"),
MovedInCapture => ("capture", "captured"),
tcx: self.tcx,
tables: self.tcx.body_tables(b),
region_maps: &self.tcx.region_maps(def_id),
- param_env: &self.tcx.parameter_environment(def_id)
+ param_env: self.tcx.param_env(def_id)
}.visit_body(self.tcx.hir.body(b));
}
}
struct MatchVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
- param_env: &'a ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
region_maps: &'a RegionMaps,
}
///
/// FIXME: this should be done by borrowck.
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
- cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::UserFacing).enter(|infcx| {
+ cx.tcx.infer_ctxt((cx.tables, cx.param_env), Reveal::UserFacing).enter(|infcx| {
let mut checker = MutationChecker {
cx: cx,
};
#![deny(warnings)]
#![feature(box_syntax)]
-#![feature(loop_break_value)]
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![cfg_attr(stage0, feature(rustc_private))]
#![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
extern crate arena;
extern crate getopts;
fn abort_msg(err_count: usize) -> String {
match err_count {
0 => "aborting with no errors (maybe a bug?)".to_owned(),
- 1 => "aborting due to previous error".to_owned(),
- e => format!("aborting due to {} previous errors", e),
+ _ => "aborting due to previous error(s)".to_owned(),
}
}
return;
}
- 1 => s = "aborting due to previous error".to_string(),
- _ => {
- s = format!("aborting due to {} previous errors", self.err_count.get());
- }
+ _ => s = "aborting due to previous error(s)".to_string(),
}
panic!(self.fatal(&s));
if def.has_dtor(cx.tcx) {
return;
}
- let parameter_environment = cx.tcx.empty_parameter_environment();
- // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
- // method
- if !ty.moves_by_default(cx.tcx, ¶meter_environment, item.span) {
+ let param_env = ty::ParamEnv::empty();
+ if !ty.moves_by_default(cx.tcx, param_env, item.span) {
return;
}
- if parameter_environment.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
+ if param_env.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
item.span,
"type could implement `Copy`; consider adding `impl \
traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
trait_ref.to_poly_trait_predicate());
- let param_env = tcx.parameter_environment(method.def_id);
+ let param_env = tcx.param_env(method.def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut selcx = traits::SelectionContext::new(&infcx);
match selcx.select(&obligation) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
if let hir::ItemUnion(ref vdata, _) = item.node {
- let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
+ let item_def_id = ctx.tcx.hir.local_def_id(item.id);
+ let param_env = ctx.tcx.param_env(item_def_id);
for field in vdata.fields() {
let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
if field_ty.needs_drop(ctx.tcx, param_env) {
-> BlockAnd<Operand<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
- let topmost_scope = self.topmost_scope(); // FIXME(#6393)
- self.as_operand(block, Some(topmost_scope), expr)
+ let local_scope = self.local_scope();
+ self.as_operand(block, local_scope, expr)
}
/// Compile `expr` into a value that can be used as an operand.
-> BlockAnd<Rvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
- let topmost_scope = self.topmost_scope(); // FIXME(#6393)
- self.as_rvalue(block, Some(topmost_scope), expr)
+ let local_scope = self.local_scope();
+ self.as_rvalue(block, local_scope, expr)
}
/// Compile `expr`, yielding an rvalue.
scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Rvalue<'tcx>> {
- debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
+ debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
let this = self;
let expr_span = expr.span;
temp_lifetime: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Lvalue<'tcx>> {
- debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
+ debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})",
+ block, temp_lifetime, expr);
let this = self;
if let ExprKind::Scope { extent, value } = expr.kind {
{
let span = tcx.hir.span(ctor_id);
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
- let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id));
+ let pe = tcx.param_env(tcx.hir.local_def_id(ctor_id));
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
let (mut mir, src) =
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
mir
}
-pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
- body_id: hir::BodyId)
- -> Mir<'tcx> {
+fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+ body_id: hir::BodyId)
+ -> Mir<'tcx> {
let tcx = hir.tcx();
let ast_expr = &tcx.hir.body(body_id).value;
let ty = hir.tables().expr_ty_adjusted(ast_expr);
builder.finish(vec![], ty)
}
-pub fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
body_id: hir::BodyId)
-> Mir<'tcx> {
let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
use rustc::ty::subst::{Kind, Subst};
use rustc::ty::{Ty, TyCtxt};
use rustc::mir::*;
+use rustc::mir::transform::MirSource;
use syntax_pos::Span;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::fx::FxHashMap;
self.scopes.last().expect("topmost_scope: no scopes present").extent
}
+ /// Returns the scope that we should use as the lifetime of an
+ /// operand. Basically, an operand must live until it is consumed.
+ /// This is similar to, but not quite the same as, the temporary
+ /// scope (which can be larger or smaller).
+ ///
+ /// Consider:
+ ///
+ /// let x = foo(bar(X, Y));
+ ///
+ /// We wish to pop the storage for X and Y after `bar()` is
+ /// called, not after the whole `let` is completed.
+ ///
+ /// As another example, if the second argument diverges:
+ ///
+ /// foo(Box::new(2), panic!())
+ ///
+ /// We would allocate the box but then free it on the unwinding
+ /// path; we would also emit a free on the 'success' path from
+ /// panic, but that will turn out to be removed as dead-code.
+ ///
+ /// When building statics/constants, returns `None` since
+ /// intermediate values do not have to be dropped in that case.
+ pub fn local_scope(&self) -> Option<CodeExtent> {
+ match self.hir.src {
+ MirSource::Const(_) |
+ MirSource::Static(..) =>
+ // No need to free storage in this context.
+ None,
+ MirSource::Fn(_) =>
+ Some(self.topmost_scope()),
+ MirSource::Promoted(..) =>
+ bug!(),
+ }
+ }
+
// Scheduling drops
// ================
/// Indicates that `lvalue` should be dropped on exit from
tcx: TyCtxt<'a, 'gcx, 'tcx>,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
pub region_maps: Rc<RegionMaps>,
+
+ /// This is `Constness::Const` if we are compiling a `static`,
+ /// `const`, or the body of a `const fn`.
constness: hir::Constness,
+ /// What are we compiling?
+ pub src: MirSource,
+
/// True if this constant/function needs overflow checks.
check_overflow: bool,
}
// Constants and const fn's always need overflow checks.
check_overflow |= constness == hir::Constness::Const;
- Cx { tcx, infcx, region_maps, constness, check_overflow }
+ Cx { tcx, infcx, region_maps, constness, src, check_overflow }
}
}
type with inference types/regions",
ty);
});
- ty.needs_drop(self.tcx.global_tcx(), &self.infcx.parameter_environment)
+ ty.needs_drop(self.tcx.global_tcx(), self.infcx.param_env)
}
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
-> &'tcx Mir<'tcx>
{
debug!("make_shim({:?})", instance);
- let did = instance.def_id();
- let param_env = tcx.parameter_environment(did);
let mut result = match instance {
ty::InstanceDef::Item(..) =>
)
}
ty::InstanceDef::DropGlue(def_id, ty) => {
- build_drop_shim(tcx, ¶m_env, def_id, ty)
+ build_drop_shim(tcx, def_id, ty)
}
ty::InstanceDef::Intrinsic(_) => {
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
}
fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
def_id: DefId,
ty: Option<Ty<'tcx>>)
-> Mir<'tcx>
if let Some(..) = ty {
let patch = {
+ let param_env = tcx.param_env(def_id);
let mut elaborator = DropShimElaborator {
mir: &mir,
patch: MirPatch::new(&mir),
- tcx, param_env
+ tcx,
+ param_env
};
let dropee = Lvalue::Local(Local::new(1+0)).deref();
let resume_block = elaborator.patch.resume_block();
mir: &'a Mir<'tcx>,
patch: MirPatch<'tcx>,
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &'a ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
}
impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> {
fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
fn mir(&self) -> &'a Mir<'tcx> { self.mir }
fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> { self.param_env }
+ fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
if let DropFlagMode::Shallow = mode {
// FIXME: Give a bonus to functions with only a single caller
let def_id = tcx.hir.local_def_id(self.source.item_id());
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
let mut first_block = true;
let mut cost = 0;
// a regular goto.
let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
let ty = ty.to_ty(tcx);
- if ty.needs_drop(tcx, ¶m_env) {
+ if ty.needs_drop(tcx, param_env) {
cost += CALL_PENALTY;
if let Some(unwind) = unwind {
work_list.push(unwind);
}
}
-fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>,
+fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>) -> Option<u64> {
tcx.infer_ctxt(param_env, traits::Reveal::All).enter(|infcx| {
ty.layout(&infcx).ok().map(|layout| {
/// Remove flags which are impossible for the given type.
fn restrict(&mut self, ty: Ty<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>) {
+ param_env: ty::ParamEnv<'tcx>) {
if ty.is_freeze(tcx, param_env, DUMMY_SP) {
*self = *self - Qualif::MUTABLE_INTERIOR;
}
mir: &'a Mir<'tcx>,
rpo: ReversePostorder<'a, 'tcx>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
temp_qualif: IndexVec<Local, Option<Qualif>>,
return_qualif: Option<Qualif>,
qualif: Qualif,
impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
mir: &'a Mir<'tcx>,
mode: Mode)
/// Add the given type's qualification to self.qualif.
fn add_type(&mut self, ty: Ty<'tcx>) {
self.add(Qualif::MUTABLE_INTERIOR | Qualif::NEEDS_DROP);
- self.qualif.restrict(ty, self.tcx, &self.param_env);
+ self.qualif.restrict(ty, self.tcx, self.param_env);
}
/// Within the provided closure, self.qualif will start
static, use a constant instead");
}
let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
- this.qualif.restrict(ty, this.tcx, &this.param_env);
+ this.qualif.restrict(ty, this.tcx, this.param_env);
}
ProjectionElem::ConstantIndex {..} |
return Qualif::NOT_CONST.bits();
}
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
qualifier.qualify_const().bits()
MirSource::Const(_) |
MirSource::Promoted(..) => return
};
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
if mode == Mode::Fn || mode == Mode::ConstFn {
// This is ugly because Qualifier holds onto mir,
// broken MIR, so try not to report duplicate errors.
return;
}
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut checker = TypeChecker::new(&infcx, item_id);
{
fn patch(&mut self) -> &mut MirPatch<'tcx>;
fn mir(&self) -> &'a Mir<'tcx>;
fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx>;
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx>;
+ fn param_env(&self) -> ty::ParamEnv<'tcx>;
fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle;
fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>>;
in_fn: bool,
promotable: bool,
mut_rvalue_borrows: NodeSet,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
}
// Adds the worst effect out of all the values of one type.
fn add_type(&mut self, ty: Ty<'gcx>) {
- if !ty.is_freeze(self.tcx, &self.param_env, DUMMY_SP) {
+ if !ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
self.promotable = false;
}
- if ty.needs_drop(self.tcx, &self.param_env) {
+ if ty.needs_drop(self.tcx, self.param_env) {
self.promotable = false;
}
}
}
let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
- let param_env = infcx.parameter_environment.clone();
+ let param_env = infcx.param_env.clone();
let outer_penv = mem::replace(&mut self.param_env, param_env);
let region_maps = &self.tcx.region_maps(item_def_id);;
euv::ExprUseVisitor::new(self, region_maps, &infcx).consume_body(body);
in_fn: false,
promotable: false,
mut_rvalue_borrows: NodeSet(),
- param_env: tcx.empty_parameter_environment(),
+ param_env: ty::ParamEnv::empty(),
}.as_deep_visitor());
tcx.sess.abort_if_errors();
}
pub struct SharedCrateContext<'a, 'tcx: 'a> {
exported_symbols: NodeSet,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- empty_param_env: ty::ParameterEnvironment<'tcx>,
check_overflow: bool,
use_dll_storage_attrs: bool,
SharedCrateContext {
exported_symbols: exported_symbols,
- empty_param_env: tcx.empty_parameter_environment(),
tcx: tcx,
check_overflow: check_overflow,
use_dll_storage_attrs: use_dll_storage_attrs,
}
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
- ty.needs_drop(self.tcx, &self.empty_param_env)
+ ty.needs_drop(self.tcx, ty::ParamEnv::empty())
}
pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
- ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP)
+ ty.is_sized(self.tcx, ty::ParamEnv::empty(), DUMMY_SP)
}
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
- ty.is_freeze(self.tcx, &self.empty_param_env, DUMMY_SP)
+ ty.is_freeze(self.tcx, ty::ParamEnv::empty(), DUMMY_SP)
}
pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
// Finally we register each of these predicates as an obligation in
// a fresh FulfillmentCtxt, and invoke select_all_or_error.
- // Create a parameter environment that represents the implementation's
- // method.
- let impl_param_env = tcx.parameter_environment(impl_m.def_id);
-
// Create mapping from impl to skolemized.
let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
- let trait_param_env = impl_param_env.with_caller_bounds(
- tcx.intern_predicates(&hybrid_preds.predicates));
- let trait_param_env = traits::normalize_param_env_or_error(tcx,
- impl_m.def_id,
- trait_param_env,
- normalize_cause.clone());
-
- tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
+ let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates));
+ let param_env = traits::normalize_param_env_or_error(tcx,
+ impl_m.def_id,
+ param_env,
+ normalize_cause.clone());
+
+ tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let inh = Inherited::new(infcx, impl_m.def_id);
let infcx = &inh.infcx;
debug!("compare_impl_method: caller_bounds={:?}",
- infcx.parameter_environment.caller_bounds);
+ infcx.param_env.caller_bounds);
let mut selcx = traits::SelectionContext::new(&infcx);
let region_maps = RegionMaps::new();
let mut free_regions = FreeRegionMap::new();
free_regions.relate_free_regions_from_predicates(
- &infcx.parameter_environment.caller_bounds);
+ &infcx.param_env.caller_bounds);
infcx.resolve_regions_and_report_errors(impl_m.def_id, ®ion_maps, &free_regions);
} else {
let fcx = FnCtxt::new(&inh, impl_m_node_id);
// check that the impl type can be made to match the trait type.
- let impl_param_env = tcx.parameter_environment(self_type_did);
+ let impl_param_env = tcx.param_env(self_type_did);
tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| {
let tcx = infcx.tcx;
let mut fulfillment_cx = traits::FulfillmentContext::new();
param_ty: ty::ParamTy) {
// FIXME -- Do we want to commit to this behavior for param bounds?
- let bounds: Vec<_> = self.parameter_environment
+ let bounds: Vec<_> = self.param_env
.caller_bounds
.iter()
.filter_map(|predicate| {
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
trait_def_id);
- let caller_predicates = self.parameter_environment.caller_bounds.to_vec();
+ let caller_predicates = self.param_env.caller_bounds.to_vec();
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
.filter_map(|p| p.to_opt_poly_trait_ref())
.filter(|b| b.def_id() == trait_def_id) {
pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
-> InheritedBuilder<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty();
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
InheritedBuilder {
infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
def_id,
let index = generics.type_param_to_index[&def_id.index];
ty::GenericPredicates {
parent: None,
- predicates: self.parameter_environment.caller_bounds.iter().filter(|predicate| {
+ predicates: self.param_env.caller_bounds.iter().filter(|predicate| {
match **predicate {
ty::Predicate::Trait(ref data) => {
data.0.self_ty().is_param(index)
let subject = self.tcx.hir.local_def_id(item_id);
let mut rcx = RegionCtxt::new(self, RepeatingScope(item_id), item_id, Subject(subject));
rcx.free_region_map.relate_free_regions_from_predicates(
- &self.parameter_environment.caller_bounds);
+ &self.param_env.caller_bounds);
rcx.relate_free_regions(wf_tys, item_id, span);
rcx.visit_region_obligations(item_id);
rcx.resolve_regions_and_report_errors();
}
rcx.free_region_map.relate_free_regions_from_predicates(
- &self.parameter_environment.caller_bounds);
+ &self.param_env.caller_bounds);
rcx.resolve_regions_and_report_errors();
fn declared_generic_bounds_from_env(&self, generic: GenericKind<'tcx>)
-> Vec<ty::Region<'tcx>>
{
- let param_env = &self.parameter_environment;
+ let param_env = &self.param_env;
// To start, collect bounds from user:
let mut param_bounds = self.tcx.required_region_bounds(generic.to_ty(self.tcx),
self_type);
let span = tcx.hir.span(impl_node_id);
- let param_env = tcx.parameter_environment(impl_did);
+ let param_env = tcx.param_env(impl_did);
assert!(!self_type.has_escaping_regions());
debug!("visit_implementation_of_copy: self_type={:?} (free)",
target);
let span = tcx.hir.span(impl_node_id);
- let param_env = tcx.parameter_environment(impl_did);
+ let param_env = tcx.param_env(impl_did);
assert!(!source.has_escaping_regions());
let err_info = CoerceUnsizedInfo { custom_kind: None };
// Finally, resolve all regions.
let region_maps = RegionMaps::new();
let mut free_regions = FreeRegionMap::new();
- free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
+ free_regions.relate_free_regions_from_predicates(&infcx.param_env
.caller_bounds);
infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions);
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
-#![feature(loop_break_value)]
#![feature(never_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![cfg_attr(stage0, feature(rustc_private))]
#![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
///
/// The returned value is `None` if the definition could not be inlined,
/// and `Some` of a vector of items if it was successfully expanded.
-pub fn try_inline(cx: &DocContext, def: Def, into: Option<ast::Name>)
+pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
-> Option<Vec<clean::Item>> {
if def == Def::Err { return None }
let did = def.def_id();
if did.is_local() { return None }
- try_inline_def(cx, def).map(|vec| {
- vec.into_iter().map(|mut item| {
- match into {
- Some(into) if item.name.is_some() => {
- item.name = Some(into.clean(cx));
- }
- _ => {}
- }
- item
- }).collect()
- })
-}
-
-fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
- let tcx = cx.tcx;
let mut ret = Vec::new();
let inner = match def {
Def::Trait(did) => {
}
_ => return None,
};
- let did = def.def_id();
cx.renderinfo.borrow_mut().inlined.insert(did);
ret.push(clean::Item {
- source: tcx.def_span(did).clean(cx),
- name: Some(tcx.item_name(did).to_string()),
+ source: cx.tcx.def_span(did).clean(cx),
+ name: Some(name.clean(cx)),
attrs: load_attrs(cx, did),
inner: inner,
visibility: Some(clean::Public),
- stability: tcx.lookup_stability(did).clean(cx),
- deprecation: tcx.lookup_deprecation(did).clean(cx),
+ stability: cx.tcx.lookup_stability(did).clean(cx),
+ deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
def_id: did,
});
Some(ret)
let def_id = item.def.def_id();
if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
if !visited.insert(def_id) { continue }
- if let Some(i) = try_inline_def(cx, item.def) {
+ if let Some(i) = try_inline(cx, item.def, item.name) {
items.extend(i)
}
}
} else {
let name = self.name;
if !denied {
- if let Some(items) = inline::try_inline(cx, path.def, Some(name)) {
+ if let Some(items) = inline::try_inline(cx, path.def, name) {
return items;
}
}
use slice;
use str::{self, Utf8Error};
-/// A type representing an owned C-compatible string
+/// A type representing an owned C-compatible string.
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
-/// A `CString` is created from either a byte slice or a byte vector. A `u8`
-/// slice can be obtained with the `as_bytes` method. Slices produced from a
+/// A `CString` is created from either a byte slice or a byte vector. A [`u8`]
+/// slice can be obtained with the `as_bytes` method. Slices produced from a
/// `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
+/// [`u8`]: ../primitive.u8.html
+///
/// # Examples
///
/// ```no_run
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
-/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
+/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
/// interface to other consumers.
///
+/// [`from_ptr`]: #method.from_ptr
+///
/// # Examples
///
-/// Inspecting a foreign C string
+/// Inspecting a foreign C string:
///
/// ```no_run
/// use std::ffi::CStr;
/// }
/// ```
///
-/// Passing a Rust-originating C string
+/// Passing a Rust-originating C string:
///
/// ```no_run
/// use std::ffi::{CString, CStr};
/// work(&s);
/// ```
///
-/// Converting a foreign C string into a Rust `String`
+/// Converting a foreign C string into a Rust [`String`]:
+///
+/// [`String`]: ../string/struct.String.html
///
/// ```no_run
/// use std::ffi::CStr;
inner: [c_char]
}
-/// An error returned from `CString::new` to indicate that a nul byte was found
+/// An error returned from [`CString::new`] to indicate that a nul byte was found
/// in the vector provided.
+///
+/// [`CString::new`]: struct.CString.html#method.new
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);
-/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
+/// An error returned from [`CStr::from_bytes_with_nul`] to indicate that a nul
/// byte was found too early in the slice provided or one wasn't found at all.
+///
+/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub struct FromBytesWithNulError {
}
}
-/// An error returned from `CString::into_string` to indicate that a UTF-8 error
+/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error
/// was encountered during the conversion.
+///
+/// [`CString::into_string`]: struct.CString.html#method.into_string
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstring_into", since = "1.7.0")]
pub struct IntoStringError {
/// Creates a C-compatible string from a byte vector without checking for
/// interior 0 bytes.
///
- /// This method is equivalent to `new` except that no runtime assertion
+ /// This method is equivalent to [`new`] except that no runtime assertion
/// is made that `v` contains no 0 bytes, and it requires an actual
/// byte vector, not anything that can be converted to one with Into.
///
+ /// [`new`]: #method.new
+ ///
/// # Examples
///
/// ```
/// # Safety
///
/// This should only ever be called with a pointer that was earlier
- /// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take
+ /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g. trying to take
/// ownership of a string that was allocated by foreign code) is likely to lead
/// to undefined behavior or allocator corruption.
+ ///
+ /// [`into_raw`]: #method.into_raw
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = libc::strlen(ptr) + 1; // Including the NUL byte
/// Transfers ownership of the string to a C caller.
///
/// The pointer must be returned to Rust and reconstituted using
- /// `from_raw` to be properly deallocated. Specifically, one
+ /// [`from_raw`] to be properly deallocated. Specifically, one
/// should *not* use the standard C `free` function to deallocate
/// this string.
///
- /// Failure to call `from_raw` will lead to a memory leak.
+ /// Failure to call [`from_raw`] will lead to a memory leak.
+ ///
+ /// [`from_raw`]: #method.from_raw
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub fn into_raw(self) -> *mut c_char {
Box::into_raw(self.into_inner()) as *mut c_char
}
- /// Converts the `CString` into a `String` if it contains valid Unicode data.
+ /// Converts the `CString` into a [`String`] if it contains valid Unicode data.
///
/// On failure, ownership of the original `CString` is returned.
+ ///
+ /// [`String`]: ../string/struct.String.html
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_string(self) -> Result<String, IntoStringError> {
String::from_utf8(self.into_bytes())
vec
}
- /// Equivalent to the `into_bytes` function except that the returned vector
+ /// Equivalent to the [`into_bytes`] function except that the returned vector
/// includes the trailing nul byte.
+ ///
+ /// [`into_bytes`]: #method.into_bytes
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_bytes_with_nul(self) -> Vec<u8> {
self.into_inner().into_vec()
&self.inner[..self.inner.len() - 1]
}
- /// Equivalent to the `as_bytes` function except that the returned slice
+ /// Equivalent to the [`as_bytes`] function except that the returned slice
/// includes the trailing nul byte.
+ ///
+ /// [`as_bytes`]: #method.as_bytes
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes_with_nul(&self) -> &[u8] {
&self.inner
}
- /// Extracts a `CStr` slice containing the entire string.
+ /// Extracts a [`CStr`] slice containing the entire string.
+ ///
+ /// [`CStr`]: struct.CStr.html
#[unstable(feature = "as_c_str", issue = "40380")]
pub fn as_c_str(&self) -> &CStr {
&*self
}
- /// Converts this `CString` into a boxed `CStr`.
+ /// Converts this `CString` into a boxed [`CStr`].
+ ///
+ /// [`CStr`]: struct.CStr.html
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_boxed_c_str(self) -> Box<CStr> {
unsafe { mem::transmute(self.into_inner()) }
}
- // Bypass "move out of struct which implements `Drop` trait" restriction.
+ // Bypass "move out of struct which implements [`Drop`] trait" restriction.
+ ///
+ /// [`Drop`]: ../ops/trait.Drop.html
fn into_inner(self) -> Box<[u8]> {
unsafe {
let result = ptr::read(&self.inner);
impl NulError {
/// Returns the position of the nul byte in the slice that was provided to
- /// `CString::new`.
+ /// [`CString::new`].
+ ///
+ /// [`CString::new`]: struct.CString.html#method.new
///
/// # Examples
///
}
impl IntoStringError {
- /// Consumes this error, returning original `CString` which generated the
+ /// Consumes this error, returning original [`CString`] which generated the
/// error.
+ ///
+ /// [`CString`]: struct.CString.html
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_cstring(self) -> CString {
self.inner
/// allows inspection and interoperation of non-owned C strings. This method
/// is unsafe for a number of reasons:
///
- /// * There is no guarantee to the validity of `ptr`
+ /// * There is no guarantee to the validity of `ptr`.
/// * The returned lifetime is not guaranteed to be the actual lifetime of
- /// `ptr`
+ /// `ptr`.
/// * There is no guarantee that the memory pointed to by `ptr` contains a
/// valid nul terminator byte at the end of the string.
///
/// Converts this C string to a byte slice containing the trailing 0 byte.
///
- /// This function is the equivalent of `to_bytes` except that it will retain
+ /// This function is the equivalent of [`to_bytes`] except that it will retain
/// the trailing nul instead of chopping it off.
///
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
+ ///
+ /// [`to_bytes`]: #method.to_bytes
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute(&self.inner) }
}
- /// Yields a `&str` slice if the `CStr` contains valid UTF-8.
+ /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
///
/// This function will calculate the length of this string and check for
- /// UTF-8 validity, and then return the `&str` if it's valid.
+ /// UTF-8 validity, and then return the [`&str`] if it's valid.
///
/// > **Note**: This method is currently implemented to check for validity
/// > after a 0-cost cast, but it is planned to alter its definition in the
/// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called.
+ ///
+ /// [`&str`]: ../primitive.str.html
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
// NB: When CStr is changed to perform the length check in .to_bytes()
str::from_utf8(self.to_bytes())
}
- /// Converts a `CStr` into a `Cow<str>`.
+ /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
///
/// This function will calculate the length of this string (which normally
/// requires a linear amount of work to be done) and then return the
- /// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
+ /// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences
/// with `U+FFFD REPLACEMENT CHARACTER`.
///
/// > **Note**: This method is currently implemented to check for validity
/// > after a 0-cost cast, but it is planned to alter its definition in the
/// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called.
+ ///
+ /// [`Cow`]: ../borrow/enum.Cow.html
+ /// [`str`]: ../primitive.str.html
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.to_bytes())
}
- /// Converts a `Box<CStr>` into a `CString` without copying or allocating.
+ /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+ ///
+ /// [`Box`]: ../boxed/struct.Box.html
+ /// [`CString`]: struct.CString.html
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_c_string(self: Box<CStr>) -> CString {
unsafe { mem::transmute(self) }
use sys_common;
use sys_common::thread_info;
use thread::Thread;
+ #[cfg(not(feature = "backtrace"))]
+ use mem;
sys::init();
sys::args::init(argc, argv);
// Let's run some code!
+ #[cfg(feature = "backtrace")]
let res = panic::catch_unwind(|| {
::sys_common::backtrace::__rust_begin_short_backtrace(main)
});
+ #[cfg(not(feature = "backtrace"))]
+ let res = panic::catch_unwind(mem::transmute::<_, fn()>(main));
sys_common::cleanup();
res.is_err()
};
-/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of Dmitry Vyukov.
- */
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
//! A mostly lock-free multi-producer, single consumer queue.
//!
-/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of Dmitry Vyukov.
- */
-
-// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
//! A single-producer single-consumer concurrent queue
//!
//! concurrently between two threads. This data structure is safe to use and
//! enforces the semantics that there is one pusher and one popper.
+// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+
use alloc::boxed::Box;
use core::ptr;
use core::cell::UnsafeCell;
pub unsafe fn destroy(key: Key) {
keys().remove(&key);
}
+
+#[inline]
+pub fn requires_synchronized_create() -> bool {
+ false
+}
}
unsafe {
thread_info::set(imp::guard::current(), their_thread);
+ #[cfg(feature = "backtrace")]
let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
::sys_common::backtrace::__rust_begin_short_backtrace(f)
}));
+ #[cfg(not(feature = "backtrace"))]
+ let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f));
*their_packet.get() = Some(try_result);
}
};
/// want to specify the stack size or the name of the thread, use this API
/// instead.
///
+/// As you can see in the signature of `spawn` there are two constraints on
+/// both the closure given to `spawn` and its return value, let's explain them:
+///
+/// - The `'static` constraint means that the closure and its return value
+/// must have a lifetime of the whole program execution. The reason for this
+/// is that threads can `detach` and outlive the lifetime they have been
+/// created in.
+/// Indeed if the thread, and by extension its return value, can outlive their
+/// caller, we need to make sure that they will be valid afterwards, and since
+/// we *can't* know when it will return we need to have them valid as long as
+/// possible, that is until the end of the program, hence the `'static`
+/// lifetime.
+/// - The [`Send`] constraint is because the closure will need to be passed
+/// *by value* from the thread where it is spawned to the new thread. Its
+/// return value will need to be passed from the new thread to the thread
+/// where it is `join`ed.
+/// As a reminder, the [`Send`] marker trait, expresses that it is safe to be
+/// passed from thread to thread. [`Sync`] expresses that it is safe to have a
+/// reference be passed from thread to thread.
+///
/// # Panics
///
/// Panics if the OS fails to create a thread; use [`Builder::spawn`]
/// [`panic`]: ../../std/macro.panic.html
/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
/// [`Builder`]: ../../std/thread/struct.Builder.html
+/// [`Send`]: ../../std/marker/trait.Send.html
+/// [`Sync`]: ../../std/marker/trait.Sync.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
- let mut parser = Parser::new(sess, self.tokens.clone(), None, false);
+ let mut parser = Parser::new(sess, self.tokens.clone(), None, false, false);
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
Success(())
}
-pub fn parse(sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], directory: Option<Directory>)
+pub fn parse(sess: &ParseSess,
+ tts: TokenStream,
+ ms: &[TokenTree],
+ directory: Option<Directory>,
+ recurse_into_modules: bool)
-> NamedParseResult {
- let mut parser = Parser::new(sess, tts, directory, true);
+ let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true);
let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), parser.span.lo));
let mut next_eis = Vec::new(); // or proceed normally
path: cx.current_expansion.module.directory.clone(),
ownership: cx.current_expansion.directory_ownership,
};
- let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), false);
+ let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false);
p.root_module_name = cx.current_expansion.module.mod_path.last()
.map(|id| id.name.as_str().to_string());
ast::ItemKind::MacroDef(ref body) => body.clone().into(),
_ => unreachable!(),
};
- let argument_map = match parse(sess, body, &argument_gram, None) {
+ let argument_map = match parse(sess, body, &argument_gram, None, true) {
Success(m) => m,
Failure(sp, tok) => {
let s = parse_failure_msg(tok);
(active, use_extern_macros, "1.15.0", Some(35896)),
- // Allows `break {expr}` with a value inside `loop`s.
- (active, loop_break_value, "1.14.0", Some(37339)),
-
// Allows #[target_feature(...)]
(active, target_feature, "1.15.0", None),
(accepted, pub_restricted, "1.18.0", Some(32409)),
// The #![windows_subsystem] attribute
(accepted, windows_subsystem, "1.18.0", Some(37499)),
+ // Allows `break {expr}` with a value inside `loop`s.
+ (accepted, loop_break_value, "1.19.0", Some(37339)),
);
// If you change this, please modify src/doc/unstable-book as well. You must
// move that documentation into the relevant place in the other docs, and
}
}
}
- ast::ExprKind::Break(_, Some(_)) => {
- gate_feature_post!(&self, loop_break_value, e.span,
- "`break` with a value is experimental");
- }
ast::ExprKind::Lit(ref lit) => {
if let ast::LitKind::Int(_, ref ty) = lit.node {
match *ty {
match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
Some(&(ascii_char, ascii_name)) => {
let msg =
- format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
+ format!("unicode character '{}' ({}) looks like '{}' ({}), but it's not",
ch, u_name, ascii_char, ascii_name);
err.span_help(span, &msg);
},
// Create a new parser from a source string
pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String)
-> Parser {
- filemap_to_parser(sess, sess.codemap().new_filemap(name, source))
+ let mut parser = filemap_to_parser(sess, sess.codemap().new_filemap(name, source));
+ parser.recurse_into_file_modules = false;
+ parser
}
/// Create a new parser, handling errors as appropriate
/// Given stream and the `ParseSess`, produce a parser
pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser {
- Parser::new(sess, stream, None, false)
+ Parser::new(sess, stream, None, true, false)
}
/// Parse a string representing a character literal into its final form.
Err(_) => panic!("could not get snippet"),
}
}
+
+ // This tests that when parsing a string (rather than a file) we don't try
+ // and read in a file for a module declaration and just parse a stub.
+ // See `recurse_into_file_modules` in the parser.
+ #[test]
+ fn out_of_line_mod() {
+ let sess = ParseSess::new(FilePathMapping::empty());
+ let item = parse_item_from_source_str(
+ "foo".to_owned(),
+ "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
+ &sess,
+ ).unwrap().unwrap();
+
+ if let ast::ItemKind::Mod(ref m) = item.node {
+ assert!(m.items.len() == 2);
+ } else {
+ panic!();
+ }
+ }
}
pub obsolete_set: HashSet<ObsoleteSyntax>,
/// Used to determine the path to externally loaded source files
pub directory: Directory,
+ /// Whether to parse sub-modules in other files.
+ pub recurse_into_file_modules: bool,
/// Name of the root module this parser originated from. If `None`, then the
/// name is not known. This does not change while the parser is descending
/// into modules, and sub-parsers have new values for this name.
pub cfg_mods: bool,
}
+
struct TokenCursor {
frame: TokenCursorFrame,
stack: Vec<TokenCursorFrame>,
pub fn new(sess: &'a ParseSess,
tokens: TokenStream,
directory: Option<Directory>,
+ recurse_into_file_modules: bool,
desugar_doc_comments: bool)
-> Self {
let mut parser = Parser {
prev_token_kind: PrevTokenKind::Other,
restrictions: Restrictions::empty(),
obsolete_set: HashSet::new(),
+ recurse_into_file_modules: recurse_into_file_modules,
directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
root_module_name: None,
expected_tokens: Vec::new(),
let tok = parser.next_tok();
parser.token = tok.tok;
parser.span = tok.sp;
+
if let Some(directory) = directory {
parser.directory = directory;
} else if parser.span != syntax_pos::DUMMY_SP {
parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
parser.directory.path.pop();
}
+
parser.process_potential_macro_variable();
parser
}
mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
let item = self.parse_item_(attrs.clone(), false, true)?;
self.directory.ownership = old_directory_ownership;
+
match item {
Some(i) => Stmt {
id: ast::DUMMY_NODE_ID,
let id = self.parse_ident()?;
if self.check(&token::Semi) {
self.bump();
- if in_cfg {
+ if in_cfg && self.recurse_into_file_modules {
// This mod is in an external file. Let's go get it!
let ModulePathSuccess { path, directory_ownership, warn } =
self.submod_path(id, &outer_attrs, id_span)?;
} else {
let old_directory = self.directory.clone();
self.push_directory(id, &outer_attrs);
+
self.expect(&token::OpenDelim(token::Brace))?;
let mod_inner_lo = self.span;
let attrs = self.parse_inner_attributes()?;
let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
+
self.directory = old_directory;
Ok((id, ItemKind::Mod(module), Some(attrs)))
}
fn submod_path(&mut self,
id: ast::Ident,
outer_attrs: &[ast::Attribute],
- id_sp: Span) -> PResult<'a, ModulePathSuccess> {
+ id_sp: Span)
+ -> PResult<'a, ModulePathSuccess> {
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
return Ok(ModulePathSuccess {
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
path: cx.current_expansion.module.directory.clone(),
ownership: cx.current_expansion.directory_ownership,
};
- macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory))
+ macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true)
}
/// Check if this TokenTree is equal to the other, regardless of span information.
fn main() {
is_send::<Foo>();
//~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
- //~| NOTE within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8`
//~| NOTE: `*const u8` cannot be sent between threads safely
//~| NOTE: required because it appears within the type `Baz`
//~| NOTE: required because it appears within the type `Bar`
fn f(p: Path) { }
//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
-//~| NOTE within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
//~| NOTE `[u8]` does not have a constant size known at compile-time
//~| NOTE required because it appears within the type `std::path::Path`
//~| NOTE all local variables must have a statically known size
const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
const CONST_FOO: str = *"foo";
//~^ ERROR `str: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
static STATIC_BAR: str = *"bar";
//~^ ERROR `str: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
+++ /dev/null
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- loop {
- break 123; //~ ERROR `break` with a value is experimental
- }
-}
fn main() {
send(before());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
- //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `[closure
//~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
send(after());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
- //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `[closure
//~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Nullable<T: NotNull>(T);
+
+pub trait NotNull {}
+
+pub trait IntoNullable {
+ type Nullable;
+}
+
+impl<T: NotNull> IntoNullable for T {
+ type Nullable = Nullable<T>;
+}
+
+impl<T: NotNull> IntoNullable for Nullable<T> {
+ type Nullable = Nullable<T>;
+}
+
+pub trait Expression {
+ type SqlType;
+}
+
+pub trait Column: Expression {}
+
+#[derive(Debug, Copy, Clone)]
+//~^ ERROR the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
+pub enum ColumnInsertValue<Col, Expr> where
+ Col: Column,
+ Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>,
+{
+ Expression(Col, Expr),
+ Default(Col),
+}
+
+fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(loop_break_value)]
#![feature(never_type)]
fn main() {
fn main() {
Index::index(&[] as &[i32], 2u32);
//~^ ERROR E0277
- //~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
//~| NOTE trait message
//~| NOTE required by
Index::index(&[] as &[i32], Foo(2u32));
//~^ ERROR E0277
- //~| NOTE the trait `Index<Foo<u32>>` is not implemented for `[i32]`
//~| NOTE on impl for Foo
//~| NOTE required by
Index::index(&[] as &[i32], Bar(2u32));
//~^ ERROR E0277
- //~| NOTE the trait `Index<Bar<u32>>` is not implemented for `[i32]`
//~| NOTE on impl for Bar
//~| NOTE required by
}
fn main() {
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
//~^ ERROR E0277
- //~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
//~| NOTE a usize is required
//~| NOTE required by
}
//~^ ERROR
//~^^ NOTE a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
//~^^^ NOTE required by `collect`
- //~| NOTE the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
+
let x: String = foobar(); //~ ERROR
//~^ NOTE test error `std::string::String` with `u8` `_` `u32`
//~^^ NOTE required by `foobar`
- //~| NOTE the trait `Foo<u8, _, u32>` is not implemented for `std::string::String`
}
let x = &[1, 2, 3] as &[i32];
x[1i32]; //~ ERROR E0277
//~| NOTE slice indices are of type `usize` or ranges of `usize`
- //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
//~| NOTE required because of the requirements on the impl of `std::ops::Index<i32>`
x[..1i32]; //~ ERROR E0277
//~| NOTE slice indices are of type `usize` or ranges of `usize`
- //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
//~| NOTE requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>`
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo<T: PartialEq>(a: &T, b: T) {
+ a == b; //~ ERROR E0277
+ //~| NOTE can't compare `&T` with `T`
+ //~| HELP the trait `std::cmp::PartialEq<T>` is not implemented for `&T`
+ //~| HELP consider adding a `where &T: std::cmp::PartialEq<T>` bound
+}
+
+fn main() {
+ foo(&1, 1);
+}
// suggest a where-clause, if needed
mem::size_of::<U>();
//~^ ERROR `U: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `U`
//~| HELP consider adding a `where U: std::marker::Sized` bound
//~| NOTE required by `std::mem::size_of`
+ //~| NOTE `U` does not have a constant size known at compile-time
+ //~| HELP the trait `std::marker::Sized` is not implemented for `U`
mem::size_of::<Misc<U>>();
//~^ ERROR `U: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `U`
//~| HELP consider adding a `where U: std::marker::Sized` bound
//~| NOTE required because it appears within the type `Misc<U>`
//~| NOTE required by `std::mem::size_of`
+ //~| NOTE `U` does not have a constant size known at compile-time
+ //~| HELP within `Misc<U>`, the trait `std::marker::Sized` is not implemented for `U`
// ... even if T occurs as a type parameter
<u64 as From<T>>::from;
//~^ ERROR `u64: std::convert::From<T>` is not satisfied
- //~| NOTE 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`
+ //~| NOTE the trait `std::convert::From<T>` is not implemented for `u64`
<u64 as From<<T as Iterator>::Item>>::from;
//~^ ERROR `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
- //~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
//~| HELP consider adding a `where u64:
//~| NOTE required by `std::convert::From::from`
+ //~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
// ... but not if there are inference variables
<Misc<_> as From<T>>::from;
//~^ ERROR `Misc<_>: std::convert::From<T>` is not satisfied
- //~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
//~| NOTE required by `std::convert::From::from`
+ //~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
// ... and also not if the error is not related to the type
mem::size_of::<[T]>();
//~^ ERROR `[T]: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `[T]`
//~| NOTE `[T]` does not have a constant size
//~| NOTE required by `std::mem::size_of`
+ //~| HELP the trait `std::marker::Sized` is not implemented for `[T]`
mem::size_of::<[&U]>();
//~^ ERROR `[&U]: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `[&U]`
//~| NOTE `[&U]` does not have a constant size
//~| NOTE required by `std::mem::size_of`
+ //~| HELP the trait `std::marker::Sized` is not implemented for `[&U]`
}
fn main() {
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that when we compile the static `XXX` into MIR, we do not
+// generate `StorageStart` or `StorageEnd` statements.
+
+// ignore-tidy-linelength
+
+static XXX: &'static Foo = &Foo {
+ tup: "hi",
+ data: &[
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ ]
+};
+
+#[derive(Debug)]
+struct Foo {
+ tup: &'static str,
+ data: &'static [(u32, u32)]
+}
+
+fn main() {
+ println!("{:?}", XXX);
+}
+
+// END RUST SOURCE
+// START rustc.node4.mir_map.0.mir
+// bb0: {
+// _7 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:9: 29:15
+// _8 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:17: 29:23
+// _9 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:25: 29:31
+// _10 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:9: 30:15
+// _11 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:17: 30:23
+// _12 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:25: 30:31
+// _13 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:9: 31:15
+// _14 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:17: 31:23
+// _15 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:25: 31:31
+// _16 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:9: 32:15
+// _17 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:17: 32:23
+// _18 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:25: 32:31
+// _19 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:9: 33:15
+// _20 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:17: 33:23
+// _21 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:25: 33:31
+// _22 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:9: 34:15
+// _23 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:17: 34:23
+// _24 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:25: 34:31
+// _25 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:9: 35:15
+// _26 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:17: 35:23
+// _27 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:25: 35:31
+// _28 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:9: 36:15
+// _29 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:17: 36:23
+// _30 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:25: 36:31
+// _31 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:9: 37:15
+// _32 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:17: 37:23
+// _33 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:25: 37:31
+// _34 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:9: 38:15
+// _35 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:17: 38:23
+// _36 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:25: 38:31
+// _37 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:9: 39:15
+// _38 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:17: 39:23
+// _39 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:25: 39:31
+// _40 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:9: 40:15
+// _41 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:17: 40:23
+// _42 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:25: 40:31
+// _43 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:9: 41:15
+// _44 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:17: 41:23
+// _45 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:25: 41:31
+// _46 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:9: 42:15
+// _47 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:17: 42:23
+// _48 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:25: 42:31
+// _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:12: 43:6
+// _5 = &_6; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+// _4 = &(*_5); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+// _3 = _4 as &'static [(u32, u32)] (Unsize); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+// _2 = Foo { tup: const "hi", data: _3 }; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:29: 44:2
+// _1 = &_2; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+// _0 = &(*_1); // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+// return; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:1: 44:3
+// }
+// END rustc.node4.mir_map.0.mir
// except according to those terms.
// compile-flags: -Z parse-only
-// ignore-tidy-linelength
fn main() {
let y = 0;
//~^ ERROR unknown start of token: \u{37e}
- //~^^ HELP unicode character ';' (Greek Question Mark) looks much like ';' (Semicolon), but it's not
+ //~^^ HELP unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it's not
}
trait Sized {}
#[lang = "copy"]
trait Copy {}
+#[lang = "freeze"]
+trait Freeze {}
#[cfg(target_has_atomic = "8")]
pub unsafe fn atomic_u8(x: *mut u8) {
// like to revisit these and potentially change them. --nmatsakis
#![feature(never_type)]
-#![feature(loop_break_value)]
trait BadDefault {
fn default() -> Self;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(loop_break_value)]
#![feature(never_type)]
#[allow(unused)]
short.next();
assert_eq!(long.size_hint(), (255, Some(255)));
assert_eq!(short.size_hint(), (0, Some(0)));
- assert_eq!(short, RangeInclusive::Empty { at: 42 });
+ assert_eq!(short, 1...0);
assert_eq!(long.len(), 255);
assert_eq!(short.len(), 0);
for i in 3...251 {
assert_eq!(long.next(), Some(i));
}
- assert_eq!(long, RangeInclusive::Empty { at: 251 });
+ assert_eq!(long, 1...0);
// check underflow
let mut narrow = 1...0;
assert_eq!(narrow.next_back(), None);
- assert_eq!(narrow, RangeInclusive::Empty { at: 0 });
+ assert_eq!(narrow, 1...0);
let mut zero = 0u8...0;
assert_eq!(zero.next_back(), Some(0));
assert_eq!(zero.next_back(), None);
- assert_eq!(zero, RangeInclusive::Empty { at: 0 });
+ assert_eq!(zero, 1...0);
let mut high = 255u8...255;
assert_eq!(high.next_back(), Some(255));
assert_eq!(high.next_back(), None);
- assert_eq!(high, RangeInclusive::Empty { at: 255 });
+ assert_eq!(high, 1...0);
// what happens if you have a nonsense range?
let mut nonsense = 10...5;
assert_eq!(nonsense.next(), None);
- assert_eq!(nonsense, RangeInclusive::Empty { at: 10 });
+ assert_eq!(nonsense, 10...5);
// output
assert_eq!(format!("{:?}", 0...10), "0...10");
assert_eq!(format!("{:?}", ...10), "...10");
- assert_eq!(format!("{:?}", long), "[empty range @ 251]");
+ assert_eq!(format!("{:?}", long), "1...0");
}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+pub mod iter {
+ mod range {
+ pub struct StepBy;
+ }
+ pub use self::range::StepBy as DeprecatedStepBy;
+ pub struct StepBy;
+}
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:renamed-via-module.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "bar"]
+
+extern crate foo;
+
+// @has foo/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has foo/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct foo::iter::DeprecatedStepBy"
+// @has foo/iter/struct.StepBy.html
+// @has - '//h1' "Struct foo::iter::StepBy"
+
+// @has bar/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has bar/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct bar::iter::DeprecatedStepBy"
+// @has bar/iter/struct.StepBy.html
+// @has - '//h1' "Struct bar::iter::StepBy"
+pub use foo::iter;
15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable
| ^ cannot move out of captured outer variable in an `Fn` closure
-error: aborting due to previous error
+error: aborting due to previous error(s)
21 | y.into_iter();
| ^ cannot move out of captured outer variable in an `Fn` closure
-error: aborting due to previous error
+error: aborting due to previous error(s)
49 | match Some(A) {
| ^^^^^^^ patterns `Some(B)`, `Some(C)`, `Some(D)` and 2 more not covered
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
15 | impl C { fn f() {} }
| --------- other definition for `f`
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | unsafe impl Send for &'static Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
100 | let y = &mut x;
| ^ cannot borrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
101 | }
| - first borrow ends here
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
| | second mutable borrow occurs here
| first mutable borrow occurs here
-error: aborting due to previous error
+error: aborting due to previous error(s)
43 | fn baz(&self) {}
| ---------------- other definition for `baz`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
| | hint: to prevent move, use `ref _s` or `ref mut _s`
| cannot move out of here
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | \tbar;
| \t^^^ not found in this scope
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | x + 1;
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
-error: aborting due to previous error
+error: aborting due to previous error(s)
22 | | }
| |_____^ impl has extra requirement `'a: 'b`
-error: aborting due to previous error
+error: aborting due to previous error(s)
22 | fn foo() where 'a: 'b { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'a: 'b`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #37166 <https://github.com/rust-lang/rust/issues/37166>
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `fn(&E, F) -> F`
found type `fn(&E, G) -> G`
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | fn b<F: Sync, G>(&self, _x: F) -> F { panic!() } //~ ERROR E0276
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `F: std::marker::Sync`
-error: aborting due to previous error
+error: aborting due to previous error(s)
76 | fn method<G: Getter<usize>>(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `G: Getter<usize>`
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
26 | | }
| |_____^ impl has extra requirement `U: Iterator<B>`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | z: fn() -> Foo + 'a,
| ^^^^^^^^^^^^^^^^ perhaps you forgot parentheses?
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
<Bar as Foo<i32>>
<Bar as Foo<u8>>
-error: aborting due to previous error
+error: aborting due to previous error(s)
<Bar as Foo<u8>>
and 2 others
-error: aborting due to previous error
+error: aborting due to previous error(s)
23 | (&mut self).bar();
| ^^^^ cannot borrow mutably
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
| try removing `&mut` here
| cannot reborrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
| try removing `&mut` here
| cannot reborrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
30 | s.x += 1;
| ^^^^^^^^ cannot mutably borrow immutable field
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
17 | f.baz;
| ^^^ did you mean `bar`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | f.zz;
| ^^ unknown field
-error: aborting due to previous error
+error: aborting due to previous error(s)
| try removing `&mut` here
| cannot reborrow mutably
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | use Foo1;
| ^^^^ no `Foo1` in the root
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
27 | self.s.push('x');
| ^^^^^^ assignment into an immutable reference
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | self.s.push('x');
| ^^^^^^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | self.s.push('x');
| ^^^^^^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | f.s.push('x');
| ^^^ assignment into an immutable reference
-error: aborting due to previous error
+error: aborting due to previous error(s)
58 | *x.0 = 1;
| ^^^^^^^^ cannot borrow as mutable
-error: aborting due to 12 previous errors
+error: aborting due to previous error(s)
and 2 others
= note: required by `Foo::bar`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: method `xxx` has no receiver
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `::<...>` instead of `<...>` if you meant to specify type arguments
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
13 | buf.iter_mut();
| ^^^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `!` instead of `~` if you meant to perform bitwise negation
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: required because it appears within the type `A`
= note: required by `is_send`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `&Bottom`
found type `&Top`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: the trait cannot require that `Self : Sized`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
43 | | }
| |_^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
= note: if you intended to print `}`, you can escape it using `}}`
= note: this error originates in a macro outside of the current crate
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= help: closure was moved because it only implements `FnOnce`
-error: aborting due to previous error
+error: aborting due to previous error(s)
--> $DIR/equality.rs:34:9
|
34 | n + sum_to(n - 1)
- | ^^^^^^^^^^^^^^^^^ the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
+ | ^^^^^^^^^^^^^^^^^ no implementation for `u32 + impl Foo`
|
- = note: no implementation for `u32 + impl Foo`
+ = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
error[E0308]: mismatched types
--> $DIR/equality.rs:53:18
= note: expected type `impl Foo` (i32)
found type `impl Foo` (u32)
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
11 | pub mod baz;
| ^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
| help: consider using a reference instead `&f.v[0]`
| cannot move out of indexed content
-error: aborting due to previous error
+error: aborting due to previous error(s)
| | ...and here (use `ref b` or `ref mut b`)
| hint: to prevent move, use `ref a` or `ref mut a`
-error: aborting due to previous error
+error: aborting due to previous error(s)
note: candidate #1 is defined in the trait `issue_41652_b::Tr`
= help: to disambiguate the method call, write `issue_41652_b::Tr::f(3)` instead
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | | }
| |_^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | | }
| |_^
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | | }
| |_^
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | x.push(z);
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | let a: &mut Vec<Ref<i32>> = x;
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | let a: &mut Vec<Ref<i32>> = x;
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `-D non-snake-case` implied by `-D bad-style`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `-F non-snake-case` implied by `-F bad-style`
-error: aborting due to previous error
+error: aborting due to previous error(s)
28 | #![warn(bad_style)]
| ^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(loop_break_value)]
#![allow(unused_variables)]
use std::ptr;
error[E0571]: `break` with value from a `for` loop
- --> $DIR/loop-break-value-no-repeat.rs:23:9
+ --> $DIR/loop-break-value-no-repeat.rs:22:9
|
-23 | break 22
+22 | break 22
| ^^^^^^^^ can only break with a value inside `loop`
-error: aborting due to previous error
+error: aborting due to previous error(s)
12 | println!(3 + 4);
| ^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
= help: `$NAME` should be written as `{NAME}`
= note: shell formatting not supported; see the documentation for `std::fmt`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
56 | let _ = fake_anon_field_expr!();
| ----------------------- in this macro invocation
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
28 | call_nested_expr_sum!();
| ------------------------ in this macro invocation
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
28 | myprintln!("{}");
| ----------------- in this macro invocation
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `fn(&Bar)`
found type `fn(&mut Bar)`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `foo`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `&{integer}`
found type `{integer}`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `X<X<_, std::string::String>, _>`
found type `X<X<_, {integer}>, _>`
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
--> $DIR/binops.rs:12:5
|
12 | 1 + Some(1);
- | ^^^^^^^^^^^ the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
+ | ^^^^^^^^^^^ no implementation for `{integer} + std::option::Option<{integer}>`
|
- = note: no implementation for `{integer} + std::option::Option<{integer}>`
+ = help: the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
--> $DIR/binops.rs:13:5
|
13 | 2 as usize - Some(1);
- | ^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
+ | ^^^^^^^^^^^^^^^^^^^^ no implementation for `usize - std::option::Option<{integer}>`
|
- = note: no implementation for `usize - std::option::Option<{integer}>`
+ = help: the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
--> $DIR/binops.rs:14:5
|
14 | 3 * ();
- | ^^^^^^ the trait `std::ops::Mul<()>` is not implemented for `{integer}`
+ | ^^^^^^ no implementation for `{integer} * ()`
|
- = note: no implementation for `{integer} * ()`
+ = help: the trait `std::ops::Mul<()>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
--> $DIR/binops.rs:15:5
|
15 | 4 / "";
- | ^^^^^^ the trait `std::ops::Div<&str>` is not implemented for `{integer}`
+ | ^^^^^^ no implementation for `{integer} / &str`
|
- = note: no implementation for `{integer} / &str`
+ = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::string::String>` is not satisfied
--> $DIR/binops.rs:16:5
|
16 | 5 < String::new();
- | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
+ | ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String`
|
- = note: can't compare `{integer}` with `std::string::String`
+ = help: the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
--> $DIR/binops.rs:16:5
|
16 | 5 < String::new();
- | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
+ | ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String`
|
- = note: can't compare `{integer}` with `std::string::String`
+ = help: the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not satisfied
--> $DIR/binops.rs:17:5
|
17 | 6 == Ok(1);
- | ^^^^^^^^^^ the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
+ | ^^^^^^^^^^ can't compare `{integer}` with `std::result::Result<{integer}, _>`
|
- = note: can't compare `{integer}` with `std::result::Result<{integer}, _>`
+ = help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
--> $DIR/cast-rfc0401.rs:63:13
|
63 | let _ = fat_v as *const Foo;
- | ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]`
+ | ^^^^^ `[u8]` does not have a constant size known at compile-time
|
- = note: `[u8]` does not have a constant size known at compile-time
+ = help: the trait `std::marker::Sized` is not implemented for `[u8]`
= note: required for the cast to the object type `Foo`
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/cast-rfc0401.rs:72:13
|
72 | let _ = a as *const Foo;
- | ^ the trait `std::marker::Sized` is not implemented for `str`
+ | ^ `str` does not have a constant size known at compile-time
|
- = note: `str` does not have a constant size known at compile-time
+ = help: the trait `std::marker::Sized` is not implemented for `str`
= note: required for the cast to the object type `Foo`
error: casting `&{float}` as `f32` is invalid
81 | vec![0.0].iter().map(|s| s as f32).collect::<Vec<f32>>();
| ^
-error: aborting due to 34 previous errors
+error: aborting due to previous error(s)
| |
| expected closure that takes 2 arguments
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
= note: required by `baz`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
21 | const fn f() -> u32 { 22 }
| ^^^^^ trait fns cannot be const
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `apply`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `()`
found type `*mut Trait`
-error: aborting due to previous error
+error: aborting due to previous error(s)
38 | cast!(2);
| --------- in this macro invocation
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `bool` (type parameter)
found type `bool` (bool)
-error: aborting due to previous error
+error: aborting due to previous error(s)
| requires `for<'r> std::ops::FnOnce<(&'r &str,)>`
| expected &str, found str
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
34 | fn ugh(&[bar]: &u32) {
| ^^^^^ pattern cannot match with input type `u32`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
= note: expected type `u32`
found type `()`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: the method `unwrap` exists but the following trait bounds were not satisfied:
`Foo : std::fmt::Debug`
-error: aborting due to previous error
+error: aborting due to previous error(s)
45 | let ans = s("burma", "shave");
| ^^^^^^^^^^^^^^^^ expected 1 parameter
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
= note: expected type `std::boxed::Box<Foo + std::marker::Send + 'static>`
found type `std::boxed::Box<Foo + 'static>`
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `fn(&mut Bar, &mut Bar)`
found type `fn(&mut Bar, &Bar)`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `call_it`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
21 | match proto {
| ^^^^^ pattern `C(QA)` not covered
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: `Type` from trait: `type Type;`
= note: `method` from trait: `fn(&Self, std::string::String) -> <Self as m1::X>::Type`
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | foo();
| ^^^ cannot infer type for `X`
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | pub(crate) () fn foo() {}
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | pub(crate) () foo: usize,
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
13 | pub (.) fn afn() {}
| ^
-error: aborting due to previous error
+error: aborting due to previous error(s)
33 | pub (in x) non_parent_invalid: usize,
| ^
-error: aborting due to 5 previous errors
+error: aborting due to previous error(s)
13 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^^
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | let x: [usize; 2] = [22, return];
| ^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
36 | *{return; &mut i} = 22;
| ^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
13 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
28 | bar(return);
| ^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^^
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
31 | Foo.bar(return);
| ^^^^^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
40 | let x = Foo { a: 22, b: return };
| ^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
25 | let x: (usize, usize) = (2, return);
| ^^^^^^^^^^^
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
14 | #![deny(unreachable_code)]
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
18 | let x: ! = ! { return; 22 };
| ^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
= note: lifetime parameter `'b` declared on fn `bar` appears only in the return type, but here is required to be higher-ranked, which means that `'b` must appear in both argument and return types
= note: this error is the result of a recent bug fix; for more information, see issue #33685 <https://github.com/rust-lang/rust/issues/33685>
-error: aborting due to previous error
+error: aborting due to previous error(s)
help: possible candidate is found in another module, you can import it into scope
| use namespaced_enums::Foo::C;
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 25 previous errors
+error: aborting due to previous error(s)
| use std::io::Result;
| use std::thread::Result;
-error: aborting due to previous error
+error: aborting due to previous error(s)
help: possible candidate is found in another module, you can import it into scope
| use SomeEnum::E;
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | let f = Foo::Variant(42);
| ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
22 | let homura = issue_19452_aux::Homura::Madoka;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `issue_19452_aux::Homura::Madoka { /* fields */ }`?
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^^^^^
= note: ...which then again requires processing `<impl at $DIR/issue-23305.rs:15:1: 15:20>`, completing the cycle.
-error: aborting due to previous error
+error: aborting due to previous error(s)
122 | self += 1;
| ^^^^ `self` value is only available in methods with `self` parameter
-error: aborting due to 17 previous errors
+error: aborting due to previous error(s)
11 | fn foo(_: Self) {
| ^^^^ `Self` is only available in traits and impls
-error: aborting due to previous error
+error: aborting due to previous error(s)
20 | let any: &Any = &Bar; //~ ERROR expected value, found trait `Bar`
| ^^^ not a value
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: method `bar` has no receiver
-error: aborting due to previous error
+error: aborting due to previous error(s)
| did you mean `handle`?
| did you mean `Handle { /* fields */ }`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
--> $DIR/issue-5035-2.rs:14:8
|
14 | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
- | ^^ the trait `std::marker::Sized` is not implemented for `I + 'static`
+ | ^^ `I + 'static` does not have a constant size known at compile-time
|
- = note: `I + 'static` does not have a constant size known at compile-time
+ = help: the trait `std::marker::Sized` is not implemented for `I + 'static`
= note: all local variables must have a statically known size
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | let _m = Monster(); //~ ERROR expected function, found struct `Monster`
| ^^^^^^^ did you mean `Monster { /* fields */ }`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
32 | let b: m::first = m::second; // Misspelled item in module.
| ^^^^^^ did you mean `Second`?
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
45 | xcrate::m::n::Z; //~ ERROR tuple struct `Z` is private
| ^^^^^^^^^^^^^^^
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
52 | method;
| ^^^^^^ did you mean `self.method(...)`?
-error: aborting due to 9 previous errors
+error: aborting due to previous error(s)
12 | assert(true);
| ^^^^^^ did you mean `assert!(...)`?
-error: aborting due to previous error
+error: aborting due to previous error(s)
38 | method();
| ^^^^^^ did you mean `self.method(...)`?
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 10 previous errors
+error: aborting due to previous error(s)
14 | if foo {
| ^^^ not found in this scope
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
= note: expected type `()`
found type `std::result::Result<bool, std::io::Error>`
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | foo(bar(;
| ^^^ not found in this scope
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
| did you mean `S`?
| did you mean `A { /* fields */ }`?
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
| did you mean `self.cx`?
| `self` value is only available in methods with `self` parameter
-error: aborting due to previous error
+error: aborting due to previous error(s)
18 | impl Foo for Bar {}
| ^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
-error: aborting due to previous error
+error: aborting due to previous error(s)
15 | let c = f(2, 3); //~ ERROR E0057
| ^^^^ expected 1 parameter
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
-error: aborting due to previous error
+error: aborting due to previous error(s)
31 | Bar(&'a mut bool),
| ------------- this field does not implement `Copy`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
27 | const F : Foo = Foo { a : 0 };
| ^^^^^^^^^^^^^ constants cannot have destructors
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | #[inline(unknown)] //~ ERROR E0535
| ^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | #[cfg(not())] //~ ERROR E0536
| ^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
11 | #[cfg(unknown())] //~ ERROR E0537
| ^^^^^^^
-error: aborting due to previous error
+error: aborting due to previous error(s)
143 | *x.y_mut() = 3; //~ ERROR cannot borrow
| ^ cannot borrow as mutable
-error: aborting due to 10 previous errors
+error: aborting due to previous error(s)
63 | **x = 3; //~ ERROR cannot borrow
| ^^ cannot borrow as mutable
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
72 | foo(f);
| ^ cannot move out of captured outer variable in an `FnMut` closure
-error: aborting due to 5 previous errors
+error: aborting due to previous error(s)
27 | x.h(); //~ ERROR cannot borrow
| ^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | x.push(format!("this is broken"));
| ^ cannot borrow as mutable
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
29 | x.borrowed_mut(); //~ ERROR cannot borrow
| ^ cannot borrow as mutable
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `_`
found type `std::boxed::Box<_>`
-error: aborting due to 5 previous errors
+error: aborting due to previous error(s)
| |
| `*a` dropped here while still borrowed
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
|
= note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
-error: aborting due to 7 previous errors
+error: aborting due to previous error(s)
23 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: consider using a `let` binding to increase its lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
| |
| `y` dropped here while still borrowed
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: `Item` from trait: `type Item;`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `Output` from trait: `type Output;`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: `Target` from trait: `type Target;`
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | #![deny(warnings)]
| ^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `&Self`
found type `&SomeType`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: required by `Tr::C`
-error: aborting due to previous error
+error: aborting due to previous error(s)
found type `std::string::String`
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
19 | bar(1, 2, 3);
| ^^^^^^^ expected 2 parameters
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
| ^^^^^^^^^^^^^^^
= help: to disambiguate the method call, write `F::foo(a)` instead
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: an implementation of `std::ops::Add` might be missing for `World`
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
| | pattern doesn't bind `c`
| pattern doesn't bind `c`
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
= help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `is_str`, perhaps you need to implement it:
= help: candidate #1: `ManyImplTrait`
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
44 | | }
| |_^
-error: aborting due to 8 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to previous error
+error: aborting due to previous error(s)
= note: expected type `()`
found type `[closure@$DIR/move-closure.rs:15:17: 15:27]`
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | | bar(x,
26 | |
27 | | y),
- | |______________^ the trait `std::ops::Add<()>` is not implemented for `u32`
+ | |______________^ no implementation for `u32 + ()`
|
- = note: no implementation for `u32 + ()`
+ = help: the trait `std::ops::Add<()>` is not implemented for `u32`
-error: aborting due to previous error
+error: aborting due to previous error(s)
25 | a.push_str("foo");
| ^ cannot borrow as mutable
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
20 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
17 | pub(crate) bar: u8,
| ^^^^^^^^^^^^^^^^^^ field already declared
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
21 | }
| - borrowed value needs to live until here
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
20 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
23 | }
| - temporary value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
| |
| `tmp0` dropped here while still borrowed
-error: aborting due to previous error
+error: aborting due to previous error(s)
23 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
24 | x += 1; //~ ERROR cannot assign
| ^^^^^^ assignment to borrowed `x` occurs here
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
30 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
35 | }
| - borrowed value needs to live until here
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
44 | }
| - borrowed value needs to live until here
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
49 | drop(y); //~ ERROR cannot move out
| ^ move out of `y` occurs here
-error: aborting due to 6 previous errors
+error: aborting due to previous error(s)
19 | }
| - temporary value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | println!("☃{}", tup[0]);
| ^^^^^^ help: to access tuple elements, use `tup.0`
-error: aborting due to previous error
+error: aborting due to previous error(s)
16 | fn homura<T: Deref<Trget = i32>>(_: T) {}
| ^^^^^^^^^^^ associated type `Trget` not found
-error: aborting due to previous error
+error: aborting due to previous error(s)
18 | println!("Hello {}", fob);
| ^^^ did you mean `foo`?
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
|
= note: values in a scope are dropped in the opposite order they are created
-error: aborting due to 2 previous errors
+error: aborting due to previous error(s)
33 | }
| - borrowed value needs to live until here
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: type must satisfy the static lifetime
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field
-error: aborting due to 11 previous errors
+error: aborting due to previous error(s)
|
= help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
26 | let dog_age = dog.dog_age();
| ^^^^^^^ private field, not a method
-error: aborting due to previous error
+error: aborting due to previous error(s)
| | unexpected token
| help: try parenthesizing the first index `((1, (2, 3)).1).1`
-error: aborting due to previous error
+error: aborting due to previous error(s)
15 | FAIL
| ^^^^ expected one of `!` or `::` here
-error: aborting due to previous error
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 4 previous errors
+error: aborting due to previous error(s)
error: main function not found
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
37 | ignored_pat!() => (), //~ NOTE caused by the macro expansion here
| ^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to previous error(s)
19 | FAIL
| ^^^^ expected one of `!` or `::` here
-error: aborting due to previous error
+error: aborting due to previous error(s)
| |
| consider giving `x` a type
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
|
= note: this error originates in a macro outside of the current crate
-error: aborting due to previous error
+error: aborting due to previous error(s)
14 | [];
| ^^ cannot infer type for `[_; 0]`
-error: aborting due to previous error
+error: aborting due to previous error(s)
21 | | }
| |_^ cannot infer type for `&'a T`
-error: aborting due to previous error
+error: aborting due to previous error(s)
12 | let x = |_| { };
| ^ consider giving this closure parameter a type
-error: aborting due to previous error
+error: aborting due to previous error(s)
println!("expected {}:\n{}\n", kind, expected);
println!("diff of {}:\n", kind);
- for diff in diff::lines(actual, expected) {
+ for diff in diff::lines(expected, actual) {
match diff {
- diff::Result::Left(l) => println!("+{}", l),
+ diff::Result::Left(l) => println!("-{}", l),
diff::Result::Both(l, _) => println!(" {}", l),
- diff::Result::Right(r) => println!("-{}", r),
+ diff::Result::Right(r) => println!("+{}", r),
}
}