- [future_atomic_orderings](future-atomic-orderings.md)
- [generic_param_attrs](generic-param-attrs.md)
- [get_type_id](get-type-id.md)
+- [global_asm](global_asm.md)
- [heap_api](heap-api.md)
- [i128](i128.md)
- [i128_type](i128-type.md)
- [optin_builtin_traits](optin-builtin-traits.md)
- [option_entry](option-entry.md)
- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
+- [overlapping_marker_traits](overlapping-marker-traits.md)
- [panic_abort](panic-abort.md)
- [panic_runtime](panic-runtime.md)
- [panic_unwind](panic-unwind.md)
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
+If you need more power and don't mind losing some of the niceties of
+`asm!`, check out [global_asm](global_asm.html).
--- /dev/null
+# `global_asm`
+
+The tracking issue for this feature is: [#35119]
+
+[#35119]: https://github.com/rust-lang/rust/issues/35119
+
+------------------------
+
+The `global_asm!` macro allows the programmer to write arbitrary
+assembly outside the scope of a function body, passing it through
+`rustc` and `llvm` to the assembler. The macro is a no-frills
+interface to LLVM's concept of [module-level inline assembly]. That is,
+all caveats applicable to LLVM's module-level inline assembly apply
+to `global_asm!`.
+
+[module-level inline assembly]: http://llvm.org/docs/LangRef.html#module-level-inline-assembly
+
+`global_asm!` fills a role not currently satisfied by either `asm!`
+or `#[naked]` functions. The programmer has _all_ features of the
+assembler at their disposal. The linker will expect to resolve any
+symbols defined in the inline assembly, modulo any symbols marked as
+external. It also means syntax for directives and assembly follow the
+conventions of the assembler in your toolchain.
+
+A simple usage looks like this:
+
+```rust,ignore
+# #![feature(global_asm)]
+# you also need relevant target_arch cfgs
+global_asm!(include_str!("something_neato.s"));
+```
+
+And a more complicated usage looks like this:
+
+```rust,ignore
+# #![feature(global_asm)]
+# #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+
+pub mod sally {
+ global_asm!(r#"
+ .global foo
+ foo:
+ jmp baz
+ "#);
+
+ #[no_mangle]
+ pub unsafe extern "C" fn baz() {}
+}
+
+// the symbols `foo` and `bar` are global, no matter where
+// `global_asm!` was used.
+extern "C" {
+ fn foo();
+ fn bar();
+}
+
+pub mod harry {
+ global_asm!(r#"
+ .global bar
+ bar:
+ jmp quux
+ "#);
+
+ #[no_mangle]
+ pub unsafe extern "C" fn quux() {}
+}
+```
+
+You may use `global_asm!` multiple times, anywhere in your crate, in
+whatever way suits you. The effect is as if you concatenated all
+usages and placed the larger, single usage in the crate root.
+
+------------------------
+
+If you don't need quite as much power and flexibility as
+`global_asm!` provides, and you don't mind restricting your inline
+assembly to `fn` bodies only, you might try the [asm](asm.html)
+feature instead.
--- /dev/null
+# `overlapping_marker_traits`
+
+The tracking issue for this feature is: [#29864]
+
+[#29864]: https://github.com/rust-lang/rust/issues/29864
+
+------------------------
//!
//! This is a larger example that implements [Dijkstra's algorithm][dijkstra]
//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
-//! It shows how to use `BinaryHeap` with custom types.
+//! It shows how to use [`BinaryHeap`] with custom types.
//!
//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem
//! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph
+//! [`BinaryHeap`]: struct.BinaryHeap.html
//!
//! ```
//! use std::cmp::Ordering;
data: Vec<T>,
}
-/// A container object that represents the result of the [`peek_mut`] method
-/// on `BinaryHeap`. See its documentation for details.
+/// Structure wrapping a mutable reference to the greatest item on a
+/// `BinaryHeap`.
+///
+/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See
+/// its documentation for more.
///
/// [`peek_mut`]: struct.BinaryHeap.html#method.peek_mut
+/// [`BinaryHeap`]: struct.BinaryHeap.html
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
pub struct PeekMut<'a, T: 'a + Ord> {
heap: &'a mut BinaryHeap<T>,
/// given `BinaryHeap`. Does nothing if the capacity is already sufficient.
///
/// Note that the allocator may give the collection more space than it requests. Therefore
- /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
+ /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future
/// insertions are expected.
///
/// # Panics
/// assert!(heap.capacity() >= 100);
/// heap.push(4);
/// ```
+ ///
+ /// [`reserve`]: #method.reserve
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve_exact(&mut self, additional: usize) {
self.data.reserve_exact(additional);
}
}
-/// `BinaryHeap` iterator.
+/// An iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by the [`iter`] method on [`BinaryHeap`]. See its
+/// documentation for more.
+///
+/// [`iter`]: struct.BinaryHeap.html#method.iter
+/// [`BinaryHeap`]: struct.BinaryHeap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
iter: slice::Iter<'a, T>,
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for Iter<'a, T> {}
-/// An iterator that moves out of a `BinaryHeap`.
+/// An owning iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`BinaryHeap`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
+///
+/// [`into_iter`]: struct.BinaryHeap.html#method.into_iter
+/// [`BinaryHeap`]: struct.BinaryHeap.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct IntoIter<T> {
#[unstable(feature = "fused", issue = "35602")]
impl<T> FusedIterator for IntoIter<T> {}
-/// An iterator that drains a `BinaryHeap`.
+/// A draining iterator over the elements of a `BinaryHeap`.
+///
+/// This `struct` is created by the [`drain`] method on [`BinaryHeap`]. See its
+/// documentation for more.
+///
+/// [`drain`]: struct.BinaryHeap.html#method.drain
+/// [`BinaryHeap`]: struct.BinaryHeap.html
#[stable(feature = "drain", since = "1.6.0")]
#[derive(Debug)]
pub struct Drain<'a, T: 'a> {
}
}
-/// An iterator over a `BTreeMap`'s entries.
+/// An iterator over the entries of a `BTreeMap`.
+///
+/// This `struct` is created by the [`iter`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`iter`]: struct.BTreeMap.html#method.iter
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, K: 'a, V: 'a> {
range: Range<'a, K, V>,
}
}
-/// A mutable iterator over a `BTreeMap`'s entries.
+/// A mutable iterator over the entries of a `BTreeMap`.
+///
+/// This `struct` is created by the [`iter_mut`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`iter_mut`]: struct.BTreeMap.html#method.iter_mut
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IterMut<'a, K: 'a, V: 'a> {
length: usize,
}
-/// An owning iterator over a `BTreeMap`'s entries.
+/// An owning iterator over the entries of a `BTreeMap`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`BTreeMap`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
+///
+/// [`into_iter`]: struct.BTreeMap.html#method.into_iter
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<K, V> {
front: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>,
}
}
-/// An iterator over a `BTreeMap`'s keys.
+/// An iterator over the keys of a `BTreeMap`.
+///
+/// This `struct` is created by the [`keys`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`keys`]: struct.BTreeMap.html#method.keys
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
}
-/// An iterator over a `BTreeMap`'s values.
+/// An iterator over the values of a `BTreeMap`.
+///
+/// This `struct` is created by the [`values`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`values`]: struct.BTreeMap.html#method.values
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Values<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
}
-/// A mutable iterator over a `BTreeMap`'s values.
+/// A mutable iterator over the values of a `BTreeMap`.
+///
+/// This `struct` is created by the [`values_mut`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`values_mut`]: struct.BTreeMap.html#method.values_mut
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "map_values_mut", since = "1.10.0")]
#[derive(Debug)]
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}
-/// An iterator over a sub-range of `BTreeMap`'s entries.
+/// An iterator over a sub-range of entries in a `BTreeMap`.
+///
+/// This `struct` is created by the [`range`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`range`]: struct.BTreeMap.html#method.range
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "btree_range", since = "1.17.0")]
pub struct Range<'a, K: 'a, V: 'a> {
front: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>,
}
}
-/// A mutable iterator over a sub-range of `BTreeMap`'s entries.
+/// A mutable iterator over a sub-range of entries in a `BTreeMap`.
+///
+/// This `struct` is created by the [`range_mut`] method on [`BTreeMap`]. See its
+/// documentation for more.
+///
+/// [`range_mut`]: struct.BTreeMap.html#method.range_mut
+/// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "btree_range", since = "1.17.0")]
pub struct RangeMut<'a, K: 'a, V: 'a> {
front: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>,
}
/// A view into a single entry in a map, which may either be vacant or occupied.
-/// This enum is constructed from the [`entry`] method on [`BTreeMap`].
+///
+/// This `enum` is constructed from the [`entry`] method on [`BTreeMap`].
///
/// [`BTreeMap`]: struct.BTreeMap.html
/// [`entry`]: struct.BTreeMap.html#method.entry
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Entry<'a, K: 'a, V: 'a> {
- /// A vacant `Entry`
+ /// A vacant entry.
#[stable(feature = "rust1", since = "1.0.0")]
Vacant(#[stable(feature = "rust1", since = "1.0.0")]
VacantEntry<'a, K, V>),
- /// An occupied `Entry`
+ /// An occupied entry.
#[stable(feature = "rust1", since = "1.0.0")]
Occupied(#[stable(feature = "rust1", since = "1.0.0")]
OccupiedEntry<'a, K, V>),
}
}
-/// A vacant `Entry`. It is part of the [`Entry`] enum.
+/// A view into a vacant entry in a `BTreeMap`.
+/// It is part of the [`Entry`] enum.
///
/// [`Entry`]: enum.Entry.html
#[stable(feature = "rust1", since = "1.0.0")]
}
}
-/// An occupied `Entry`. It is part of the [`Entry`] enum.
+/// A view into an occupied entry in a `BTreeMap`.
+/// It is part of the [`Entry`] enum.
///
/// [`Entry`]: enum.Entry.html
#[stable(feature = "rust1", since = "1.0.0")]
map: BTreeMap<T, ()>,
}
-/// An iterator over a `BTreeSet`'s items.
+/// An iterator over the items of a `BTreeSet`.
///
-/// This structure is created by the [`iter`] method on [`BTreeSet`].
+/// This `struct` is created by the [`iter`] method on [`BTreeSet`].
+/// See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`iter`]: struct.BTreeSet.html#method.iter
}
}
-/// An owning iterator over a `BTreeSet`'s items.
+/// An owning iterator over the items of a `BTreeSet`.
///
-/// This structure is created by the `into_iter` method on [`BTreeSet`]
-/// [`BTreeSet`] (provided by the `IntoIterator` trait).
+/// This `struct` is created by the [`into_iter`] method on [`BTreeSet`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
+/// [`into_iter`]: struct.BTreeSet.html#method.into_iter
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IntoIter<T> {
iter: ::btree_map::IntoIter<T, ()>,
}
-/// An iterator over a sub-range of `BTreeSet`'s items.
+/// An iterator over a sub-range of items in a `BTreeSet`.
///
-/// This structure is created by the [`range`] method on [`BTreeSet`].
+/// This `struct` is created by the [`range`] method on [`BTreeSet`].
+/// See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`range`]: struct.BTreeSet.html#method.range
iter: ::btree_map::Range<'a, T, ()>,
}
-/// A lazy iterator producing elements in the set difference (in-order).
+/// A lazy iterator producing elements in the difference of `BTreeSet`s.
///
-/// This structure is created by the [`difference`] method on [`BTreeSet`].
+/// This `struct` is created by the [`difference`] method on [`BTreeSet`].
+/// See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`difference`]: struct.BTreeSet.html#method.difference
}
}
-/// A lazy iterator producing elements in the set symmetric difference (in-order).
+/// A lazy iterator producing elements in the symmetric difference of `BTreeSet`s.
///
-/// This structure is created by the [`symmetric_difference`] method on
-/// [`BTreeSet`].
+/// This `struct` is created by the [`symmetric_difference`] method on
+/// [`BTreeSet`]. See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference
}
}
-/// A lazy iterator producing elements in the set intersection (in-order).
+/// A lazy iterator producing elements in the intersection of `BTreeSet`s.
///
-/// This structure is created by the [`intersection`] method on [`BTreeSet`].
+/// This `struct` is created by the [`intersection`] method on [`BTreeSet`].
+/// See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`intersection`]: struct.BTreeSet.html#method.intersection
}
}
-/// A lazy iterator producing elements in the set union (in-order).
+/// A lazy iterator producing elements in the union of `BTreeSet`s.
///
-/// This structure is created by the [`union`] method on [`BTreeSet`].
+/// This `struct` is created by the [`union`] method on [`BTreeSet`].
+/// See its documentation for more.
///
/// [`BTreeSet`]: struct.BTreeSet.html
/// [`union`]: struct.BTreeSet.html#method.union
type Item = T;
type IntoIter = IntoIter<T>;
- /// Gets an iterator for moving out the BtreeSet's contents.
+ /// Gets an iterator for moving out the `BTreeSet`'s contents.
///
/// # Examples
///
}
/// An endpoint of a range of keys.
+///
+/// # Examples
+///
+/// `Bound`s are range endpoints:
+///
+/// ```
+/// #![feature(collections_range)]
+///
+/// use std::collections::range::RangeArgument;
+/// use std::collections::Bound::*;
+///
+/// assert_eq!((..100).start(), Unbounded);
+/// assert_eq!((1..12).start(), Included(&1));
+/// assert_eq!((1..12).end(), Excluded(&12));
+/// ```
+///
+/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
+/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
+///
+/// ```
+/// use std::collections::BTreeMap;
+/// use std::collections::Bound::{Excluded, Included, Unbounded};
+///
+/// let mut map = BTreeMap::new();
+/// map.insert(3, "a");
+/// map.insert(5, "b");
+/// map.insert(8, "c");
+///
+/// for (key, value) in map.range((Excluded(3), Included(8))) {
+/// println!("{}: {}", key, value);
+/// }
+///
+/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
+/// ```
+///
+/// [`BTreeMap::range`]: btree_map/struct.BTreeMap.html#method.range
#[stable(feature = "collections_bound", since = "1.17.0")]
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Bound<T> {
element: T,
}
-/// An iterator over references to the elements of a `LinkedList`.
+/// An iterator over the elements of a `LinkedList`.
+///
+/// This `struct` is created by the [`iter`] method on [`LinkedList`]. See its
+/// documentation for more.
+///
+/// [`iter`]: struct.LinkedList.html#method.iter
+/// [`LinkedList`]: struct.LinkedList.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
head: Option<Shared<Node<T>>>,
}
}
-/// An iterator over mutable references to the elements of a `LinkedList`.
+/// A mutable iterator over the elements of a `LinkedList`.
+///
+/// This `struct` is created by the [`iter_mut`] method on [`LinkedList`]. See its
+/// documentation for more.
+///
+/// [`iter_mut`]: struct.LinkedList.html#method.iter_mut
+/// [`LinkedList`]: struct.LinkedList.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
list: &'a mut LinkedList<T>,
}
}
-/// An iterator over the elements of a `LinkedList`.
+/// An owning iterator over the elements of a `LinkedList`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`LinkedList`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
+///
+/// [`into_iter`]: struct.LinkedList.html#method.into_iter
+/// [`LinkedList`]: struct.LinkedList.html
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
/// Splits the list into two at the given index. Returns everything after the given index,
/// including the index.
///
+ /// This operation should compute in O(n) time.
+ ///
/// # Panics
///
/// Panics if `at > len`.
///
- /// This operation should compute in O(n) time.
- ///
/// # Examples
///
/// ```
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! `VecDeque` is a double-ended queue, which is implemented with the help of a
-//! growing ring buffer.
+//! A double-ended queue implemented with a growable ring buffer.
//!
//! This queue has `O(1)` amortized inserts and removals from both ends of the
//! container. It also has `O(1)` indexing like a vector. The contained elements
#[cfg(target_pointer_width = "64")]
const MAXIMUM_ZST_CAPACITY: usize = 1 << (64 - 1); // Largest possible power of two
-/// `VecDeque` is a growable ring buffer, which can be used as a double-ended
-/// queue efficiently.
+/// A double-ended queue implemented with a growable ring buffer.
///
-/// The "default" usage of this type as a queue is to use `push_back` to add to
-/// the queue, and `pop_front` to remove from the queue. `extend` and `append`
+/// The "default" usage of this type as a queue is to use [`push_back`] to add to
+/// the queue, and [`pop_front`] to remove from the queue. [`extend`] and [`append`]
/// push onto the back in this manner, and iterating over `VecDeque` goes front
/// to back.
+///
+/// [`push_back`]: #method.push_back
+/// [`pop_front`]: #method.pop_front
+/// [`extend`]: #method.extend
+/// [`append`]: #method.append
#[stable(feature = "rust1", since = "1.0.0")]
pub struct VecDeque<T> {
// tail and head are pointers into the buffer. Tail always points
/// given `VecDeque`. Does nothing if the capacity is already sufficient.
///
/// Note that the allocator may give the collection more space than it requests. Therefore
- /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
+ /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future
/// insertions are expected.
///
/// # Panics
/// buf.reserve_exact(10);
/// assert!(buf.capacity() >= 11);
/// ```
+ ///
+ /// [`reserve`]: #method.reserve
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve_exact(&mut self, additional: usize) {
self.reserve(additional);
(head.wrapping_sub(tail)) & (size - 1)
}
-/// `VecDeque` iterator.
+/// An iterator over the elements of a `VecDeque`.
+///
+/// This `struct` is created by the [`iter`] method on [`VecDeque`]. See its
+/// documentation for more.
+///
+/// [`iter`]: struct.VecDeque.html#method.iter
+/// [`VecDeque`]: struct.VecDeque.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, T: 'a> {
ring: &'a [T],
impl<'a, T> FusedIterator for Iter<'a, T> {}
-/// `VecDeque` mutable iterator.
+/// A mutable iterator over the elements of a `VecDeque`.
+///
+/// This `struct` is created by the [`iter_mut`] method on [`VecDeque`]. See its
+/// documentation for more.
+///
+/// [`iter_mut`]: struct.VecDeque.html#method.iter_mut
+/// [`VecDeque`]: struct.VecDeque.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, T: 'a> {
ring: &'a mut [T],
#[unstable(feature = "fused", issue = "35602")]
impl<'a, T> FusedIterator for IterMut<'a, T> {}
-/// A by-value `VecDeque` iterator
+/// An owning iterator over the elements of a `VecDeque`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`VecDeque`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
+///
+/// [`into_iter`]: struct.VecDeque.html#method.into_iter
+/// [`VecDeque`]: struct.VecDeque.html
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
#[unstable(feature = "fused", issue = "35602")]
impl<T> FusedIterator for IntoIter<T> {}
-/// A draining `VecDeque` iterator
+/// A draining iterator over the elements of a `VecDeque`.
+///
+/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its
+/// documentation for more.
+///
+/// [`drain`]: struct.VecDeque.html#method.drain
+/// [`VecDeque`]: struct.VecDeque.html
#[stable(feature = "drain", since = "1.6.0")]
pub struct Drain<'a, T: 'a> {
after_tail: usize,
/// A hashable type.
///
-/// The `H` type parameter is an abstract hash state that is used by the `Hash`
-/// to compute the hash.
+/// Types implementing `Hash` are able to be [`hash`]ed with an instance of
+/// [`Hasher`].
///
-/// If you are also implementing [`Eq`], there is an additional property that
-/// is important:
+/// ## Implementing `Hash`
///
-/// ```text
-/// k1 == k2 -> hash(k1) == hash(k2)
-/// ```
-///
-/// In other words, if two keys are equal, their hashes should also be equal.
-/// [`HashMap`] and [`HashSet`] both rely on this behavior.
+/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`.
+/// The resulting hash will be the combination of the values from calling
+/// [`hash`] on each field.
///
-/// ## Derivable
-///
-/// This trait can be used with `#[derive]` if all fields implement `Hash`.
-/// When `derive`d, the resulting hash will be the combination of the values
-/// from calling [`.hash`] on each field.
-///
-/// ## How can I implement `Hash`?
+/// ```
+/// #[derive(Hash)]
+/// struct Rustacean {
+/// name: String,
+/// country: String,
+/// }
+/// ```
///
-/// If you need more control over how a value is hashed, you need to implement
-/// the `Hash` trait:
+/// If you need more control over how a value is hashed, you can of course
+/// implement the `Hash` trait yourself:
///
/// ```
/// use std::hash::{Hash, Hasher};
/// }
/// ```
///
+/// ## `Hash` and `Eq`
+///
+/// When implementing both `Hash` and [`Eq`], it is important that the following
+/// property holds:
+///
+/// ```text
+/// k1 == k2 -> hash(k1) == hash(k2)
+/// ```
+///
+/// In other words, if two keys are equal, their hashes must also be equal.
+/// [`HashMap`] and [`HashSet`] both rely on this behavior.
+///
+/// Thankfully, you won't need to worry about upholding this property when
+/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`.
+///
/// [`Eq`]: ../../std/cmp/trait.Eq.html
+/// [`Hasher`]: trait.Hasher.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
-/// [`.hash`]: #tymethod.hash
+/// [`hash`]: #tymethod.hash
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash {
- /// Feeds this value into the state given, updating the hasher as necessary.
+ /// Feeds this value into the given [`Hasher`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::hash_map::DefaultHasher;
+ /// use std::hash::{Hash, Hasher};
+ ///
+ /// let mut hasher = DefaultHasher::new();
+ /// 7920.hash(&mut hasher);
+ /// println!("Hash is {:x}!", hasher.finish());
+ /// ```
+ ///
+ /// [`Hasher`]: trait.Hasher.html
#[stable(feature = "rust1", since = "1.0.0")]
fn hash<H: Hasher>(&self, state: &mut H);
- /// Feeds a slice of this type into the state provided.
+ /// Feeds a slice of this type into the given [`Hasher`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::hash_map::DefaultHasher;
+ /// use std::hash::{Hash, Hasher};
+ ///
+ /// let mut hasher = DefaultHasher::new();
+ /// let numbers = [6, 28, 496, 8128];
+ /// Hash::hash_slice(&numbers, &mut hasher);
+ /// println!("Hash is {:x}!", hasher.finish());
+ /// ```
+ ///
+ /// [`Hasher`]: trait.Hasher.html
#[stable(feature = "hash_slice", since = "1.3.0")]
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
where Self: Sized
}
}
-/// A trait which represents the ability to hash an arbitrary stream of bytes.
+/// A trait for hashing an arbitrary stream of bytes.
+///
+/// Instances of `Hasher` usually represent state that is changed while hashing
+/// data.
+///
+/// `Hasher` provides a fairly basic interface for retrieving the generated hash
+/// (with [`finish`]), and writing integers as well as slices of bytes into an
+/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher`
+/// instances are used in conjunction with the [`Hash`] trait.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::hash_map::DefaultHasher;
+/// use std::hash::Hasher;
+///
+/// let mut hasher = DefaultHasher::new();
+///
+/// hasher.write_u32(1989);
+/// hasher.write_u8(11);
+/// hasher.write_u8(9);
+/// hasher.write(b"Huh?");
+///
+/// println!("Hash is {:x}!", hasher.finish());
+/// ```
+///
+/// [`Hash`]: trait.Hash.html
+/// [`finish`]: #tymethod.finish
+/// [`write`]: #tymethod.write
+/// [`write_u8`]: #method.write_u8
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Hasher {
/// Completes a round of hashing, producing the output hash generated.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::hash_map::DefaultHasher;
+ /// use std::hash::Hasher;
+ ///
+ /// let mut hasher = DefaultHasher::new();
+ /// hasher.write(b"Cool!");
+ ///
+ /// println!("Hash is {:x}!", hasher.finish());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn finish(&self) -> u64;
/// Writes some data into this `Hasher`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::hash_map::DefaultHasher;
+ /// use std::hash::Hasher;
+ ///
+ /// let mut hasher = DefaultHasher::new();
+ /// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
+ ///
+ /// hasher.write(&data);
+ ///
+ /// println!("Hash is {:x}!", hasher.finish());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, bytes: &[u8]);
- /// Write a single `u8` into this hasher.
+ /// Writes a single `u8` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u8(&mut self, i: u8) {
}
}
-/// A `BuildHasher` is typically used as a factory for instances of `Hasher`
-/// which a `HashMap` can then use to hash keys independently.
+/// A trait for creating instances of [`Hasher`].
+///
+/// A `BuildHasher` is typically used (e.g. by [`HashMap`]) to create
+/// [`Hasher`]s for each key such that they are hashed independently of one
+/// another, since [`Hasher`]s contain state.
+///
+/// For each instance of `BuildHasher`, the [`Hasher`]s created by
+/// [`build_hasher`] should be identical. That is, if the same stream of bytes
+/// is fed into each hasher, the same output will also be generated.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::hash_map::RandomState;
+/// use std::hash::{BuildHasher, Hasher};
+///
+/// let s = RandomState::new();
+/// let mut hasher_1 = s.build_hasher();
+/// let mut hasher_2 = s.build_hasher();
///
-/// Note that for each instance of `BuildHasher`, the created hashers should be
-/// identical. That is, if the same stream of bytes is fed into each hasher, the
-/// same output will also be generated.
+/// hasher_1.write_u32(8128);
+/// hasher_2.write_u32(8128);
+///
+/// assert_eq!(hasher_1.finish(), hasher_2.finish());
+/// ```
+///
+/// [`build_hasher`]: #tymethod.build_hasher
+/// [`Hasher`]: trait.Hasher.html
+/// [`HashMap`]: ../../std/collections/struct.HashMap.html
#[stable(since = "1.7.0", feature = "build_hasher")]
pub trait BuildHasher {
/// Type of the hasher that will be created.
/// Creates a new hasher.
///
+ /// Each call to `build_hasher` on the same instance should produce identical
+ /// [`Hasher`]s.
+ ///
/// # Examples
///
/// ```
/// let s = RandomState::new();
/// let new_s = s.build_hasher();
/// ```
+ ///
+ /// [`Hasher`]: trait.Hasher.html
#[stable(since = "1.7.0", feature = "build_hasher")]
fn build_hasher(&self) -> Self::Hasher;
}
-/// The `BuildHasherDefault` structure is used in scenarios where one has a
-/// type that implements [`Hasher`] and [`Default`], but needs that type to
-/// implement [`BuildHasher`].
+/// Used to create a default [`BuildHasher`] instance for types that implement
+/// [`Hasher`] and [`Default`].
///
-/// This structure is zero-sized and does not need construction.
+/// `BuildHasherDefault<H>` can be used when a type `H` implements [`Hasher`] and
+/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is
+/// defined.
+///
+/// Any `BuildHasherDefault` is [zero-sized]. It can be created with
+/// [`default`][method.Default]. When using `BuildHasherDefault` with [`HashMap`] or
+/// [`HashSet`], this doesn't need to be done, since they implement appropriate
+/// [`Default`] instances themselves.
///
/// # Examples
///
///
/// [`BuildHasher`]: trait.BuildHasher.html
/// [`Default`]: ../default/trait.Default.html
+/// [method.default]: #method.default
/// [`Hasher`]: trait.Hasher.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
+/// [`HashSet`]: ../../std/collections/struct.HashSet.html
+/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts
#[stable(since = "1.7.0", feature = "build_hasher")]
pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
#![feature(allow_internal_unstable)]
#![feature(asm)]
#![feature(associated_type_defaults)]
+#![feature(associated_consts)]
#![feature(cfg_target_feature)]
#![feature(cfg_target_has_atomic)]
#![feature(concat_idents)]
/// a bignum.
pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Option<T> {
let num_digits = integral.len() + fractional.len();
- // log_10(f64::max_sig) ~ 15.95. We compare the exact value to max_sig near the end,
+ // log_10(f64::MAX_SIG) ~ 15.95. We compare the exact value to MAX_SIG near the end,
// this is just a quick, cheap rejection (and also frees the rest of the code from
// worrying about underflow).
if num_digits > 16 {
return None;
}
- if e.abs() >= T::ceil_log5_of_max_sig() as i64 {
+ if e.abs() >= T::CEIL_LOG5_OF_MAX_SIG as i64 {
return None;
}
let f = num::from_str_unchecked(integral.iter().chain(fractional.iter()));
- if f > T::max_sig() {
+ if f > T::MAX_SIG {
return None;
}
/// > the best possible approximation that uses p bits of significand.)
pub fn bellerophon<T: RawFloat>(f: &Big, e: i16) -> T {
let slop;
- if f <= &Big::from_u64(T::max_sig()) {
+ if f <= &Big::from_u64(T::MAX_SIG) {
// The cases abs(e) < log5(2^N) are in fast_path()
slop = if e >= 0 { 0 } else { 3 };
} else {
slop = if e >= 0 { 1 } else { 4 };
}
let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize();
- let exp_p_n = 1 << (P - T::sig_bits() as u32);
+ let exp_p_n = 1 << (P - T::SIG_BITS as u32);
let lowbits: i64 = (z.f % exp_p_n) as i64;
// Is the slop large enough to make a difference when
// rounding to n bits?
if d2 < y {
let mut d2_double = d2;
d2_double.mul_pow2(1);
- if m == T::min_sig() && d_negative && d2_double > y {
+ if m == T::MIN_SIG && d_negative && d2_double > y {
z = prev_float(z);
} else {
return z;
}
} else if d2 == y {
if m % 2 == 0 {
- if m == T::min_sig() && d_negative {
+ if m == T::MIN_SIG && d_negative {
z = prev_float(z);
} else {
return z;
quick_start::<T>(&mut u, &mut v, &mut k);
let mut rem = Big::from_small(0);
let mut x = Big::from_small(0);
- let min_sig = Big::from_u64(T::min_sig());
- let max_sig = Big::from_u64(T::max_sig());
+ let min_sig = Big::from_u64(T::MIN_SIG);
+ let max_sig = Big::from_u64(T::MAX_SIG);
loop {
u.div_rem(&v, &mut x, &mut rem);
- if k == T::min_exp_int() {
- // We have to stop at the minimum exponent, if we wait until `k < T::min_exp_int()`,
+ if k == T::MIN_EXP_INT {
+ // We have to stop at the minimum exponent, if we wait until `k < T::MIN_EXP_INT`,
// then we'd be off by a factor of two. Unfortunately this means we have to special-
// case normal numbers with the minimum exponent.
// FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure
}
return underflow(x, v, rem);
}
- if k > T::max_exp_int() {
- return T::infinity2();
+ if k > T::MAX_EXP_INT {
+ return T::INFINITY;
}
if x < min_sig {
u.mul_pow2(1);
// The target ratio is one where u/v is in an in-range significand. Thus our termination
// condition is log2(u / v) being the significand bits, plus/minus one.
// FIXME Looking at the second bit could improve the estimate and avoid some more divisions.
- let target_ratio = T::sig_bits() as i16;
+ let target_ratio = T::SIG_BITS as i16;
let log2_u = u.bit_length() as i16;
let log2_v = v.bit_length() as i16;
let mut u_shift: i16 = 0;
let mut v_shift: i16 = 0;
assert!(*k == 0);
loop {
- if *k == T::min_exp_int() {
+ if *k == T::MIN_EXP_INT {
// Underflow or subnormal. Leave it to the main function.
break;
}
- if *k == T::max_exp_int() {
+ if *k == T::MAX_EXP_INT {
// Overflow. Leave it to the main function.
break;
}
}
fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
- if x < Big::from_u64(T::min_sig()) {
+ if x < Big::from_u64(T::MIN_SIG) {
let q = num::to_u64(&x);
let z = rawfp::encode_subnormal(q);
return round_by_remainder(v, rem, q, z);
// needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
// is zero, we have a half-to-even situation.
let bits = x.bit_length();
- let lsb = bits - T::sig_bits() as usize;
+ let lsb = bits - T::SIG_BITS as usize;
let q = num::get_bits(&x, lsb, bits);
- let k = T::min_exp_int() + lsb as i16;
+ let k = T::MIN_EXP_INT + lsb as i16;
let z = rawfp::encode_normal(Unpacked::new(q, k));
let q_even = q % 2 == 0;
match num::compare_with_half_ulp(&x, lsb) {
let (sign, s) = extract_sign(s);
let flt = match parse_decimal(s) {
ParseResult::Valid(decimal) => convert(decimal)?,
- ParseResult::ShortcutToInf => T::infinity2(),
- ParseResult::ShortcutToZero => T::zero2(),
+ ParseResult::ShortcutToInf => T::INFINITY,
+ ParseResult::ShortcutToZero => T::ZERO,
ParseResult::Invalid => match s {
- "inf" => T::infinity2(),
- "NaN" => T::nan2(),
+ "inf" => T::INFINITY,
+ "NaN" => T::NAN,
_ => { return Err(pfe_invalid()); }
}
};
// FIXME These bounds are rather conservative. A more careful analysis of the failure modes
// of Bellerophon could allow using it in more cases for a massive speed up.
let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
- let value_in_range = upper_bound <= T::max_normal_digits() as u64;
+ let value_in_range = upper_bound <= T::MAX_NORMAL_DIGITS as u64;
if exponent_in_range && value_in_range {
Ok(algorithm::bellerophon(&f, e))
} else {
fn trivial_cases<T: RawFloat>(decimal: &Decimal) -> Option<T> {
// There were zeros but they were stripped by simplify()
if decimal.integral.is_empty() && decimal.fractional.is_empty() {
- return Some(T::zero2());
+ return Some(T::ZERO);
}
// This is a crude approximation of ceil(log10(the real value)). We don't need to worry too
// much about overflow here because the input length is tiny (at least compared to 2^64) and
// the parser already handles exponents whose absolute value is greater than 10^18
// (which is still 10^19 short of 2^64).
let max_place = decimal.exp + decimal.integral.len() as i64;
- if max_place > T::inf_cutoff() {
- return Some(T::infinity2());
- } else if max_place < T::zero_cutoff() {
- return Some(T::zero2());
+ if max_place > T::INF_CUTOFF {
+ return Some(T::INFINITY);
+ } else if max_place < T::ZERO_CUTOFF {
+ return Some(T::ZERO);
}
None
}
///
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
/// Inherits from `Float` because there is some overlap, but all the reused methods are trivial.
-/// The "methods" (pseudo-constants) with default implementation should not be overriden.
pub trait RawFloat : Float + Copy + Debug + LowerExp
+ Mul<Output=Self> + Div<Output=Self> + Neg<Output=Self>
{
- // suffix of "2" because Float::infinity is deprecated
- #[allow(deprecated)]
- fn infinity2() -> Self {
- Float::infinity()
- }
-
- // suffix of "2" because Float::nan is deprecated
- #[allow(deprecated)]
- fn nan2() -> Self {
- Float::nan()
- }
-
- // suffix of "2" because Float::zero is deprecated
- fn zero2() -> Self;
+ const INFINITY: Self;
+ const NAN: Self;
+ const ZERO: Self;
// suffix of "2" because Float::integer_decode is deprecated
#[allow(deprecated)]
/// represented, the other code in this module makes sure to never let that happen.
fn from_int(x: u64) -> Self;
- /// Get the value 10<sup>e</sup> from a pre-computed table. Panics for e >=
- /// ceil_log5_of_max_sig().
+ /// Get the value 10<sup>e</sup> from a pre-computed table.
+ /// Panics for `e >= CEIL_LOG5_OF_MAX_SIG`.
fn short_fast_pow10(e: usize) -> Self;
- // FIXME Everything that follows should be associated constants, but taking the value of an
- // associated constant from a type parameter does not work (yet?)
- // A possible workaround is having a `FloatInfo` struct for all the constants, but so far
- // the methods aren't painful enough to rewrite.
-
/// What the name says. It's easier to hard code than juggling intrinsics and
/// hoping LLVM constant folds it.
- fn ceil_log5_of_max_sig() -> i16;
+ const CEIL_LOG5_OF_MAX_SIG: i16;
// A conservative bound on the decimal digits of inputs that can't produce overflow or zero or
/// subnormals. Probably the decimal exponent of the maximum normal value, hence the name.
- fn max_normal_digits() -> usize;
+ const MAX_NORMAL_DIGITS: usize;
/// When the most significant decimal digit has a place value greater than this, the number
/// is certainly rounded to infinity.
- fn inf_cutoff() -> i64;
+ const INF_CUTOFF: i64;
/// When the most significant decimal digit has a place value less than this, the number
/// is certainly rounded to zero.
- fn zero_cutoff() -> i64;
+ const ZERO_CUTOFF: i64;
/// The number of bits in the exponent.
- fn exp_bits() -> u8;
+ const EXP_BITS: u8;
/// The number of bits in the singificand, *including* the hidden bit.
- fn sig_bits() -> u8;
+ const SIG_BITS: u8;
/// The number of bits in the singificand, *excluding* the hidden bit.
- fn explicit_sig_bits() -> u8 {
- Self::sig_bits() - 1
- }
+ const EXPLICIT_SIG_BITS: u8;
/// The maximum legal exponent in fractional representation.
- fn max_exp() -> i16 {
- (1 << (Self::exp_bits() - 1)) - 1
- }
+ const MAX_EXP: i16;
/// The minimum legal exponent in fractional representation, excluding subnormals.
- fn min_exp() -> i16 {
- -Self::max_exp() + 1
- }
+ const MIN_EXP: i16;
/// `MAX_EXP` for integral representation, i.e., with the shift applied.
- fn max_exp_int() -> i16 {
- Self::max_exp() - (Self::sig_bits() as i16 - 1)
- }
+ const MAX_EXP_INT: i16;
/// `MAX_EXP` encoded (i.e., with offset bias)
- fn max_encoded_exp() -> i16 {
- (1 << Self::exp_bits()) - 1
- }
+ const MAX_ENCODED_EXP: i16;
/// `MIN_EXP` for integral representation, i.e., with the shift applied.
- fn min_exp_int() -> i16 {
- Self::min_exp() - (Self::sig_bits() as i16 - 1)
- }
+ const MIN_EXP_INT: i16;
/// The maximum normalized singificand in integral representation.
- fn max_sig() -> u64 {
- (1 << Self::sig_bits()) - 1
- }
+ const MAX_SIG: u64;
/// The minimal normalized significand in integral representation.
- fn min_sig() -> u64 {
- 1 << (Self::sig_bits() - 1)
- }
+ const MIN_SIG: u64;
}
-impl RawFloat for f32 {
- fn zero2() -> Self {
- 0.0
- }
-
- fn sig_bits() -> u8 {
- 24
- }
-
- fn exp_bits() -> u8 {
- 8
+// Mostly a workaround for #34344.
+macro_rules! other_constants {
+ ($type: ident) => {
+ const EXPLICIT_SIG_BITS: u8 = Self::SIG_BITS - 1;
+ const MAX_EXP: i16 = (1 << (Self::EXP_BITS - 1)) - 1;
+ const MIN_EXP: i16 = -Self::MAX_EXP + 1;
+ const MAX_EXP_INT: i16 = Self::MAX_EXP - (Self::SIG_BITS as i16 - 1);
+ const MAX_ENCODED_EXP: i16 = (1 << Self::EXP_BITS) - 1;
+ const MIN_EXP_INT: i16 = Self::MIN_EXP - (Self::SIG_BITS as i16 - 1);
+ const MAX_SIG: u64 = (1 << Self::SIG_BITS) - 1;
+ const MIN_SIG: u64 = 1 << (Self::SIG_BITS - 1);
+
+ const INFINITY: Self = $crate::$type::INFINITY;
+ const NAN: Self = $crate::$type::NAN;
+ const ZERO: Self = 0.0;
}
+}
- fn ceil_log5_of_max_sig() -> i16 {
- 11
- }
+impl RawFloat for f32 {
+ const SIG_BITS: u8 = 24;
+ const EXP_BITS: u8 = 8;
+ const CEIL_LOG5_OF_MAX_SIG: i16 = 11;
+ const MAX_NORMAL_DIGITS: usize = 35;
+ const INF_CUTOFF: i64 = 40;
+ const ZERO_CUTOFF: i64 = -48;
+ other_constants!(f32);
fn transmute(self) -> u64 {
let bits: u32 = unsafe { transmute(self) };
fn short_fast_pow10(e: usize) -> Self {
table::F32_SHORT_POWERS[e]
}
-
- fn max_normal_digits() -> usize {
- 35
- }
-
- fn inf_cutoff() -> i64 {
- 40
- }
-
- fn zero_cutoff() -> i64 {
- -48
- }
}
impl RawFloat for f64 {
- fn zero2() -> Self {
- 0.0
- }
-
- fn sig_bits() -> u8 {
- 53
- }
-
- fn exp_bits() -> u8 {
- 11
- }
-
- fn ceil_log5_of_max_sig() -> i16 {
- 23
- }
+ const SIG_BITS: u8 = 53;
+ const EXP_BITS: u8 = 11;
+ const CEIL_LOG5_OF_MAX_SIG: i16 = 23;
+ const MAX_NORMAL_DIGITS: usize = 305;
+ const INF_CUTOFF: i64 = 310;
+ const ZERO_CUTOFF: i64 = -326;
+ other_constants!(f64);
fn transmute(self) -> u64 {
let bits: u64 = unsafe { transmute(self) };
fn short_fast_pow10(e: usize) -> Self {
table::F64_SHORT_POWERS[e]
}
-
- fn max_normal_digits() -> usize {
- 305
- }
-
- fn inf_cutoff() -> i64 {
- 310
- }
-
- fn zero_cutoff() -> i64 {
- -326
- }
-
}
-/// Convert an Fp to the closest f64. Only handles number that fit into a normalized f64.
+/// Convert an Fp to the closest machine float type.
+/// Does not handle subnormal results.
pub fn fp_to_float<T: RawFloat>(x: Fp) -> T {
let x = x.normalize();
// x.f is 64 bit, so x.e has a mantissa shift of 63
let e = x.e + 63;
- if e > T::max_exp() {
+ if e > T::MAX_EXP {
panic!("fp_to_float: exponent {} too large", e)
- } else if e > T::min_exp() {
+ } else if e > T::MIN_EXP {
encode_normal(round_normal::<T>(x))
} else {
panic!("fp_to_float: exponent {} too small", e)
}
}
-/// Round the 64-bit significand to 53 bit with half-to-even. Does not handle exponent overflow.
+/// Round the 64-bit significand to T::SIG_BITS bits with half-to-even.
+/// Does not handle exponent overflow.
pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
- let excess = 64 - T::sig_bits() as i16;
+ let excess = 64 - T::SIG_BITS as i16;
let half: u64 = 1 << (excess - 1);
let (q, rem) = (x.f >> excess, x.f & ((1 << excess) - 1));
assert_eq!(q << excess | rem, x.f);
Unpacked::new(q, k)
} else if rem == half && (q % 2) == 0 {
Unpacked::new(q, k)
- } else if q == T::max_sig() {
- Unpacked::new(T::min_sig(), k + 1)
+ } else if q == T::MAX_SIG {
+ Unpacked::new(T::MIN_SIG, k + 1)
} else {
Unpacked::new(q + 1, k)
}
/// Inverse of `RawFloat::unpack()` for normalized numbers.
/// Panics if the significand or exponent are not valid for normalized numbers.
pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
- debug_assert!(T::min_sig() <= x.sig && x.sig <= T::max_sig(),
+ debug_assert!(T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
"encode_normal: significand not normalized");
// Remove the hidden bit
- let sig_enc = x.sig & !(1 << T::explicit_sig_bits());
+ let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS);
// Adjust the exponent for exponent bias and mantissa shift
- let k_enc = x.k + T::max_exp() + T::explicit_sig_bits() as i16;
- debug_assert!(k_enc != 0 && k_enc < T::max_encoded_exp(),
+ let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16;
+ debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP,
"encode_normal: exponent out of range");
// Leave sign bit at 0 ("+"), our numbers are all positive
- let bits = (k_enc as u64) << T::explicit_sig_bits() | sig_enc;
+ let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc;
T::from_bits(bits)
}
-/// Construct the subnormal. A mantissa of 0 is allowed and constructs zero.
+/// Construct a subnormal. A mantissa of 0 is allowed and constructs zero.
pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
- assert!(significand < T::min_sig(), "encode_subnormal: not actually subnormal");
+ assert!(significand < T::MIN_SIG, "encode_subnormal: not actually subnormal");
// Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
T::from_bits(significand)
}
Zero => panic!("prev_float: argument is zero"),
Normal => {
let Unpacked { sig, k } = x.unpack();
- if sig == T::min_sig() {
- encode_normal(Unpacked::new(T::max_sig(), k - 1))
+ if sig == T::MIN_SIG {
+ encode_normal(Unpacked::new(T::MAX_SIG, k - 1))
} else {
encode_normal(Unpacked::new(sig - 1, k))
}
pub fn next_float<T: RawFloat>(x: T) -> T {
match x.classify() {
Nan => panic!("next_float: argument is NaN"),
- Infinite => T::infinity2(),
+ Infinite => T::INFINITY,
// This seems too good to be true, but it works.
// 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa.
// In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F.
// Macro namespace
Macro(DefId, MacroKind),
+ GlobalAsm(DefId),
+
// Both namespaces
Err,
}
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) | Def::TyAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
- Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) => {
+ Def::AssociatedConst(id) | Def::Local(id) | Def::Upvar(id, ..) | Def::Macro(id, ..) |
+ Def::GlobalAsm(id) => {
id
}
Def::Label(..) => "label",
Def::SelfTy(..) => "self type",
Def::Macro(..) => "macro",
+ Def::GlobalAsm(..) => "global asm",
Def::Err => "unresolved item",
}
}
visitor.visit_id(item.id);
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
}
+ ItemGlobalAsm(_) => {
+ visitor.visit_id(item.id);
+ }
ItemTy(ref typ, ref type_parameters) => {
visitor.visit_id(item.id);
visitor.visit_ty(typ);
}
}
+ fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
+ P(hir::GlobalAsm {
+ asm: ga.asm,
+ ctxt: ga.ctxt,
+ })
+ }
+
fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
Spanned {
node: hir::Variant_ {
}
ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
+ ItemKind::GlobalAsm(ref ga) => hir::ItemGlobalAsm(self.lower_global_asm(ga)),
ItemKind::Ty(ref t, ref generics) => {
hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
}
DefPathData::ValueNs(i.ident.name.as_str()),
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
+ ItemKind::GlobalAsm(..) => DefPathData::Misc,
ItemKind::Use(ref view_path) => {
match view_path.node {
ViewPathGlob(..) => {}
ItemFn(..) => "fn",
ItemMod(..) => "mod",
ItemForeignMod(..) => "foreign mod",
+ ItemGlobalAsm(..) => "global asm",
ItemTy(..) => "ty",
ItemEnum(..) => "enum",
ItemStruct(..) => "struct",
pub items: HirVec<ForeignItem>,
}
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub struct GlobalAsm {
+ pub asm: Symbol,
+ pub ctxt: SyntaxContext,
+}
+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct EnumDef {
pub variants: HirVec<Variant>,
ItemMod(Mod),
/// An external module
ItemForeignMod(ForeignMod),
+ /// Module-level inline assembly (from global_asm!)
+ ItemGlobalAsm(P<GlobalAsm>),
/// A type alias, e.g. `type Foo = Bar<u8>`
ItemTy(P<Ty>, Generics),
/// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
ItemFn(..) => "function",
ItemMod(..) => "module",
ItemForeignMod(..) => "foreign module",
+ ItemGlobalAsm(..) => "global asm",
ItemTy(..) => "type alias",
ItemEnum(..) => "enum",
ItemStruct(..) => "struct",
self.print_foreign_mod(nmod, &item.attrs)?;
self.bclose(item.span)?;
}
+ hir::ItemGlobalAsm(ref ga) => {
+ self.head(&visibility_qualified(&item.vis, "global asm"))?;
+ word(&mut self.s, &ga.asm.as_str())?;
+ self.end()?
+ }
hir::ItemTy(ref ty, ref params) => {
self.ibox(indent_unit)?;
self.ibox(0)?;
hir::ItemFn(..) |
hir::ItemMod(..) |
hir::ItemForeignMod(..) |
+ hir::ItemGlobalAsm(..) |
hir::ItemTy(..) |
hir::ItemEnum(..) |
hir::ItemStruct(..) |
ItemFn(fn_decl, unsafety, constness, abi, generics, body_id),
ItemMod(module),
ItemForeignMod(foreign_mod),
+ ItemGlobalAsm(global_asm),
ItemTy(ty, generics),
ItemEnum(enum_def, generics),
ItemStruct(variant_data, generics),
is_indirect
});
+impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::GlobalAsm {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a, 'tcx>,
+ hasher: &mut StableHasher<W>) {
+ let hir::GlobalAsm {
+ asm,
+ ctxt: _
+ } = *self;
+
+ asm.hash_stable(hcx, hasher);
+ }
+}
+
impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::InlineAsm {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'tcx>,
Upvar(def_id, index, expr_id),
Label(node_id),
Macro(def_id, macro_kind),
+ GlobalAsm(def_id),
Err
});
hir::ItemMod(..) | hir::ItemForeignMod(..) |
hir::ItemImpl(..) | hir::ItemTrait(..) |
hir::ItemStruct(..) | hir::ItemEnum(..) |
- hir::ItemUnion(..) | hir::ItemDefaultImpl(..) => {}
+ hir::ItemUnion(..) | hir::ItemDefaultImpl(..) |
+ hir::ItemGlobalAsm(..) => {}
}
}
hir_map::NodeTraitItem(trait_method) => {
hir::ItemUse(..) |
hir::ItemMod(..) |
hir::ItemDefaultImpl(..) |
- hir::ItemForeignMod(..) => {
+ hir::ItemForeignMod(..) |
+ hir::ItemGlobalAsm(..) => {
// These sorts of items have no lifetime parameters at all.
intravisit::walk_item(self, item);
}
if other.evaluation == EvaluatedToOk {
if let ImplCandidate(victim_def) = victim.candidate {
let tcx = self.tcx().global_tcx();
- return traits::specializes(tcx, other_def, victim_def);
+ return traits::specializes(tcx, other_def, victim_def) ||
+ tcx.impls_are_allowed_to_overlap(other_def, victim_def);
}
}
possible_sibling,
impl_def_id);
if let Some(impl_header) = overlap {
+ if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+ return Ok((false, false));
+ }
+
let le = specializes(tcx, impl_def_id, possible_sibling);
let ge = specializes(tcx, possible_sibling, impl_def_id);
queries::impl_trait_ref::get(self, DUMMY_SP, id)
}
+ /// Returns true if the impls are the same polarity and are implementing
+ /// a trait which contains no items
+ pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
+ if !self.sess.features.borrow().overlapping_marker_traits {
+ return false;
+ }
+ let trait1_is_empty = self.impl_trait_ref(def_id1)
+ .map_or(false, |trait_ref| {
+ self.associated_item_def_ids(trait_ref.def_id).is_empty()
+ });
+ let trait2_is_empty = self.impl_trait_ref(def_id2)
+ .map_or(false, |trait_ref| {
+ self.associated_item_def_ids(trait_ref.def_id).is_empty()
+ });
+ self.trait_impl_polarity(def_id1) == self.trait_impl_polarity(def_id2)
+ && trait1_is_empty
+ && trait2_is_empty
+ }
+
// Returns `ty::VariantDef` if `def` refers to a struct,
// or variant or their constructors, panics otherwise.
pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
pub fn target() -> Result<Target, String> {
let mut post_link_args = LinkArgs::new();
- post_link_args.insert(LinkerFlavor::Gcc,
+ post_link_args.insert(LinkerFlavor::Em,
vec!["-s".to_string(),
"BINARYEN=1".to_string(),
"-s".to_string(),
/// Adds a new move entry for a move of `lp` that occurs at location `id` with kind `kind`.
pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- lp: Rc<LoanPath<'tcx>>,
+ orig_lp: Rc<LoanPath<'tcx>>,
id: ast::NodeId,
kind: MoveKind) {
- // Moving one union field automatically moves all its fields.
- if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
- if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
+ // Moving one union field automatically moves all its fields. Also move siblings of
+ // all parent union fields, moves do not propagate upwards automatically.
+ let mut lp = orig_lp.clone();
+ while let LpExtend(ref base_lp, mutbl, lp_elem) = lp.clone().kind {
+ if let (&ty::TyAdt(adt_def, _), LpInterior(opt_variant_id, interior))
+ = (&base_lp.ty.sty, lp_elem) {
if adt_def.is_union() {
for field in &adt_def.struct_variant().fields {
let field = InteriorKind::InteriorField(mc::NamedField(field.name));
- let field_ty = if field == interior {
- lp.ty
- } else {
- tcx.types.err // Doesn't matter
- };
- let sibling_lp_kind = LpExtend(base_lp.clone(), mutbl,
- LpInterior(opt_variant_id, field));
- let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
- self.add_move_helper(tcx, sibling_lp, id, kind);
+ if field != interior {
+ let sibling_lp_kind =
+ LpExtend(base_lp.clone(), mutbl, LpInterior(opt_variant_id, field));
+ let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, tcx.types.err));
+ self.add_move_helper(tcx, sibling_lp, id, kind);
+ }
}
- return;
}
}
+ lp = base_lp.clone();
}
- self.add_move_helper(tcx, lp.clone(), id, kind);
+ self.add_move_helper(tcx, orig_lp.clone(), id, kind);
}
fn add_move_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
hir::ItemStatic(..) |
hir::ItemFn(..) |
hir::ItemForeignMod(..) |
+ hir::ItemGlobalAsm(..) |
hir::ItemTy(..) => None,
hir::ItemEnum(..) |
/// See Module::setModuleInlineAsm.
pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
+ pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char);
/// See llvm::LLVMTypeKind::getTypeID.
pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind;
EntryKind::Trait(_) => Def::Trait(did),
EntryKind::Enum(..) => Def::Enum(did),
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
+ EntryKind::GlobalAsm => Def::GlobalAsm(did),
EntryKind::ForeignMod |
EntryKind::Impl(_) |
return self.encode_info_for_mod(FromId(item.id, (m, &item.attrs, &item.vis)));
}
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
+ hir::ItemGlobalAsm(..) => EntryKind::GlobalAsm,
hir::ItemTy(..) => EntryKind::Type,
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
hir::ItemStruct(ref struct_def, _) => {
hir::ItemFn(..) |
hir::ItemMod(..) |
hir::ItemForeignMod(..) |
+ hir::ItemGlobalAsm(..) |
hir::ItemExternCrate(..) |
hir::ItemUse(..) |
hir::ItemDefaultImpl(..) |
ForeignImmStatic,
ForeignMutStatic,
ForeignMod,
+ GlobalAsm,
Type,
Enum(ReprOptions),
Field,
EntryKind::ForeignImmStatic |
EntryKind::ForeignMutStatic |
EntryKind::ForeignMod |
+ EntryKind::GlobalAsm |
EntryKind::Field |
EntryKind::Type => {
// Nothing else to hash here.
self.prev_level
}
// Other `pub` items inherit levels from parents
- _ => {
+ hir::ItemConst(..) | hir::ItemEnum(..) | hir::ItemExternCrate(..) |
+ hir::ItemGlobalAsm(..) | hir::ItemFn(..) | hir::ItemMod(..) |
+ hir::ItemStatic(..) | hir::ItemStruct(..) | hir::ItemTrait(..) |
+ hir::ItemTy(..) | hir::ItemUnion(..) | hir::ItemUse(..) => {
if item.vis == hir::Public { self.prev_level } else { None }
}
};
}
}
}
- _ => {}
+ hir::ItemUse(..) | hir::ItemStatic(..) | hir::ItemConst(..) |
+ hir::ItemGlobalAsm(..) | hir::ItemTy(..) | hir::ItemMod(..) |
+ hir::ItemFn(..) | hir::ItemExternCrate(..) | hir::ItemDefaultImpl(..) => {}
}
// Mark all items in interfaces of reachable items as reachable
hir::ItemUse(..) => {}
// The interface is empty
hir::ItemDefaultImpl(..) => {}
+ // The interface is empty
+ hir::ItemGlobalAsm(..) => {}
// Visit everything
hir::ItemConst(..) | hir::ItemStatic(..) |
hir::ItemFn(..) | hir::ItemTy(..) => {
hir::ItemMod(..) => {}
// Checked in resolve
hir::ItemUse(..) => {}
+ // No subitems
+ hir::ItemGlobalAsm(..) => {}
// Subitems of these items have inherited publicity
hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
hir::ItemTy(..) => {
self.define(parent, ident, TypeNS, imported_binding);
}
+ ItemKind::GlobalAsm(..) => {}
+
ItemKind::Mod(..) if item.ident == keywords::Invalid.ident() => {} // Crate root
ItemKind::Mod(..) => {
}
}
- ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => {
+ ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(_)=> {
// do nothing, these are just around to be encoded
}
Def::AssociatedTy(..) |
Def::AssociatedConst(..) |
Def::PrimTy(_) |
+ Def::GlobalAsm(_) |
Def::Err => {
span_bug!(span,
"process_def_kind for unexpected item: {:?}",
Def::SelfTy(..) |
Def::Label(..) |
Def::Macro(..) |
+ Def::GlobalAsm(..) |
Def::Err => None,
}
}
llvm::LLVMMDNodeInContext(bcx.ccx.llcx(), &val, 1));
}
}
+
+pub fn trans_global_asm<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+ ga: &hir::GlobalAsm) {
+ let asm = CString::new(ga.asm.as_str().as_bytes()).unwrap();
+ unsafe {
+ llvm::LLVMRustAppendModuleInlineAsm(ccx.llmod(), asm.as_ptr());
+ }
+}
collect_neighbours(scx, instance, &mut neighbors);
}
+ TransItem::GlobalAsm(..) => {
+ recursion_depth_reset = None;
+ }
}
record_inlining_canditates(scx.tcx(), starting_point, &neighbors[..], inlining_map);
}
}
}
+ hir::ItemGlobalAsm(..) => {
+ debug!("RootCollector: ItemGlobalAsm({})",
+ def_id_to_string(self.scx.tcx(),
+ self.scx.tcx().hir.local_def_id(item.id)));
+ self.output.push(TransItem::GlobalAsm(item.id));
+ }
hir::ItemStatic(..) => {
debug!("RootCollector: ItemStatic({})",
def_id_to_string(self.scx.tcx(),
symbol_name.len().hash(&mut state);
symbol_name.hash(&mut state);
let exported = match item {
- TransItem::Fn(ref instance) => {
- let node_id =
- scx.tcx().hir.as_local_node_id(instance.def_id());
+ TransItem::Fn(ref instance) => {
+ let node_id =
+ scx.tcx().hir.as_local_node_id(instance.def_id());
node_id.map(|node_id| exported_symbols.contains(&node_id))
- .unwrap_or(false)
- }
- TransItem::Static(node_id) => {
+ .unwrap_or(false)
+ }
+ TransItem::Static(node_id) => {
exported_symbols.contains(&node_id)
- }
+ }
+ TransItem::GlobalAsm(..) => true,
};
exported.hash(&mut state);
}
TransItem::Fn(instance) => {
tcx.hir.as_local_node_id(instance.def_id())
}
- TransItem::Static(node_id) => Some(node_id),
+ TransItem::Static(node_id) | TransItem::GlobalAsm(node_id) => {
+ Some(node_id)
+ }
}
}
}
None => {
match trans_item {
TransItem::Fn(..) |
- TransItem::Static(..) => llvm::ExternalLinkage,
+ TransItem::Static(..) |
+ TransItem::GlobalAsm(..) => llvm::ExternalLinkage,
}
}
};
Some(def_id)
}
- TransItem::Static(node_id) => Some(tcx.hir.local_def_id(node_id)),
+ TransItem::Static(node_id) |
+ TransItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
}
}
TransItem::Fn(Instance { def, .. }) => {
tcx.hir.as_local_node_id(def.def_id())
}
- TransItem::Static(node_id) => Some(node_id),
+ TransItem::Static(node_id) |
+ TransItem::GlobalAsm(node_id) => {
+ Some(node_id)
+ }
}.map(|node_id| {
tcx.hir.span(node_id)
})
//! item-path. This is used for unit testing the code that generates
//! paths etc in all kinds of annoying scenarios.
+use asm;
use attributes;
use base;
use consts;
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub enum TransItem<'tcx> {
Fn(Instance<'tcx>),
- Static(NodeId)
+ Static(NodeId),
+ GlobalAsm(NodeId),
}
/// Describes how a translation item will be instantiated in object files.
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
}
}
+ TransItem::GlobalAsm(node_id) => {
+ let item = ccx.tcx().hir.expect_item(node_id);
+ if let hir::ItemGlobalAsm(ref ga) = item.node {
+ asm::trans_global_asm(ccx, ga);
+ } else {
+ span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
+ }
+ }
TransItem::Fn(instance) => {
let _task = ccx.tcx().dep_graph.in_task(
DepNode::TransCrateItem(instance.def_id())); // (*)
TransItem::Fn(instance) => {
TransItem::predefine_fn(ccx, instance, linkage, &symbol_name);
}
+ TransItem::GlobalAsm(..) => {}
}
debug!("END PREDEFINING '{} ({})' in cgu {}",
let def_id = scx.tcx().hir.local_def_id(node_id);
symbol_names::symbol_name(Instance::mono(scx.tcx(), def_id), scx)
}
+ TransItem::GlobalAsm(node_id) => {
+ let def_id = scx.tcx().hir.local_def_id(node_id);
+ format!("global_asm_{:?}", def_id)
+ }
}
}
}
}
TransItem::Static(..) => InstantiationMode::GloballyShared,
+ TransItem::GlobalAsm(..) => InstantiationMode::GloballyShared,
}
}
TransItem::Fn(ref instance) => {
instance.substs.types().next().is_some()
}
- TransItem::Static(..) => false,
+ TransItem::Static(..) |
+ TransItem::GlobalAsm(..) => false,
}
}
let def_id = match *self {
TransItem::Fn(ref instance) => instance.def_id(),
TransItem::Static(node_id) => tcx.hir.local_def_id(node_id),
+ TransItem::GlobalAsm(..) => return None,
};
let attributes = tcx.get_attrs(def_id);
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
to_string_internal(tcx, "static ", instance)
},
+ TransItem::GlobalAsm(..) => {
+ "global_asm".to_string()
+ }
};
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
TransItem::Static(id) => {
format!("Static({:?})", id)
}
+ TransItem::GlobalAsm(id) => {
+ format!("GlobalAsm({:?})", id)
+ }
}
}
}
let def_id = tcx.hir.local_def_id(item_id);
match it.node {
// These don't define types.
- hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => {
- }
+ hir::ItemExternCrate(_) |
+ hir::ItemUse(..) |
+ hir::ItemMod(_) |
+ hir::ItemGlobalAsm(_) => {}
hir::ItemForeignMod(ref foreign_mod) => {
for item in &foreign_mod.items {
let def_id = tcx.hir.local_def_id(item.id);
tcx.item_generics(def_id);
tcx.item_type(def_id);
tcx.item_predicates(def_id);
- },
- _ => {
+ }
+ hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => {
tcx.item_generics(def_id);
tcx.item_type(def_id);
tcx.item_predicates(def_id);
- },
+ }
}
}
ItemTrait(..) |
ItemMod(..) |
ItemForeignMod(..) |
+ ItemGlobalAsm(..) |
ItemExternCrate(..) |
ItemUse(..) => {
span_bug!(
hir::ItemFn(..) |
hir::ItemMod(..) |
hir::ItemForeignMod(..) |
+ hir::ItemGlobalAsm(..) |
hir::ItemTy(..) |
hir::ItemImpl(..) |
hir::ItemDefaultImpl(..) => {}
hir::ItemFn(..) |
hir::ItemMod(..) |
hir::ItemForeignMod(..) |
+ hir::ItemGlobalAsm(..) |
hir::ItemTy(..) => {}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct PathSegment {
pub name: String,
- pub params: PathParameters
+ pub params: PathParameters,
}
impl Clean<PathSegment> for hir::PathSegment {
/// rendering function with the necessary arguments for linking to a local path.
fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
print_all: bool, use_absolute: bool, is_not_debug: bool) -> fmt::Result {
- let last = path.segments.last().unwrap();
- let rel_root = match &*path.segments[0].name {
- "self" => Some("./".to_string()),
- _ => None,
+ let empty = clean::PathSegment {
+ name: String::new(),
+ params: clean::PathParameters::Parenthesized {
+ inputs: Vec::new(),
+ output: None,
+ }
+ };
+ let last = path.segments.last()
+ .unwrap_or(&empty);
+ let rel_root = if path.segments.is_empty() {
+ None
+ } else {
+ match &*path.segments[0].name {
+ "self" => Some("./".to_string()),
+ _ => None,
+ }
};
if print_all {
root.push_str(&seg.name);
root.push_str("/");
if is_not_debug {
- write!(w, "<a class=\"mod\"
- href=\"{}index.html\">{}</a>::",
- root,
- seg.name)?;
+ write!(w, "<a class=\"mod\" href=\"{}index.html\">{}</a>::",
+ root,
+ seg.name)?;
} else {
write!(w, "{}::", seg.name)?;
}
match href(did) {
Some((_, _, fqp)) => format!("{}::{}",
fqp[..fqp.len()-1].join("::"),
- HRef::new(did, fqp.last().unwrap())),
+ HRef::new(did, fqp.last()
+ .unwrap_or(&String::new()))),
None => format!("{}", HRef::new(did, &last.name)),
}
} else {
match href(did) {
Some((_, _, fqp)) => format!("{:?}::{:?}",
fqp[..fqp.len()-1].join("::"),
- HRef::new(did, fqp.last().unwrap())),
+ HRef::new(did, fqp.last()
+ .unwrap_or(&String::new()))),
None => format!("{:?}", HRef::new(did, &last.name)),
}
} else {
}
Ok(())
}
- // It's pretty unsightly to look at `<A as B>::C` in output, and
- // we've got hyperlinking on our side, so try to avoid longer
- // notation as much as possible by making `C` a hyperlink to trait
- // `B` to disambiguate.
- //
- // FIXME: this is still a lossy conversion and there should probably
- // be a better way of representing this in general? Most of
- // the ugliness comes from inlining across crates where
- // everything comes in as a fully resolved QPath (hard to
- // look at).
- clean::QPath {
- ref name,
- ref self_type,
- trait_: box clean::ResolvedPath { did, ref typarams, .. },
- } => {
- if f.alternate() {
- write!(f, "{:#}::", self_type)?;
- } else {
- write!(f, "{}::", self_type)?;
- }
- let path = clean::Path::singleton(name.clone());
- resolved_path(f, did, &path, true, use_absolute, is_not_debug)?;
-
- // FIXME: `typarams` are not rendered, and this seems bad?
- drop(typarams);
- Ok(())
- }
clean::QPath { ref name, ref self_type, ref trait_ } => {
+ let should_show_cast = match *trait_ {
+ box clean::ResolvedPath { .. } => {
+ let path = clean::Path::singleton(name.clone());
+ !path.segments.is_empty() && &format!("{:#}", trait_) != "()" &&
+ &format!("{:#}", self_type) != "Self"
+ }
+ _ => true,
+ };
if f.alternate() {
if is_not_debug {
- write!(f, "<{:#} as {:#}>::{}", self_type, trait_, name)
+ if should_show_cast {
+ write!(f, "<{:#} as {:#}>::", self_type, trait_)?
+ } else {
+ write!(f, "{:#}::", self_type)?
+ }
} else {
- write!(f, "<{:#?} as {:#?}>::{}", self_type, trait_, name)
+ if should_show_cast {
+ write!(f, "<{:#?} as {:#?}>::", self_type, trait_)?
+ } else {
+ write!(f, "{:#?}::", self_type)?
+ }
}
} else {
if is_not_debug {
- write!(f, "<{} as {}>::{}", self_type, trait_, name)
+ if should_show_cast {
+ write!(f, "<{} as {}>::", self_type, trait_)?
+ } else {
+ write!(f, "{}::", self_type)?
+ }
} else {
- write!(f, "<{:?} as {:?}>::{}", self_type, trait_, name)
+ if should_show_cast {
+ write!(f, "<{:?} as {:?}>::", self_type, trait_)?
+ } else {
+ write!(f, "{:?}::", self_type)?
+ }
+ }
+ };
+ match *trait_ {
+ // It's pretty unsightly to look at `<A as B>::C` in output, and
+ // we've got hyperlinking on our side, so try to avoid longer
+ // notation as much as possible by making `C` a hyperlink to trait
+ // `B` to disambiguate.
+ //
+ // FIXME: this is still a lossy conversion and there should probably
+ // be a better way of representing this in general? Most of
+ // the ugliness comes from inlining across crates where
+ // everything comes in as a fully resolved QPath (hard to
+ // look at).
+ box clean::ResolvedPath { did, ref typarams, .. } => {
+ let path = clean::Path::singleton(name.clone());
+ resolved_path(f, did, &path, true, use_absolute, is_not_debug)?;
+
+ // FIXME: `typarams` are not rendered, and this seems bad?
+ drop(typarams);
+ Ok(())
+ }
+ _ => {
+ write!(f, "{}", name)
}
}
}
}
// If we're inlining, skip private items.
_ if self.inlining && item.vis != hir::Public => {}
+ hir::ItemGlobalAsm(..) => {}
hir::ItemExternCrate(ref p) => {
let cstore = &self.cx.sess().cstore;
om.extern_crates.push(ExternCrate {
use rustc::hir::def::Def;
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
use rustc::ty::Visibility;
+use rustc::util::nodemap::FxHashSet;
use std::cell::RefMut;
access_levels: RefMut<'a, AccessLevels<DefId>>,
// Previous accessibility level, None means unreachable
prev_level: Option<AccessLevel>,
+ // Keeps track of already visited modules, in case a module re-exports its parent
+ visited_mods: FxHashSet<DefId>,
}
impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
cstore: &*cx.sess().cstore,
access_levels: cx.access_levels.borrow_mut(),
prev_level: Some(AccessLevel::Public),
+ visited_mods: FxHashSet()
}
}
}
pub fn visit_mod(&mut self, def_id: DefId) {
+ if !self.visited_mods.insert(def_id) {
+ return;
+ }
+
for item in self.cstore.item_children(def_id) {
self.visit_item(item.def);
}
// 1. Alfredo Viola (2005). Distributional analysis of Robin Hood linear probing
// hashing with buckets.
-/// A hash map implementation which uses linear probing with Robin Hood bucket
-/// stealing.
+/// A hash map implemented with linear probing and Robin Hood bucket stealing.
///
/// By default, `HashMap` uses a hashing algorithm selected to provide
/// resistance against HashDoS attacks. The algorithm is randomly seeded, and a
/// attacks such as HashDoS.
///
/// The hashing algorithm can be replaced on a per-`HashMap` basis using the
-/// [`HashMap::default`], [`HashMap::with_hasher`], and
-/// [`HashMap::with_capacity_and_hasher`] methods. Many alternative algorithms
-/// are available on crates.io, such as the [`fnv`] crate.
+/// [`default`], [`with_hasher`], and [`with_capacity_and_hasher`] methods. Many
+/// alternative algorithms are available on crates.io, such as the [`fnv`] crate.
///
/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although
/// this can frequently be achieved by using `#[derive(PartialEq, Eq, Hash)]`.
/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
/// [`Cell`]: ../../std/cell/struct.Cell.html
-/// [`HashMap::default`]: #method.default
-/// [`HashMap::with_hasher`]: #method.with_hasher
-/// [`HashMap::with_capacity_and_hasher`]: #method.with_capacity_and_hasher
+/// [`default`]: #method.default
+/// [`with_hasher`]: #method.with_hasher
+/// [`with_capacity_and_hasher`]: #method.with_capacity_and_hasher
/// [`fnv`]: https://crates.io/crates/fnv
///
/// ```
/// }
/// ```
///
-/// A HashMap with fixed list of elements can be initialized from an array:
+/// A `HashMap` with fixed list of elements can be initialized from an array:
///
/// ```
/// use std::collections::HashMap;
}
}
- /// Creates an empty `HashMap` with the specified capacity, using `hasher`
+ /// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
/// to hash the keys.
///
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. If `capacity` is 0, the hash map will not allocate.
- /// Warning: `hasher` is normally randomly generated, and
+ ///
+ /// Warning: `hash_builder` is normally randomly generated, and
/// is designed to allow HashMaps to be resistant to attacks that
/// cause many collisions and very poor performance. Setting it
/// manually using this function can expose a DoS attack vector.
}
}
- /// Returns a reference to the map's hasher.
+ /// Returns a reference to the map's [`BuildHasher`].
+ ///
+ /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
#[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
pub fn hasher(&self) -> &S {
&self.hash_builder
}
/// An iterator visiting all keys in arbitrary order.
- /// Iterator element type is `&'a K`.
+ /// The iterator element type is `&'a K`.
///
/// # Examples
///
}
/// An iterator visiting all values in arbitrary order.
- /// Iterator element type is `&'a V`.
+ /// The iterator element type is `&'a V`.
///
/// # Examples
///
}
/// An iterator visiting all values mutably in arbitrary order.
- /// Iterator element type is `&'a mut V`.
+ /// The iterator element type is `&'a mut V`.
///
/// # Examples
///
}
/// An iterator visiting all key-value pairs in arbitrary order.
- /// Iterator element type is `(&'a K, &'a V)`.
+ /// The iterator element type is `(&'a K, &'a V)`.
///
/// # Examples
///
/// An iterator visiting all key-value pairs in arbitrary order,
/// with mutable references to the values.
- /// Iterator element type is `(&'a K, &'a mut V)`.
+ /// The iterator element type is `(&'a K, &'a mut V)`.
///
/// # Examples
///
}
}
-/// HashMap iterator.
+/// An iterator over the entries of a `HashMap`.
+///
+/// This `struct` is created by the [`iter`] method on [`HashMap`]. See its
+/// documentation for more.
+///
+/// [`iter`]: struct.HashMap.html#method.iter
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, K: 'a, V: 'a> {
inner: table::Iter<'a, K, V>,
}
}
-/// HashMap mutable values iterator.
+/// A mutable iterator over the entries of a `HashMap`.
+///
+/// This `struct` is created by the [`iter_mut`] method on [`HashMap`]. See its
+/// documentation for more.
+///
+/// [`iter_mut`]: struct.HashMap.html#method.iter_mut
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IterMut<'a, K: 'a, V: 'a> {
inner: table::IterMut<'a, K, V>,
}
-/// HashMap move iterator.
+/// An owning iterator over the entries of a `HashMap`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`HashMap`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
+///
+/// [`into_iter`]: struct.HashMap.html#method.into_iter
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<K, V> {
pub(super) inner: table::IntoIter<K, V>,
}
-/// HashMap keys iterator.
+/// An iterator over the keys of a `HashMap`.
+///
+/// This `struct` is created by the [`keys`] method on [`HashMap`]. See its
+/// documentation for more.
+///
+/// [`keys`]: struct.HashMap.html#method.keys
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Keys<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
}
-/// HashMap values iterator.
+/// An iterator over the values of a `HashMap`.
+///
+/// This `struct` is created by the [`values`] method on [`HashMap`]. See its
+/// documentation for more.
+///
+/// [`values`]: struct.HashMap.html#method.values
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Values<'a, K: 'a, V: 'a> {
inner: Iter<'a, K, V>,
}
}
-/// HashMap drain iterator.
+/// A draining iterator over the entries of a `HashMap`.
+///
+/// This `struct` is created by the [`drain`] method on [`HashMap`]. See its
+/// documentation for more.
+///
+/// [`drain`]: struct.HashMap.html#method.drain
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "drain", since = "1.6.0")]
pub struct Drain<'a, K: 'a, V: 'a> {
pub(super) inner: table::Drain<'a, K, V>,
}
-/// Mutable HashMap values iterator.
+/// A mutable iterator over the values of a `HashMap`.
+///
+/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
+/// documentation for more.
+///
+/// [`values_mut`]: struct.HashMap.html#method.values_mut
+/// [`HashMap`]: struct.HashMap.html
#[stable(feature = "map_values_mut", since = "1.10.0")]
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}
}
-/// A view into a single location in a map, which may be vacant or occupied.
-/// This enum is constructed from the [`entry`] method on [`HashMap`].
+/// A view into a single entry in a map, which may either be vacant or occupied.
+///
+/// This `enum` is constructed from the [`entry`] method on [`HashMap`].
///
/// [`HashMap`]: struct.HashMap.html
/// [`entry`]: struct.HashMap.html#method.entry
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Entry<'a, K: 'a, V: 'a> {
- /// An occupied Entry.
+ /// An occupied entry.
#[stable(feature = "rust1", since = "1.0.0")]
Occupied(#[stable(feature = "rust1", since = "1.0.0")]
OccupiedEntry<'a, K, V>),
- /// A vacant Entry.
+ /// A vacant entry.
#[stable(feature = "rust1", since = "1.0.0")]
Vacant(#[stable(feature = "rust1", since = "1.0.0")]
VacantEntry<'a, K, V>),
}
}
-/// A view into a single occupied location in a HashMap.
+/// A view into an occupied entry in a `HashMap`.
/// It is part of the [`Entry`] enum.
///
/// [`Entry`]: enum.Entry.html
}
}
-/// A view into a single empty location in a HashMap.
+/// A view into a vacant entry in a `HashMap`.
/// It is part of the [`Entry`] enum.
///
/// [`Entry`]: enum.Entry.html
#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
impl Default for DefaultHasher {
- /// Creates a new `DefaultHasher` using [`DefaultHasher::new`]. See
- /// [`DefaultHasher::new`] documentation for more information.
+ /// Creates a new `DefaultHasher` using [`new`]. See its documentation for more.
///
- /// [`DefaultHasher::new`]: #method.new
+ /// [`new`]: #method.new
fn default() -> DefaultHasher {
DefaultHasher::new()
}
// for `bucket.val` in the case of HashSet. I suppose we would need HKT
// to get rid of it properly.
-/// An implementation of a hash set using the underlying representation of a
-/// HashMap where the value is ().
+/// A hash set implemented as a `HashMap` where the value is `()`.
///
-/// As with the `HashMap` type, a `HashSet` requires that the elements
-/// implement the `Eq` and `Hash` traits. This can frequently be achieved by
+/// As with the [`HashMap`] type, a `HashSet` requires that the elements
+/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by
/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself,
/// it is important that the following property holds:
///
///
///
/// It is a logic error for an item to be modified in such a way that the
-/// item's hash, as determined by the `Hash` trait, or its equality, as
-/// determined by the `Eq` trait, changes while it is in the set. This is
-/// normally only possible through `Cell`, `RefCell`, global state, I/O, or
+/// item's hash, as determined by the [`Hash`] trait, or its equality, as
+/// determined by the [`Eq`] trait, changes while it is in the set. This is
+/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
/// unsafe code.
///
/// # Examples
/// ```
///
/// The easiest way to use `HashSet` with a custom type is to derive
-/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the
-/// future be implied by `Eq`.
+/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`], this will in the
+/// future be implied by [`Eq`].
///
/// ```
/// use std::collections::HashSet;
/// }
/// ```
///
-/// HashSet with fixed list of elements can be initialized from an array:
+/// A `HashSet` with fixed list of elements can be initialized from an array:
///
/// ```
/// use std::collections::HashSet;
/// // use the values stored in the set
/// }
/// ```
+///
+/// [`Cell`]: ../../std/cell/struct.Cell.html
+/// [`Eq`]: ../../std/cmp/trait.Eq.html
+/// [`Hash`]: ../../std/hash/trait.Hash.html
+/// [`HashMap`]: struct.HashMap.html
+/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
+/// [`RefCell`]: ../../std/cell/struct.RefCell.html
#[derive(Clone)]
HashSet { map: HashMap::with_hasher(hasher) }
}
- /// Creates an empty HashSet with with the specified capacity, using
+ /// Creates an empty `HashSet` with with the specified capacity, using
/// `hasher` to hash the keys.
///
/// The hash set will be able to hold at least `capacity` elements without
HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
}
- /// Returns a reference to the set's hasher.
+ /// Returns a reference to the set's [`BuildHasher`].
+ ///
+ /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html
#[stable(feature = "hashmap_public_hasher", since = "1.9.0")]
pub fn hasher(&self) -> &S {
self.map.hasher()
}
/// An iterator visiting all elements in arbitrary order.
- /// Iterator element type is &'a T.
+ /// The iterator element type is `&'a T`.
///
/// # Examples
///
Iter { iter: self.map.keys() }
}
- /// Visit the values representing the difference,
+ /// Visits the values representing the difference,
/// i.e. the values that are in `self` but not in `other`.
///
/// # Examples
}
}
- /// Visit the values representing the symmetric difference,
+ /// Visits the values representing the symmetric difference,
/// i.e. the values that are in `self` or in `other` but not in both.
///
/// # Examples
SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
}
- /// Visit the values representing the intersection,
+ /// Visits the values representing the intersection,
/// i.e. the values that are both in `self` and `other`.
///
/// # Examples
}
}
- /// Visit the values representing the union,
+ /// Visits the values representing the union,
/// i.e. all the values in `self` or `other`, without duplicates.
///
/// # Examples
/// Returns `true` if the set contains a value.
///
/// The value may be any borrowed form of the set's value type, but
- /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
/// the value type.
///
/// # Examples
/// assert_eq!(set.contains(&1), true);
/// assert_eq!(set.contains(&4), false);
/// ```
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where T: Borrow<Q>,
/// Returns a reference to the value in the set, if any, that is equal to the given value.
///
/// The value may be any borrowed form of the set's value type, but
- /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
/// the value type.
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
#[stable(feature = "set_recovery", since = "1.9.0")]
pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
where T: Borrow<Q>,
/// present in the set.
///
/// The value may be any borrowed form of the set's value type, but
- /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
/// the value type.
///
/// # Examples
/// assert_eq!(set.remove(&2), true);
/// assert_eq!(set.remove(&2), false);
/// ```
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
where T: Borrow<Q>,
/// Removes and returns the value in the set, if any, that is equal to the given one.
///
/// The value may be any borrowed form of the set's value type, but
- /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
/// the value type.
+ ///
+ /// [`Eq`]: ../../std/cmp/trait.Eq.html
+ /// [`Hash`]: ../../std/hash/trait.Hash.html
#[stable(feature = "set_recovery", since = "1.9.0")]
pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
where T: Borrow<Q>,
}
}
-/// HashSet iterator
+/// An iterator over the items of a `HashSet`.
+///
+/// This `struct` is created by the [`iter`] method on [`HashSet`].
+/// See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`iter`]: struct.HashSet.html#method.iter
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Iter<'a, K: 'a> {
iter: Keys<'a, K, ()>,
}
-/// HashSet move iterator
+/// An owning iterator over the items of a `HashSet`.
+///
+/// This `struct` is created by the [`into_iter`] method on [`HashSet`]
+/// (provided by the `IntoIterator` trait). See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`into_iter`]: struct.HashSet.html#method.into_iter
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<K> {
iter: map::IntoIter<K, ()>,
}
-/// HashSet drain iterator
+/// A draining iterator over the items of a `HashSet`.
+///
+/// This `struct` is created by the [`drain`] method on [`HashSet`].
+/// See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`drain`]: struct.HashSet.html#method.drain
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Drain<'a, K: 'a> {
iter: map::Drain<'a, K, ()>,
}
-/// Intersection iterator
+/// A lazy iterator producing elements in the intersection of `HashSet`s.
+///
+/// This `struct` is created by the [`intersection`] method on [`HashSet`].
+/// See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`intersection`]: struct.HashSet.html#method.intersection
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Intersection<'a, T: 'a, S: 'a> {
// iterator of the first set
other: &'a HashSet<T, S>,
}
-/// Difference iterator
+/// A lazy iterator producing elements in the difference of `HashSet`s.
+///
+/// This `struct` is created by the [`difference`] method on [`HashSet`].
+/// See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`difference`]: struct.HashSet.html#method.difference
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Difference<'a, T: 'a, S: 'a> {
// iterator of the first set
other: &'a HashSet<T, S>,
}
-/// Symmetric difference iterator.
+/// A lazy iterator producing elements in the symmetric difference of `HashSet`s.
+///
+/// This `struct` is created by the [`symmetric_difference`] method on
+/// [`HashSet`]. See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
}
-/// Set union iterator.
+/// A lazy iterator producing elements in the union of `HashSet`s.
+///
+/// This `struct` is created by the [`union`] method on [`HashSet`].
+/// See its documentation for more.
+///
+/// [`HashSet`]: struct.HashSet.html
+/// [`union`]: struct.HashSet.html#method.union
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Union<'a, T: 'a, S: 'a> {
iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
//! information to do this itself. Therefore, it is up to us programmers to give
//! it hints.
//!
-//! Any `with_capacity()` constructor will instruct the collection to allocate
+//! Any `with_capacity` constructor will instruct the collection to allocate
//! enough space for the specified number of elements. Ideally this will be for
//! exactly that many elements, but some implementation details may prevent
//! this. [`Vec`] and [`VecDeque`] can be relied on to allocate exactly the
-//! requested amount, though. Use `with_capacity()` when you know exactly how many
+//! requested amount, though. Use `with_capacity` when you know exactly how many
//! elements will be inserted, or at least have a reasonable upper-bound on that
//! number.
//!
-//! When anticipating a large influx of elements, the `reserve()` family of
+//! When anticipating a large influx of elements, the `reserve` family of
//! methods can be used to hint to the collection how much room it should make
-//! for the coming items. As with `with_capacity()`, the precise behavior of
+//! for the coming items. As with `with_capacity`, the precise behavior of
//! these methods will be specific to the collection of interest.
//!
//! For optimal performance, collections will generally avoid shrinking
//! themselves. If you believe that a collection will not soon contain any more
-//! elements, or just really need the memory, the `shrink_to_fit()` method prompts
+//! elements, or just really need the memory, the `shrink_to_fit` method prompts
//! the collection to shrink the backing array to the minimum size capable of
//! holding its elements.
//!
//! Finally, if ever you're interested in what the actual capacity of the
-//! collection is, most collections provide a `capacity()` method to query this
+//! collection is, most collections provide a `capacity` method to query this
//! information on demand. This can be useful for debugging purposes, or for
-//! use with the `reserve()` methods.
+//! use with the `reserve` methods.
//!
//! ## Iterators
//!
//!
//! All of the standard collections provide several iterators for performing
//! bulk manipulation of their contents. The three primary iterators almost
-//! every collection should provide are `iter()`, `iter_mut()`, and `into_iter()`.
+//! every collection should provide are `iter`, `iter_mut`, and `into_iter`.
//! Some of these are not provided on collections where it would be unsound or
//! unreasonable to provide them.
//!
-//! `iter()` provides an iterator of immutable references to all the contents of a
+//! `iter` provides an iterator of immutable references to all the contents of a
//! collection in the most "natural" order. For sequence collections like [`Vec`],
//! this means the items will be yielded in increasing order of index starting
//! at 0. For ordered collections like [`BTreeMap`], this means that the items
//! }
//! ```
//!
-//! `iter_mut()` provides an iterator of *mutable* references in the same order as
-//! `iter()`. This is great for mutating all the contents of the collection.
+//! `iter_mut` provides an iterator of *mutable* references in the same order as
+//! `iter`. This is great for mutating all the contents of the collection.
//!
//! ```
//! let mut vec = vec![1, 2, 3, 4];
//! }
//! ```
//!
-//! `into_iter()` transforms the actual collection into an iterator over its
+//! `into_iter` transforms the actual collection into an iterator over its
//! contents by-value. This is great when the collection itself is no longer
-//! needed, and the values are needed elsewhere. Using `extend()` with `into_iter()`
+//! needed, and the values are needed elsewhere. Using `extend` with `into_iter`
//! is the main way that contents of one collection are moved into another.
-//! `extend()` automatically calls `into_iter()`, and takes any `T: `[`IntoIterator`].
-//! Calling `collect()` on an iterator itself is also a great way to convert one
+//! `extend` automatically calls `into_iter`, and takes any `T: `[`IntoIterator`].
+//! Calling `collect` on an iterator itself is also a great way to convert one
//! collection into another. Both of these methods should internally use the
//! capacity management tools discussed in the previous section to do this as
//! efficiently as possible.
//! ```
//!
//! Iterators also provide a series of *adapter* methods for performing common
-//! threads to sequences. Among the adapters are functional favorites like `map()`,
-//! `fold()`, `skip()` and `take()`. Of particular interest to collections is the
-//! `rev()` adapter, that reverses any iterator that supports this operation. Most
+//! threads to sequences. Among the adapters are functional favorites like `map`,
+//! `fold`, `skip` and `take`. Of particular interest to collections is the
+//! `rev` adapter, that reverses any iterator that supports this operation. Most
//! collections provide reversible iterators as the way to iterate over them in
//! reverse order.
//!
//!
//! Several other collection methods also return iterators to yield a sequence
//! of results but avoid allocating an entire collection to store the result in.
-//! This provides maximum flexibility as `collect()` or `extend()` can be called to
+//! This provides maximum flexibility as `collect` or `extend` can be called to
//! "pipe" the sequence into any collection if desired. Otherwise, the sequence
//! can be looped over with a `for` loop. The iterator can also be discarded
//! after partial use, preventing the computation of the unused items.
//!
//! ## Entries
//!
-//! The `entry()` API is intended to provide an efficient mechanism for
+//! The `entry` API is intended to provide an efficient mechanism for
//! manipulating the contents of a map conditionally on the presence of a key or
//! not. The primary motivating use case for this is to provide efficient
//! accumulator maps. For instance, if one wishes to maintain a count of the
//! number of times each key has been seen, they will have to perform some
//! conditional logic on whether this is the first time the key has been seen or
-//! not. Normally, this would require a `find()` followed by an `insert()`,
+//! not. Normally, this would require a `find` followed by an `insert`,
//! effectively duplicating the search effort on each insertion.
//!
//! When a user calls `map.entry(&key)`, the map will search for the key and
//! then yield a variant of the `Entry` enum.
//!
//! If a `Vacant(entry)` is yielded, then the key *was not* found. In this case
-//! the only valid operation is to `insert()` a value into the entry. When this is
+//! the only valid operation is to `insert` a value into the entry. When this is
//! done, the vacant entry is consumed and converted into a mutable reference to
//! the value that was inserted. This allows for further manipulation of the
//! value beyond the lifetime of the search itself. This is useful if complex
//! just inserted.
//!
//! If an `Occupied(entry)` is yielded, then the key *was* found. In this case,
-//! the user has several options: they can `get()`, `insert()` or `remove()` the
+//! the user has several options: they can `get`, `insert` or `remove` the
//! value of the occupied entry. Additionally, they can convert the occupied
//! entry into a mutable reference to its value, providing symmetry to the
-//! vacant `insert()` case.
+//! vacant `insert` case.
//!
//! ### Examples
//!
-//! Here are the two primary ways in which `entry()` is used. First, a simple
+//! Here are the two primary ways in which `entry` is used. First, a simple
//! example where the logic performed on the values is trivial.
//!
//! #### Counting the number of times each character in a string occurs
//! ```
//!
//! When the logic to be performed on the value is more complex, we may simply
-//! use the `entry()` API to ensure that the value is initialized and perform the
+//! use the `entry` API to ensure that the value is initialized and perform the
//! logic afterwards.
//!
//! #### Tracking the inebriation of customers at a bar
//!
//! # Insert and complex keys
//!
-//! If we have a more complex key, calls to `insert()` will
+//! If we have a more complex key, calls to `insert` will
//! not update the value of the key. For example:
//!
//! ```
#[stable(feature = "rust1", since = "1.0.0")]
pub mod hash_map {
- //! A hash map implementation which uses linear probing with Robin
- //! Hood bucket stealing.
+ //! A hash map implemented with linear probing and Robin Hood bucket stealing.
#[stable(feature = "rust1", since = "1.0.0")]
pub use super::hash::map::*;
}
#[stable(feature = "rust1", since = "1.0.0")]
pub mod hash_set {
- //! An implementation of a hash set using the underlying representation of a
- //! HashMap where the value is ().
+ //! A hash set implemented as a `HashMap` where the value is `()`.
#[stable(feature = "rust1", since = "1.0.0")]
pub use super::hash::set::*;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! The 32-bit floating point type.
+//! This module provides constants which are specific to the implementation
+//! of the `f32` floating point data type. Mathematically significant
+//! numbers are provided in the `consts` sub-module.
//!
//! *[See also the `f32` primitive type](../primitive.f32.html).*
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! The 64-bit floating point type.
+//! This module provides constants which are specific to the implementation
+//! of the `f64` floating point data type. Mathematically significant
+//! numbers are provided in the `consts` sub-module.
//!
//! *[See also the `f64` primitive type](../primitive.f64.html).*
pub items: Vec<ForeignItem>,
}
+/// Global inline assembly
+///
+/// aka module-level assembly or file-scoped assembly
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+pub struct GlobalAsm {
+ pub asm: Symbol,
+ pub ctxt: SyntaxContext,
+}
+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct EnumDef {
pub variants: Vec<Variant>,
///
/// E.g. `extern {}` or `extern "C" {}`
ForeignMod(ForeignMod),
+ /// Module-level inline assembly (from `global_asm!()`)
+ GlobalAsm(P<GlobalAsm>),
/// A type alias (`type` or `pub type`).
///
/// E.g. `type Foo = Bar<u8>;`
ItemKind::Fn(..) => "function",
ItemKind::Mod(..) => "module",
ItemKind::ForeignMod(..) => "foreign module",
+ ItemKind::GlobalAsm(..) => "global asm",
ItemKind::Ty(..) => "type alias",
ItemKind::Enum(..) => "enum",
ItemKind::Struct(..) => "struct",
feature_tests! {
fn enable_quotes = quote,
fn enable_asm = asm,
+ fn enable_global_asm = global_asm,
fn enable_log_syntax = log_syntax,
fn enable_concat_idents = concat_idents,
fn enable_trace_macros = trace_macros,
// Hack to document `-Z linker-flavor` in The Unstable Book
(active, linker_flavor, "1.18.0", Some(41142)),
+
+ // Allows module-level inline assembly by way of global_asm!()
+ (active, global_asm, "1.18.0", Some(35119)),
+
+ // Allows overlapping impls of marker traits
+ (active, overlapping_marker_traits, "1.18.0", Some(29864)),
);
declare_features! (
pub const EXPLAIN_ASM: &'static str =
"inline assembly is not stable enough for use and is subject to change";
+pub const EXPLAIN_GLOBAL_ASM: &'static str =
+ "`global_asm!` is not stable enough for use and is subject to change";
+
pub const EXPLAIN_LOG_SYNTAX: &'static str =
"`log_syntax!` is not stable enough for use and is subject to change";
noop_fold_foreign_mod(nm, self)
}
+ fn fold_global_asm(&mut self, ga: P<GlobalAsm>) -> P<GlobalAsm> {
+ noop_fold_global_asm(ga, self)
+ }
+
fn fold_variant(&mut self, v: Variant) -> Variant {
noop_fold_variant(v, self)
}
}
}
+pub fn noop_fold_global_asm<T: Folder>(ga: P<GlobalAsm>,
+ _: &mut T) -> P<GlobalAsm> {
+ ga
+}
+
pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
Spanned {
node: Variant_ {
}
ItemKind::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
+ ItemKind::GlobalAsm(ga) => ItemKind::GlobalAsm(folder.fold_global_asm(ga)),
ItemKind::Ty(t, generics) => {
ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
}
self.print_foreign_mod(nmod, &item.attrs)?;
self.bclose(item.span)?;
}
+ ast::ItemKind::GlobalAsm(ref ga) => {
+ self.head(&visibility_qualified(&item.vis, "global_asm!"))?;
+ word(&mut self.s, &ga.asm.as_str())?;
+ self.end()?;
+ }
ast::ItemKind::Ty(ref ty, ref params) => {
self.ibox(INDENT_UNIT)?;
self.ibox(0)?;
}
fn visit_mod(&mut self, m: &'ast Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
fn visit_foreign_item(&mut self, i: &'ast ForeignItem) { walk_foreign_item(self, i) }
+ fn visit_global_asm(&mut self, ga: &'ast GlobalAsm) { walk_global_asm(self, ga) }
fn visit_item(&mut self, i: &'ast Item) { walk_item(self, i) }
fn visit_local(&mut self, l: &'ast Local) { walk_local(self, l) }
fn visit_block(&mut self, b: &'ast Block) { walk_block(self, b) }
ItemKind::ForeignMod(ref foreign_module) => {
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
}
+ ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga),
ItemKind::Ty(ref typ, ref type_parameters) => {
visitor.visit_ty(typ);
visitor.visit_generics(type_parameters)
walk_list!(visitor, visit_attribute, &foreign_item.attrs);
}
+pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
+ // Empty!
+}
+
pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) {
match *bound {
TraitTyParamBound(ref typ, ref modifier) => {
--- /dev/null
+// Copyright 2012-2013 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.
+
+/// Module-level assembly support.
+///
+/// The macro defined here allows you to specify "top-level",
+/// "file-scoped", or "module-level" assembly. These synonyms
+/// all correspond to LLVM's module-level inline assembly instruction.
+///
+/// For example, `global_asm!("some assembly here")` translates to
+/// LLVM's `module asm "some assembly here"`. All of LLVM's caveats
+/// therefore apply.
+
+use syntax::ast;
+use syntax::ext::base;
+use syntax::ext::base::*;
+use syntax::feature_gate;
+use syntax::ptr::P;
+use syntax::symbol::Symbol;
+use syntax_pos::Span;
+use syntax::tokenstream;
+
+use syntax::util::small_vector::SmallVector;
+
+pub const MACRO: &'static str = "global_asm";
+
+pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
+ sp: Span,
+ tts: &[tokenstream::TokenTree]) -> Box<base::MacResult + 'cx> {
+ if !cx.ecfg.enable_global_asm() {
+ feature_gate::emit_feature_err(&cx.parse_sess,
+ MACRO,
+ sp,
+ feature_gate::GateIssue::Language,
+ feature_gate::EXPLAIN_GLOBAL_ASM);
+ return DummyResult::any(sp);
+ }
+
+ let mut p = cx.new_parser_from_tts(tts);
+ let (asm, _) = match expr_to_string(cx,
+ panictry!(p.parse_expr()),
+ "inline assembly must be a string literal") {
+ Some((s, st)) => (s, st),
+ None => return DummyResult::any(sp),
+ };
+
+ MacEager::items(SmallVector::one(P(ast::Item {
+ ident: ast::Ident::with_empty_ctxt(Symbol::intern("")),
+ attrs: Vec::new(),
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ItemKind::GlobalAsm(P(ast::GlobalAsm {
+ asm: asm,
+ ctxt: cx.backtrace(),
+ })),
+ vis: ast::Visibility::Inherited,
+ span: sp,
+ })))
+}
mod env;
mod format;
mod format_foreign;
+mod global_asm;
mod log_syntax;
mod trace_macros;
module_path: expand_mod,
asm: asm::expand_asm,
+ global_asm: global_asm::expand_global_asm,
cfg: cfg::expand_cfg,
concat: concat::expand_syntax_ext,
concat_idents: concat_idents::expand_syntax_ext,
HasSideEffects, IsAlignStack, fromRust(Dialect)));
}
+extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
+ unwrap(M)->appendModuleInlineAsm(StringRef(Asm));
+}
+
typedef DIBuilder *LLVMRustDIBuilderRef;
typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
--- /dev/null
+.global foo
+foo:
+ jmp baz
--- /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.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(global_asm)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// this regex will capture the correct unconditional branch inst.
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+global_asm!(r#"
+ .global foo
+foo:
+ jmp baz
+"#);
+
+extern "C" {
+ fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
--- /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.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(global_asm)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+global_asm!(include_str!("foo.s"));
+
+extern "C" {
+ fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
--- /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.
+
+// ignore-aarch64
+// ignore-aarch64_be
+// ignore-arm
+// ignore-armeb
+// ignore-avr
+// ignore-bpfel
+// ignore-bpfeb
+// ignore-hexagon
+// ignore-mips
+// ignore-mipsel
+// ignore-mips64
+// ignore-mips64el
+// ignore-msp430
+// ignore-powerpc64
+// ignore-powerpc64le
+// ignore-powerpc
+// ignore-r600
+// ignore-amdgcn
+// ignore-sparc
+// ignore-sparcv9
+// ignore-sparcel
+// ignore-s390x
+// ignore-tce
+// ignore-thumb
+// ignore-thumbeb
+// ignore-xcore
+// ignore-nvptx
+// ignore-nvptx64
+// ignore-le32
+// ignore-le64
+// ignore-amdil
+// ignore-amdil64
+// ignore-hsail
+// ignore-hsail64
+// ignore-spir
+// ignore-spir64
+// ignore-kalimba
+// ignore-shave
+// ignore-wasm32
+// ignore-wasm64
+// ignore-emscripten
+// compile-flags: -C no-prepopulate-passes
+
+#![feature(global_asm)]
+#![crate_type = "lib"]
+#[no_std]
+
+// CHECK-LABEL: foo
+// CHECK: module asm
+// CHECK: module asm "{{[[:space:]]+}}jmp baz"
+// any other global_asm will be appended to this first block, so:
+// CHECK-LABEL: bar
+// CHECK: module asm "{{[[:space:]]+}}jmp quux"
+global_asm!(r#"
+ .global foo
+foo:
+ jmp baz
+"#);
+
+extern "C" {
+ fn foo();
+}
+
+// CHECK-LABEL: @baz
+#[no_mangle]
+pub unsafe extern "C" fn baz() {}
+
+// no checks here; this has been appended to the first occurrence
+global_asm!(r#"
+ .global bar
+bar:
+ jmp quux
+"#);
+
+extern "C" {
+ fn bar();
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn quux() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
impl Drop for MyTrait {
//~^ ERROR E0120
// except according to those terms.
pub trait Foo {
+ fn foo() {}
}
impl Foo for isize {
// except according to those terms.
#![feature(optin_builtin_traits)]
+#![feature(overlapping_marker_traits)]
trait MyTrait {}
//~^ ERROR conflicting implementations of trait `std::marker::Send`
unsafe impl<T:'static> Send for TestType<T> {}
-//~^ ERROR conflicting implementations of trait `std::marker::Send`
impl !Send for TestType<i32> {}
+//~^ ERROR conflicting implementations of trait `std::marker::Send`
fn main() {}
#![feature(optin_builtin_traits)]
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
impl MyTrait for .. {}
//~^ ERROR redundant default implementations of trait `MyTrait`
// except according to those terms.
#![feature(optin_builtin_traits)]
+#![feature(overlapping_marker_traits)]
use std::marker::Copy;
unsafe impl Send for &'static [NotSync] {}
//~^ ERROR E0117
-//~| ERROR E0119
fn main() {
}
// Test that you cannot *directly* dispatch on lifetime requirements
-trait MyTrait {}
+trait MyTrait { fn foo() {} }
impl<T> MyTrait for T {}
impl<T: 'static> MyTrait for T {} //~ ERROR E0119
// Seems pretty basic, but then there was issue #24241. :)
trait From<U> {
+ fn foo() {}
}
impl <T> From<T> for T {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {}
+trait Foo { fn foo() {} }
impl<T> Foo for T {}
impl<U> Foo for U {} //~ ERROR conflicting implementations of trait `Foo`:
-trait Bar {}
+trait Bar { fn bar() {} }
impl<T> Bar for (T, u8) {}
impl<T> Bar for (u8, T) {} //~ ERROR conflicting implementations of trait `Bar` for type `(u8, u8)`:
-trait Baz<T> {}
+trait Baz<T> { fn baz() {} }
impl<T> Baz<u8> for T {}
impl<T> Baz<T> for u8 {} //~ ERROR conflicting implementations of trait `Baz<u8>` for type `u8`:
-trait Quux<U, V> {}
+trait Quux<U, V> { fn quux() {} }
impl<T, U, V> Quux<U, V> for T {}
impl<T, U> Quux<U, U> for T {} //~ ERROR conflicting implementations of trait `Quux<_, _>`:
// due to the orphan rules. Therefore, `A::Item` may yet turn out to
// be `i32`.
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
pub trait Bar {
type Output: 'static;
use std::marker::PhantomData;
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
impl <P, T: Foo<P>> Foo<P> for Option<T> {}
use std::marker::PhantomData;
-pub trait Foo<P> {}
+pub trait Foo<P> { fn foo() {} }
pub trait Bar {
type Output: 'static;
struct MyType { x: i32 }
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyFundamentalStruct` is declared fundamental, so we can test that
struct MyType { x: i32 }
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyFundamentalStruct` is declared fundamental, so we can test that
struct MyType { x: i32 }
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
struct MyType { x: i32 }
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// `MyStruct` is not declared fundamental, therefore this would
struct MyType { x: i32 }
-trait MyTrait { }
+trait MyTrait { fn foo() {} }
impl<T: lib::MyCopy> MyTrait for T { }
// Tuples are not fundamental, therefore this would require that
--- /dev/null
+// Copyright 2014 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.
+
+// gate-test-global_asm
+
+global_asm!(""); //~ ERROR `global_asm!` is not stable
+
+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.
+
+use std::fmt::{Debug, Display};
+
+trait MyMarker {}
+
+impl<T: Display> MyMarker for T {}
+impl<T: Debug> MyMarker for T {}
+//~^ ERROR E0119
+
+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.
+
+// Test for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits without items. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`. This test just
+// checks that we don't consider **all** types to be `MyMarker`. See
+// also the companion test in
+// `run-pass/overlap-permitted-for-marker-traits.rs`.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+use std::fmt::{Debug, Display};
+
+trait Marker {}
+
+impl<T: Debug> Marker for T {}
+impl<T: Display> Marker for T {}
+
+fn is_marker<T: Marker>() { }
+
+struct NotDebugOrDisplay;
+
+fn main() {
+ // Debug && Display:
+ is_marker::<i32>();
+
+ // Debug && !Display:
+ is_marker::<Vec<i32>>();
+
+ // !Debug && !Display
+ is_marker::<NotDebugOrDisplay>(); //~ ERROR
+}
#![feature(specialization)]
-trait Foo {}
+trait Foo { fn foo() {} }
impl<T: Clone> Foo for T {}
impl<T> Foo for Vec<T> {} //~ ERROR E0119
-trait Bar {}
+trait Bar { fn bar() {} }
impl<T> Bar for (T, u8) {}
impl<T> Bar for (u8, T) {} //~ ERROR E0119
-trait Baz<U> {}
+trait Baz<U> { fn baz() {} }
impl<T> Baz<T> for u8 {}
impl<T> Baz<u8> for T {} //~ ERROR E0119
-trait Qux {}
+trait Qux { fn qux() {} }
impl<T: Clone> Qux for T {}
impl<T: Eq> Qux for T {} //~ ERROR E0119
--- /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.
+
+#![feature(untagged_unions)]
+#![allow(unused)]
+
+#[allow(unions_with_drop_fields)]
+union U {
+ x: ((Vec<u8>, Vec<u8>), Vec<u8>),
+ y: Box<Vec<u8>>,
+}
+
+unsafe fn parent_sibling_borrow() {
+ let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+ let a = &mut u.x.0;
+ let a = &u.y; //~ ERROR cannot borrow `u.y`
+}
+
+unsafe fn parent_sibling_move() {
+ let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+ let a = u.x.0;
+ let a = u.y; //~ ERROR use of moved value: `u.y`
+}
+
+unsafe fn grandparent_sibling_borrow() {
+ let mut u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+ let a = &mut (u.x.0).0;
+ let a = &u.y; //~ ERROR cannot borrow `u.y`
+}
+
+unsafe fn grandparent_sibling_move() {
+ let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+ let a = (u.x.0).0;
+ let a = u.y; //~ ERROR use of moved value: `u.y`
+}
+
+unsafe fn deref_sibling_borrow() {
+ let mut u = U { y: Box::default() };
+ let a = &mut *u.y;
+ let a = &u.x; //~ ERROR cannot borrow `u` (via `u.x`)
+}
+
+unsafe fn deref_sibling_move() {
+ let u = U { x: ((Vec::new(), Vec::new()), Vec::new()) };
+ let a = *u.y;
+ let a = u.x; //~ ERROR use of moved value: `u.x`
+}
+
+
+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.
+
+#![feature(global_asm)]
+
+#[cfg(target_arch = "x86")]
+global_asm!("");
+
+#[cfg(target_arch = "x86_64")]
+global_asm!("");
+
+#[cfg(target_arch = "arm")]
+global_asm!("");
+
+#[cfg(target_arch = "aarch64")]
+global_asm!("");
+
+#[cfg(target_arch = "mips")]
+global_asm!("");
+
+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.
+
+#![feature(overlapping_marker_traits)]
+#![feature(specialization)]
+
+trait MyMarker {}
+
+impl<T> MyMarker for T {}
+impl<T> MyMarker for Vec<T> {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+ t
+}
+
+fn main() {
+ assert_eq!(1, foo(1));
+ assert_eq!(2.0, foo(2.0));
+ assert_eq!(vec![1], foo(vec![1]));
+}
--- /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.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+// Overlapping negative impls for `MyStruct` are permitted:
+struct MyStruct;
+impl !Send for MyStruct {}
+impl !Send for MyStruct {}
+
+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.
+
+// Tests for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits without items. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`.
+
+#![feature(overlapping_marker_traits)]
+#![feature(optin_builtin_traits)]
+
+use std::fmt::{Debug, Display};
+
+trait MyMarker {}
+
+impl<T: Debug> MyMarker for T {}
+impl<T: Display> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+ t
+}
+
+fn main() {
+ // Debug && Display:
+ assert_eq!(1, foo(1));
+ assert_eq!(2.0, foo(2.0));
+
+ // Debug && !Display:
+ assert_eq!(vec![1], foo(vec![1]));
+}
--- /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.
+
+#![feature(global_asm)]
+#![feature(naked_functions)]
+
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
+global_asm!(r#"
+ .global foo
+ .global _foo
+foo:
+_foo:
+ ret
+"#);
+
+extern {
+ fn foo();
+}
+
+#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
+fn main() { unsafe { foo(); } }
+
+#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
+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.
+
+#![crate_name = "foo"]
+
+// ignore-tidy-linelength
+
+pub trait Expression {
+ type SqlType;
+}
+
+pub trait AsExpression<T> {
+ type Expression: Expression<SqlType = T>;
+ fn as_expression(self) -> Self::Expression;
+}
+
+// @has foo/type.AsExprOf.html
+// @has - '//*[@class="rust typedef"]' 'type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;'
+pub type AsExprOf<Item, Type> = <Item as AsExpression<Type>>::Expression;
--- /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 mod outermod {
+ pub mod innermod {
+ pub use super::*;
+ }
+}
--- /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:issue-40936.rs
+// build-aux-docs
+
+#![crate_name = "foo"]
+
+extern crate issue_40936;
if file.ends_with("btree_set/struct.BTreeSet.html") ||
file.ends_with("collections/struct.BTreeSet.html") ||
file.ends_with("collections/btree_map/struct.BTreeMap.html") ||
- file.ends_with("collections/hash_map/struct.HashMap.html") {
+ file.ends_with("collections/hash_map/struct.HashMap.html") ||
+ file.ends_with("collections/hash_set/struct.HashSet.html") {
return None;
}