mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #33049 - Manishearth:rollup, r=Manishearth
Rollup of 10 pull requests - Successful merges: #31441, #32956, #33003, #33022, #33023, #33032, #33039, #33044, #33045, #33046 - Failed merges:
This commit is contained in:
commit
a626400263
@ -307,7 +307,7 @@ are:
|
||||
[gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here
|
||||
[rif]: http://internals.rust-lang.org
|
||||
[rr]: https://doc.rust-lang.org/book/README.html
|
||||
[tlgba]: http://tomlee.co/2014/04/03/a-more-detailed-tour-of-the-rust-compiler/
|
||||
[tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
|
||||
[ro]: http://www.rustaceans.org/
|
||||
[rctd]: ./COMPILER_TESTS.md
|
||||
[cheatsheet]: http://buildbot.rust-lang.org/homu/
|
||||
|
@ -165,10 +165,15 @@ Rust lets us:
|
||||
```rust
|
||||
use std::mem;
|
||||
|
||||
unsafe {
|
||||
let a = [0u8, 0u8, 0u8, 0u8];
|
||||
|
||||
let b = mem::transmute::<[u8; 4], u32>(a);
|
||||
fn main() {
|
||||
unsafe {
|
||||
let a = [0u8, 1u8, 0u8, 0u8];
|
||||
let b = mem::transmute::<[u8; 4], u32>(a);
|
||||
println!("{}", b); // 256
|
||||
// or, more concisely:
|
||||
let c: u32 = mem::transmute(a);
|
||||
println!("{}", c); // 256
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -31,6 +31,16 @@
|
||||
// Since Rust doesn't actually have dependent types and polymorphic recursion,
|
||||
// we make do with lots of unsafety.
|
||||
|
||||
// A major goal of this module is to avoid complexity by treating the tree as a generic (if
|
||||
// weirdly shaped) container and avoiding dealing with most of the B-Tree invariants. As such,
|
||||
// this module doesn't care whether the entries are sorted, which nodes can be underfull, or
|
||||
// even what underfull means. However, we do rely on a few invariants:
|
||||
//
|
||||
// - Trees must have uniform depth/height. This means that every path down to a leaf from a
|
||||
// given node has exactly the same length.
|
||||
// - A node of length `n` has `n` keys, `n` values, and (in an internal node) `n + 1` edges.
|
||||
// This implies that even an empty internal node has at least one edge.
|
||||
|
||||
use alloc::heap;
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
@ -43,17 +53,43 @@ use boxed::Box;
|
||||
const B: usize = 6;
|
||||
pub const CAPACITY: usize = 2 * B - 1;
|
||||
|
||||
/// The underlying representation of leaf nodes. Note that it is often unsafe to actually store
|
||||
/// these, since only the first `len` keys and values are assumed to be initialized. As such,
|
||||
/// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
|
||||
/// case.
|
||||
///
|
||||
/// See also rust-lang/rfcs#197, which would make this structure significantly more safe by
|
||||
/// avoiding accidentally dropping unused and uninitialized keys and values.
|
||||
struct LeafNode<K, V> {
|
||||
/// The arrays storing the actual data of the node. Only the first `len` elements of each
|
||||
/// array are initialized and valid.
|
||||
keys: [K; CAPACITY],
|
||||
vals: [V; CAPACITY],
|
||||
|
||||
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
|
||||
/// This either points to an actual node or is null.
|
||||
parent: *const InternalNode<K, V>,
|
||||
|
||||
/// This node's index into the parent node's `edges` array.
|
||||
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
|
||||
/// This is only guaranteed to be initialized when `parent` is nonnull.
|
||||
parent_idx: u16,
|
||||
|
||||
/// The number of keys and values this node stores.
|
||||
///
|
||||
/// This is at the end of the node's representation and next to `parent_idx` to encourage
|
||||
/// the compiler to join `len` and `parent_idx` into the same 32-bit word, reducing space
|
||||
/// overhead.
|
||||
len: u16,
|
||||
}
|
||||
|
||||
impl<K, V> LeafNode<K, V> {
|
||||
/// Creates a new `LeafNode`. Unsafe because all nodes should really be hidden behind
|
||||
/// `BoxedNode`, preventing accidental dropping of uninitialized keys and values.
|
||||
unsafe fn new() -> Self {
|
||||
LeafNode {
|
||||
// As a general policy, we leave fields uninitialized if they can be, as this should
|
||||
// be both slightly faster and easier to track in Valgrind.
|
||||
keys: mem::uninitialized(),
|
||||
vals: mem::uninitialized(),
|
||||
parent: ptr::null(),
|
||||
@ -63,15 +99,28 @@ impl<K, V> LeafNode<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
// We use repr(C) so that a pointer to an internal node can be
|
||||
// directly used as a pointer to a leaf node
|
||||
/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
|
||||
/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
|
||||
/// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the
|
||||
/// node, allowing code to act on leaf and internal nodes generically without having to even check
|
||||
/// which of the two a pointer is pointing at. This property is enabled by the use of `repr(C)`.
|
||||
#[repr(C)]
|
||||
struct InternalNode<K, V> {
|
||||
data: LeafNode<K, V>,
|
||||
|
||||
/// The pointers to the children of this node. `len + 1` of these are considered
|
||||
/// initialized and valid.
|
||||
edges: [BoxedNode<K, V>; 2 * B],
|
||||
}
|
||||
|
||||
impl<K, V> InternalNode<K, V> {
|
||||
/// Creates a new `InternalNode`.
|
||||
///
|
||||
/// This is unsafe for two reasons. First, it returns an `InternalNode` by value, risking
|
||||
/// dropping of uninitialized fields. Second, an invariant of internal nodes is that `len + 1`
|
||||
/// edges are initialized and valid, meaning that even when the node is empty (having a
|
||||
/// `len` of 0), there must be one initialized and valid edge. This function does not set up
|
||||
/// such an edge.
|
||||
unsafe fn new() -> Self {
|
||||
InternalNode {
|
||||
data: LeafNode::new(),
|
||||
@ -80,8 +129,12 @@ impl<K, V> InternalNode<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An owned pointer to a node. This basically is either `Box<LeafNode<K, V>>` or
|
||||
/// `Box<InternalNode<K, V>>`. However, it contains no information as to which of the two types
|
||||
/// of nodes is acutally behind the box, and, partially due to this lack of information, has no
|
||||
/// destructor.
|
||||
struct BoxedNode<K, V> {
|
||||
ptr: Unique<LeafNode<K, V>> // we don't know if this points to a leaf node or an internal node
|
||||
ptr: Unique<LeafNode<K, V>>
|
||||
}
|
||||
|
||||
impl<K, V> BoxedNode<K, V> {
|
||||
@ -156,7 +209,7 @@ impl<K, V> Root<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Add a new internal node with a single edge, pointing to the previous root, and make that
|
||||
/// Adds a new internal node with a single edge, pointing to the previous root, and make that
|
||||
/// new node the root. This increases the height by 1 and is the opposite of `pop_level`.
|
||||
pub fn push_level(&mut self)
|
||||
-> NodeRef<marker::Mut, K, V, marker::Internal> {
|
||||
@ -180,7 +233,7 @@ impl<K, V> Root<K, V> {
|
||||
ret
|
||||
}
|
||||
|
||||
/// Remove the root node, using its first child as the new root. This cannot be called when
|
||||
/// Removes the root node, using its first child as the new root. This cannot be called when
|
||||
/// the tree consists only of a leaf node. As it is intended only to be called when the root
|
||||
/// has only one edge, no cleanup is done on any of the other children are elements of the root.
|
||||
/// This decreases the height by 1 and is the opposite of `push_level`.
|
||||
@ -229,6 +282,7 @@ impl<K, V> Root<K, V> {
|
||||
pub struct NodeRef<BorrowType, K, V, Type> {
|
||||
height: usize,
|
||||
node: NonZero<*const LeafNode<K, V>>,
|
||||
// This is null unless the borrow type is `Mut`
|
||||
root: *const Root<K, V>,
|
||||
_marker: PhantomData<(BorrowType, Type)>
|
||||
}
|
||||
@ -268,10 +322,14 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
|
||||
|
||||
impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||
/// Finds the length of the node. This is the number of keys or values. In an
|
||||
/// internal node, the number of edges is `len() + 1`.
|
||||
pub fn len(&self) -> usize {
|
||||
self.as_leaf().len as usize
|
||||
}
|
||||
|
||||
/// Removes any static information about whether this node is a `Leaf` or an
|
||||
/// `Internal` node.
|
||||
pub fn forget_type(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
|
||||
NodeRef {
|
||||
height: self.height,
|
||||
@ -281,6 +339,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Temporarily takes out another, immutable reference to the same node.
|
||||
fn reborrow<'a>(&'a self) -> NodeRef<marker::Immut<'a>, K, V, Type> {
|
||||
NodeRef {
|
||||
height: self.height,
|
||||
@ -304,6 +363,13 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||
self.reborrow().into_slices().1
|
||||
}
|
||||
|
||||
/// Finds the parent of the current node. Returns `Ok(handle)` if the current
|
||||
/// node actually has a parent, where `handle` points to the edge of the parent
|
||||
/// that points to the current node. Returns `Err(self)` if the current node has
|
||||
/// no parent, giving back the original `NodeRef`.
|
||||
///
|
||||
/// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should
|
||||
/// both, upon success, do nothing.
|
||||
pub fn ascend(self) -> Result<
|
||||
Handle<
|
||||
NodeRef<
|
||||
@ -344,6 +410,9 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
|
||||
}
|
||||
|
||||
impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
|
||||
/// Similar to `ascend`, gets a reference to a node's parent node, but also
|
||||
/// deallocate the current node in the process. This is unsafe because the
|
||||
/// current node will still be accessible despite being deallocated.
|
||||
pub unsafe fn deallocate_and_ascend(self) -> Option<
|
||||
Handle<
|
||||
NodeRef<
|
||||
@ -362,6 +431,9 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Leaf> {
|
||||
}
|
||||
|
||||
impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
|
||||
/// Similar to `ascend`, gets a reference to a node's parent node, but also
|
||||
/// deallocate the current node in the process. This is unsafe because the
|
||||
/// current node will still be accessible despite being deallocated.
|
||||
pub unsafe fn deallocate_and_ascend(self) -> Option<
|
||||
Handle<
|
||||
NodeRef<
|
||||
@ -384,6 +456,8 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> {
|
||||
}
|
||||
|
||||
impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||
/// Unsafely asserts to the compiler some static information about whether this
|
||||
/// node is a `Leaf`.
|
||||
unsafe fn cast_unchecked<NewType>(&mut self)
|
||||
-> NodeRef<marker::Mut, K, V, NewType> {
|
||||
|
||||
@ -395,6 +469,16 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Temporarily takes out another, mutable reference to the same node. Beware, as
|
||||
/// this method is very dangerous, doubly so since it may not immediately appear
|
||||
/// dangerous.
|
||||
///
|
||||
/// Because mutable pointers can roam anywhere around the tree and can even (through
|
||||
/// `into_root_mut`) mess with the root of the tree, the result of `reborrow_mut`
|
||||
/// can easily be used to make the original mutable pointer dangling, or, in the case
|
||||
/// of a reborrowed handle, out of bounds.
|
||||
// FIXME(@gereeter) consider adding yet another type parameter to `NodeRef` that restricts
|
||||
// the use of `ascend` and `into_root_mut` on reborrowed pointers, preventing this unsafety.
|
||||
unsafe fn reborrow_mut(&mut self) -> NodeRef<marker::Mut, K, V, Type> {
|
||||
NodeRef {
|
||||
height: self.height,
|
||||
@ -437,6 +521,8 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
|
||||
}
|
||||
|
||||
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||
/// Gets a mutable reference to the root itself. This is useful primarily when the
|
||||
/// height of the tree needs to be adjusted. Never call this on a reborrowed pointer.
|
||||
pub fn into_root_mut(self) -> &'a mut Root<K, V> {
|
||||
unsafe {
|
||||
&mut *(self.root as *mut Root<K, V>)
|
||||
@ -460,6 +546,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
|
||||
}
|
||||
|
||||
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||
/// Adds a key/value pair the end of the node.
|
||||
pub fn push(&mut self, key: K, val: V) {
|
||||
// Necessary for correctness, but this is an internal module
|
||||
debug_assert!(self.len() < CAPACITY);
|
||||
@ -474,6 +561,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||
self.as_leaf_mut().len += 1;
|
||||
}
|
||||
|
||||
/// Adds a key/value pair to the beginning of the node.
|
||||
pub fn push_front(&mut self, key: K, val: V) {
|
||||
// Necessary for correctness, but this is an internal module
|
||||
debug_assert!(self.len() < CAPACITY);
|
||||
@ -488,6 +576,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
|
||||
}
|
||||
|
||||
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
/// Adds a key/value pair and an edge to go to the right of that pair to
|
||||
/// the end of the node.
|
||||
pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||
// Necessary for correctness, but this is an internal module
|
||||
debug_assert!(edge.height == self.height - 1);
|
||||
@ -506,6 +596,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a key/value pair and an edge to go to the left of that pair to
|
||||
/// the beginning of the node.
|
||||
pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||
// Necessary for correctness, but this is an internal module
|
||||
debug_assert!(edge.height == self.height - 1);
|
||||
@ -534,6 +626,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
||||
}
|
||||
|
||||
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
|
||||
/// Removes a key/value pair from the end of this node. If this is an internal node,
|
||||
/// also removes the edge that was to the right of that pair.
|
||||
pub fn pop(&mut self) -> (K, V, Option<Root<K, V>>) {
|
||||
// Necessary for correctness, but this is an internal module
|
||||
debug_assert!(self.len() > 0);
|
||||
@ -558,6 +652,8 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a key/value pair from the beginning of this node. If this is an internal node,
|
||||
/// also removes the edge that was to the left of that pair.
|
||||
pub fn pop_front(&mut self) -> (K, V, Option<Root<K, V>>) {
|
||||
// Necessary for correctness, but this is an internal module
|
||||
debug_assert!(self.len() > 0);
|
||||
@ -597,6 +693,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
|
||||
}
|
||||
|
||||
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
|
||||
/// Checks whether a node is an `Internal` node or a `Leaf` node.
|
||||
pub fn force(self) -> ForceResult<
|
||||
NodeRef<BorrowType, K, V, marker::Leaf>,
|
||||
NodeRef<BorrowType, K, V, marker::Internal>
|
||||
@ -619,6 +716,14 @@ impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a specific key/value pair or edge within a node. The `Node` parameter
|
||||
/// must be a `NodeRef`, while the `Type` can either be `KV` (signifying a handle on a key/value
|
||||
/// pair) or `Edge` (signifying a handle on an edge).
|
||||
///
|
||||
/// Note that even `Leaf` nodes can have `Edge` handles. Instead of representing a pointer to
|
||||
/// a child node, these represent the spaces where child pointers would go between the key/value
|
||||
/// pairs. For example, in a node with length 2, there would be 3 possible edge locations - one
|
||||
/// to the left of the node, one between the two pairs, and one at the right of the node.
|
||||
pub struct Handle<Node, Type> {
|
||||
node: Node,
|
||||
idx: usize,
|
||||
@ -626,6 +731,8 @@ pub struct Handle<Node, Type> {
|
||||
}
|
||||
|
||||
impl<Node: Copy, Type> Copy for Handle<Node, Type> { }
|
||||
// We don't need the full generality of `#[derive(Clone)]`, as the only time `Node` will be
|
||||
// `Clone`able is when it is an immutable reference and therefore `Copy`.
|
||||
impl<Node: Copy, Type> Clone for Handle<Node, Type> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
@ -633,12 +740,14 @@ impl<Node: Copy, Type> Clone for Handle<Node, Type> {
|
||||
}
|
||||
|
||||
impl<Node, Type> Handle<Node, Type> {
|
||||
/// Retrieves the node that contains the edge of key/value pair this handle pointes to.
|
||||
pub fn into_node(self) -> Node {
|
||||
self.node
|
||||
}
|
||||
}
|
||||
|
||||
impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, marker::KV> {
|
||||
/// Creates a new handle to a key/value pair in `node`. `idx` must be less than `node.len()`.
|
||||
pub fn new_kv(node: NodeRef<BorrowType, K, V, NodeType>, idx: usize) -> Self {
|
||||
// Necessary for correctness, but in a private module
|
||||
debug_assert!(idx < node.len());
|
||||
@ -670,6 +779,7 @@ impl<BorrowType, K, V, NodeType, HandleType> PartialEq
|
||||
impl<BorrowType, K, V, NodeType, HandleType>
|
||||
Handle<NodeRef<BorrowType, K, V, NodeType>, HandleType> {
|
||||
|
||||
/// Temporarily takes out another, immutable handle on the same location.
|
||||
pub fn reborrow(&self)
|
||||
-> Handle<NodeRef<marker::Immut, K, V, NodeType>, HandleType> {
|
||||
|
||||
@ -685,6 +795,16 @@ impl<BorrowType, K, V, NodeType, HandleType>
|
||||
impl<'a, K, V, NodeType, HandleType>
|
||||
Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, HandleType> {
|
||||
|
||||
/// Temporarily takes out another, mutable handle on the same location. Beware, as
|
||||
/// this method is very dangerous, doubly so since it may not immediately appear
|
||||
/// dangerous.
|
||||
///
|
||||
/// Because mutable pointers can roam anywhere around the tree and can even (through
|
||||
/// `into_root_mut`) mess with the root of the tree, the result of `reborrow_mut`
|
||||
/// can easily be used to make the original mutable pointer dangling, or, in the case
|
||||
/// of a reborrowed handle, out of bounds.
|
||||
// FIXME(@gereeter) consider adding yet another type parameter to `NodeRef` that restricts
|
||||
// the use of `ascend` and `into_root_mut` on reborrowed pointers, preventing this unsafety.
|
||||
pub unsafe fn reborrow_mut(&mut self)
|
||||
-> Handle<NodeRef<marker::Mut, K, V, NodeType>, HandleType> {
|
||||
|
||||
@ -700,6 +820,8 @@ impl<'a, K, V, NodeType, HandleType>
|
||||
impl<BorrowType, K, V, NodeType>
|
||||
Handle<NodeRef<BorrowType, K, V, NodeType>, marker::Edge> {
|
||||
|
||||
/// Creates a new handle to an edge in `node`. `idx` must be less than or equal to
|
||||
/// `node.len()`.
|
||||
pub fn new_edge(node: NodeRef<BorrowType, K, V, NodeType>, idx: usize) -> Self {
|
||||
// Necessary for correctness, but in a private module
|
||||
debug_assert!(idx <= node.len());
|
||||
@ -733,6 +855,11 @@ impl<BorrowType, K, V, NodeType>
|
||||
}
|
||||
|
||||
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge> {
|
||||
/// Inserts a new key/value pair between the key/value pairs to the right and left of
|
||||
/// this edge. This method assumes that there is enough space in the node for the new
|
||||
/// pair to fit.
|
||||
///
|
||||
/// The returned pointer points to the inserted value.
|
||||
fn insert_fit(&mut self, key: K, val: V) -> *mut V {
|
||||
// Necessary for correctness, but in a private module
|
||||
debug_assert!(self.node.len() < CAPACITY);
|
||||
@ -747,6 +874,10 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts a new key/value pair between the key/value pairs to the right and left of
|
||||
/// this edge. This method splits the node if there isn't enough room.
|
||||
///
|
||||
/// The returned pointer points to the inserted value.
|
||||
pub fn insert(mut self, key: K, val: V)
|
||||
-> (InsertResult<'a, K, V, marker::Leaf>, *mut V) {
|
||||
|
||||
@ -774,6 +905,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
|
||||
}
|
||||
|
||||
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> {
|
||||
/// Fixes the parent pointer and index in the child node below this edge. This is useful
|
||||
/// when the ordering of edges has been changed, such as in the various `insert` methods.
|
||||
fn correct_parent_link(mut self) {
|
||||
let idx = self.idx as u16;
|
||||
let ptr = self.node.as_internal_mut() as *mut _;
|
||||
@ -782,18 +915,24 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
||||
child.as_leaf_mut().parent_idx = idx;
|
||||
}
|
||||
|
||||
/// Unsafely asserts to the compiler some static information about whether the underlying
|
||||
/// node of this handle is a `Leaf`.
|
||||
unsafe fn cast_unchecked<NewType>(&mut self)
|
||||
-> Handle<NodeRef<marker::Mut, K, V, NewType>, marker::Edge> {
|
||||
|
||||
Handle::new_edge(self.node.cast_unchecked(), self.idx)
|
||||
}
|
||||
|
||||
/// Inserts a new key/value pair and an edge that will go to the right of that new pair
|
||||
/// between this edge and the key/value pair to the right of this edge. This method assumes
|
||||
/// that there is enough space in the node for the new pair to fit.
|
||||
fn insert_fit(&mut self, key: K, val: V, edge: Root<K, V>) {
|
||||
// Necessary for correctness, but in an internal module
|
||||
debug_assert!(self.node.len() < CAPACITY);
|
||||
debug_assert!(edge.height == self.node.height - 1);
|
||||
|
||||
unsafe {
|
||||
// This cast is a lie, but it allows us to reuse the key/value insertion logic.
|
||||
self.cast_unchecked::<marker::Leaf>().insert_fit(key, val);
|
||||
|
||||
slice_insert(
|
||||
@ -811,6 +950,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts a new key/value pair and an edge that will go to the right of that new pair
|
||||
/// between this edge and the key/value pair to the right of this edge. This method splits
|
||||
/// the node if there isn't enough room.
|
||||
pub fn insert(mut self, key: K, val: V, edge: Root<K, V>)
|
||||
-> InsertResult<'a, K, V, marker::Internal> {
|
||||
|
||||
@ -843,6 +985,10 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
||||
impl<BorrowType, K, V>
|
||||
Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge> {
|
||||
|
||||
/// Finds the node pointed to by this edge.
|
||||
///
|
||||
/// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should
|
||||
/// both, upon success, do nothing.
|
||||
pub fn descend(self) -> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
|
||||
NodeRef {
|
||||
height: self.node.height - 1,
|
||||
@ -885,6 +1031,13 @@ impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker
|
||||
}
|
||||
|
||||
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV> {
|
||||
/// Splits the underlying node into three parts:
|
||||
///
|
||||
/// - The node is truncated to only contain the key/value pairs to the right of
|
||||
/// this handle.
|
||||
/// - The key and value pointed to by this handle and extracted.
|
||||
/// - All the key/value pairs to the right of this handle are put into a newly
|
||||
/// allocated node.
|
||||
pub fn split(mut self)
|
||||
-> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
|
||||
unsafe {
|
||||
@ -920,6 +1073,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the key/value pair pointed to by this handle, returning the edge between the
|
||||
/// now adjacent key/value pairs to the left and right of this handle.
|
||||
pub fn remove(mut self)
|
||||
-> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
|
||||
unsafe {
|
||||
@ -932,6 +1087,13 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
|
||||
}
|
||||
|
||||
impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::KV> {
|
||||
/// Splits the underlying node into three parts:
|
||||
///
|
||||
/// - The node is truncated to only contain the edges and key/value pairs to the
|
||||
/// right of this handle.
|
||||
/// - The key and value pointed to by this handle and extracted.
|
||||
/// - All the edges and key/value pairs to the right of this handle are put into
|
||||
/// a newly allocated node.
|
||||
pub fn split(mut self)
|
||||
-> (NodeRef<marker::Mut<'a>, K, V, marker::Internal>, K, V, Root<K, V>) {
|
||||
unsafe {
|
||||
@ -979,6 +1141,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether it is valid to call `.merge()`, i.e., whether there is enough room in
|
||||
/// a node to hold the combination of the nodes to the left and right of this handle along
|
||||
/// with the key/value pair at this handle.
|
||||
pub fn can_merge(&self) -> bool {
|
||||
(
|
||||
self.reborrow()
|
||||
@ -993,6 +1158,11 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
||||
) <= CAPACITY
|
||||
}
|
||||
|
||||
/// Combines the node immediately to the left of this handle, the key/value pair pointed
|
||||
/// to by this handle, and the node immediately to the right of this handle into one new
|
||||
/// child of the underlying node, returning an edge referencing that new child.
|
||||
///
|
||||
/// Assumes that this edge `.can_merge()`.
|
||||
pub fn merge(mut self)
|
||||
-> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> {
|
||||
let self1 = unsafe { ptr::read(&self) };
|
||||
@ -1068,6 +1238,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
||||
impl<BorrowType, K, V, HandleType>
|
||||
Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, HandleType> {
|
||||
|
||||
/// Check whether the underlying node is an `Internal` node or a `Leaf` node.
|
||||
pub fn force(self) -> ForceResult<
|
||||
Handle<NodeRef<BorrowType, K, V, marker::Leaf>, HandleType>,
|
||||
Handle<NodeRef<BorrowType, K, V, marker::Internal>, HandleType>
|
||||
|
@ -38,9 +38,23 @@ use slice::SliceExt;
|
||||
/// all standard arithmetic operations on the underlying value are
|
||||
/// intended to have wrapping semantics.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
|
||||
pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Wrapping<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "wrapping_display", since = "1.10.0")]
|
||||
impl<T: fmt::Display> fmt::Display for Wrapping<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
mod wrapping;
|
||||
|
||||
// All these modules are technically private and only exposed for libcoretest:
|
||||
|
@ -119,6 +119,17 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
|
||||
/// `src` is not used before the data is overwritten again (e.g. with `write`,
|
||||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x = 12;
|
||||
/// let y = &x as *const i32;
|
||||
///
|
||||
/// unsafe { println!("{}", std::ptr::read(y)); }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn read<T>(src: *const T) -> T {
|
||||
@ -155,6 +166,21 @@ pub unsafe fn read_and_drop<T>(dest: *mut T) -> T {
|
||||
///
|
||||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let mut x = 0;
|
||||
/// let y = &mut x as *mut i32;
|
||||
/// let z = 12;
|
||||
///
|
||||
/// unsafe {
|
||||
/// std::ptr::write(y, z);
|
||||
/// println!("{}", std::ptr::read(y));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn write<T>(dst: *mut T, src: T) {
|
||||
@ -185,6 +211,17 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
||||
/// `src` is not used before the data is overwritten again (e.g. with `write`,
|
||||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let x = 12;
|
||||
/// let y = &x as *const i32;
|
||||
///
|
||||
/// unsafe { println!("{}", std::ptr::read_volatile(y)); }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "volatile", since = "1.9.0")]
|
||||
pub unsafe fn read_volatile<T>(src: *const T) -> T {
|
||||
@ -217,6 +254,21 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
|
||||
///
|
||||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let mut x = 0;
|
||||
/// let y = &mut x as *mut i32;
|
||||
/// let z = 12;
|
||||
///
|
||||
/// unsafe {
|
||||
/// std::ptr::write_volatile(y, z);
|
||||
/// println!("{}", std::ptr::read_volatile(y));
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "volatile", since = "1.9.0")]
|
||||
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
|
||||
|
@ -12,5 +12,4 @@ crate-type = ["dylib"]
|
||||
log = { path = "../liblog" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
arena = { path = "../libarena" }
|
||||
|
@ -13,7 +13,6 @@
|
||||
//! Here we build the "reduced graph": the graph of the module tree without
|
||||
//! any imports resolved.
|
||||
|
||||
use DefModifiers;
|
||||
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
|
||||
use Module;
|
||||
use Namespace::{self, TypeNS, ValueNS};
|
||||
@ -28,9 +27,9 @@ use rustc::hir::def::*;
|
||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
||||
use rustc::ty::{self, VariantKind};
|
||||
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast::{Name, NodeId};
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
use syntax::parse::token::{special_idents, SELF_KEYWORD_NAME, SUPER_KEYWORD_NAME};
|
||||
use syntax::parse::token::keywords;
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
|
||||
use rustc::hir;
|
||||
@ -53,10 +52,9 @@ impl<'a> ToNameBinding<'a> for (Module<'a>, Span) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToNameBinding<'a> for (Def, Span, DefModifiers, ty::Visibility) {
|
||||
impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
let kind = NameBindingKind::Def(self.0);
|
||||
NameBinding { modifiers: self.2, kind: kind, span: Some(self.1), vis: self.3 }
|
||||
NameBinding { kind: NameBindingKind::Def(self.0), span: Some(self.1), vis: self.2 }
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,12 +98,42 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
block.stmts.iter().any(is_item)
|
||||
}
|
||||
|
||||
fn sanity_check_import(&self, view_path: &hir::ViewPath, id: NodeId) {
|
||||
let path = match view_path.node {
|
||||
ViewPathSimple(_, ref path) |
|
||||
ViewPathGlob (ref path) |
|
||||
ViewPathList(ref path, _) => path
|
||||
};
|
||||
|
||||
// Check for type parameters
|
||||
let found_param = path.segments.iter().any(|segment| {
|
||||
!segment.parameters.types().is_empty() ||
|
||||
!segment.parameters.lifetimes().is_empty() ||
|
||||
!segment.parameters.bindings().is_empty()
|
||||
});
|
||||
if found_param {
|
||||
self.session.span_err(path.span,
|
||||
"type or lifetime parameter is found in import path");
|
||||
}
|
||||
|
||||
// Checking for special identifiers in path
|
||||
// prevent `self` or `super` at beginning of global path
|
||||
if path.global && path.segments.len() > 0 {
|
||||
let first = path.segments[0].identifier.name;
|
||||
if first == keywords::Super.to_name() || first == keywords::SelfValue.to_name() {
|
||||
self.session.add_lint(
|
||||
lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH, id, path.span,
|
||||
format!("expected identifier, found keyword `{}`", first)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs the reduced graph for one item.
|
||||
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
|
||||
let parent = *parent_ref;
|
||||
let name = item.name;
|
||||
let sp = item.span;
|
||||
let modifiers = DefModifiers::IMPORTABLE;
|
||||
self.current_module = parent;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
|
||||
@ -114,10 +142,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
// Extract and intern the module part of the path. For
|
||||
// globs and lists, the path is found directly in the AST;
|
||||
// for simple paths we have to munge the path a little.
|
||||
let is_global;
|
||||
let module_path: Vec<Name> = match view_path.node {
|
||||
ViewPathSimple(_, ref full_path) => {
|
||||
is_global = full_path.global;
|
||||
full_path.segments
|
||||
.split_last()
|
||||
.unwrap()
|
||||
@ -129,7 +155,6 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
|
||||
ViewPathGlob(ref module_ident_path) |
|
||||
ViewPathList(ref module_ident_path, _) => {
|
||||
is_global = module_ident_path.global;
|
||||
module_ident_path.segments
|
||||
.iter()
|
||||
.map(|seg| seg.identifier.name)
|
||||
@ -137,22 +162,10 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
// Checking for special identifiers in path
|
||||
// prevent `self` or `super` at beginning of global path
|
||||
if is_global && (module_path.first() == Some(&SELF_KEYWORD_NAME) ||
|
||||
module_path.first() == Some(&SUPER_KEYWORD_NAME)) {
|
||||
self.session.add_lint(
|
||||
lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
|
||||
item.id,
|
||||
item.span,
|
||||
format!("expected identifier, found keyword `{}`",
|
||||
module_path.first().unwrap().as_str()));
|
||||
}
|
||||
self.sanity_check_import(view_path, item.id);
|
||||
|
||||
// Build up the import directives.
|
||||
let is_prelude = item.attrs.iter().any(|attr| {
|
||||
attr.name() == special_idents::prelude_import.name.as_str()
|
||||
});
|
||||
let is_prelude = item.attrs.iter().any(|attr| attr.name() == "prelude_import");
|
||||
|
||||
match view_path.node {
|
||||
ViewPathSimple(binding, ref full_path) => {
|
||||
@ -268,21 +281,21 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
ItemStatic(_, m, _) => {
|
||||
let mutbl = m == hir::MutMutable;
|
||||
let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
|
||||
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||
self.define(parent, name, ValueNS, (def, sp, vis));
|
||||
}
|
||||
ItemConst(_, _) => {
|
||||
let def = Def::Const(self.ast_map.local_def_id(item.id));
|
||||
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||
self.define(parent, name, ValueNS, (def, sp, vis));
|
||||
}
|
||||
ItemFn(_, _, _, _, _, _) => {
|
||||
let def = Def::Fn(self.ast_map.local_def_id(item.id));
|
||||
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||
self.define(parent, name, ValueNS, (def, sp, vis));
|
||||
}
|
||||
|
||||
// These items live in the type namespace.
|
||||
ItemTy(..) => {
|
||||
let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, sp, modifiers, vis));
|
||||
self.define(parent, name, TypeNS, (def, sp, vis));
|
||||
}
|
||||
|
||||
ItemEnum(ref enum_definition, _) => {
|
||||
@ -301,13 +314,13 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
ItemStruct(ref struct_def, _) => {
|
||||
// Define a name in the type namespace.
|
||||
let def = Def::Struct(self.ast_map.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, sp, modifiers, vis));
|
||||
self.define(parent, name, TypeNS, (def, sp, vis));
|
||||
|
||||
// If this is a newtype or unit-like struct, define a name
|
||||
// in the value namespace as well
|
||||
if !struct_def.is_struct() {
|
||||
let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
|
||||
self.define(parent, name, ValueNS, (def, sp, modifiers, vis));
|
||||
self.define(parent, name, ValueNS, (def, sp, vis));
|
||||
}
|
||||
|
||||
// Record the def ID and fields of this struct.
|
||||
@ -339,8 +352,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
|
||||
};
|
||||
|
||||
let modifiers = DefModifiers::empty(); // NB: not DefModifiers::IMPORTABLE
|
||||
self.define(module_parent, item.name, ns, (def, item.span, modifiers, vis));
|
||||
self.define(module_parent, item.name, ns, (def, item.span, vis));
|
||||
|
||||
self.trait_item_map.insert((item.name, def_id), item_def_id);
|
||||
}
|
||||
@ -363,11 +375,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
|
||||
// Variants are always treated as importable to allow them to be glob used.
|
||||
// All variants are defined in both type and value namespaces as future-proofing.
|
||||
let modifiers = DefModifiers::IMPORTABLE;
|
||||
let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
|
||||
|
||||
self.define(parent, name, ValueNS, (def, variant.span, modifiers, parent.vis));
|
||||
self.define(parent, name, TypeNS, (def, variant.span, modifiers, parent.vis));
|
||||
self.define(parent, name, ValueNS, (def, variant.span, parent.vis));
|
||||
self.define(parent, name, TypeNS, (def, variant.span, parent.vis));
|
||||
}
|
||||
|
||||
/// Constructs the reduced graph for one foreign item.
|
||||
@ -375,7 +385,6 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
foreign_item: &ForeignItem,
|
||||
parent: Module<'b>) {
|
||||
let name = foreign_item.name;
|
||||
let modifiers = DefModifiers::IMPORTABLE;
|
||||
|
||||
let def = match foreign_item.node {
|
||||
ForeignItemFn(..) => {
|
||||
@ -387,7 +396,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
};
|
||||
self.current_module = parent;
|
||||
let vis = self.resolve_visibility(&foreign_item.vis);
|
||||
self.define(parent, name, ValueNS, (def, foreign_item.span, modifiers, vis));
|
||||
self.define(parent, name, ValueNS, (def, foreign_item.span, vis));
|
||||
}
|
||||
|
||||
fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &mut Module<'b>) {
|
||||
@ -422,10 +431,6 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
|
||||
let name = xcdef.name;
|
||||
let vis = if parent.is_trait() { ty::Visibility::Public } else { xcdef.vis };
|
||||
let modifiers = match parent.is_normal() {
|
||||
true => DefModifiers::IMPORTABLE,
|
||||
false => DefModifiers::empty(),
|
||||
};
|
||||
|
||||
match def {
|
||||
Def::Mod(_) | Def::ForeignMod(_) | Def::Enum(..) => {
|
||||
@ -439,9 +444,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
debug!("(building reduced graph for external crate) building variant {}", name);
|
||||
// Variants are always treated as importable to allow them to be glob used.
|
||||
// All variants are defined in both type and value namespaces as future-proofing.
|
||||
let modifiers = DefModifiers::IMPORTABLE;
|
||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers, vis));
|
||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers, vis));
|
||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
|
||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
|
||||
if self.session.cstore.variant_kind(variant_id) == Some(VariantKind::Struct) {
|
||||
// Not adding fields for variants as they are not accessed with a self receiver
|
||||
self.structs.insert(variant_id, Vec::new());
|
||||
@ -454,7 +458,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
Def::Method(..) => {
|
||||
debug!("(building reduced graph for external crate) building value (fn/static) {}",
|
||||
name);
|
||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers, vis));
|
||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
|
||||
}
|
||||
Def::Trait(def_id) => {
|
||||
debug!("(building reduced graph for external crate) building type {}", name);
|
||||
@ -480,16 +484,16 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
|
||||
}
|
||||
Def::TyAlias(..) | Def::AssociatedTy(..) => {
|
||||
debug!("(building reduced graph for external crate) building type {}", name);
|
||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers, vis));
|
||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
|
||||
}
|
||||
Def::Struct(def_id)
|
||||
if self.session.cstore.tuple_struct_definition_if_ctor(def_id).is_none() => {
|
||||
debug!("(building reduced graph for external crate) building type and value for {}",
|
||||
name);
|
||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, modifiers, vis));
|
||||
self.try_define(parent, name, TypeNS, (def, DUMMY_SP, vis));
|
||||
if let Some(ctor_def_id) = self.session.cstore.struct_ctor_def_id(def_id) {
|
||||
let def = Def::Struct(ctor_def_id);
|
||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, modifiers, vis));
|
||||
self.try_define(parent, name, ValueNS, (def, DUMMY_SP, vis));
|
||||
}
|
||||
|
||||
// Record the def ID and fields of this struct.
|
||||
|
@ -29,9 +29,6 @@ extern crate log;
|
||||
extern crate syntax;
|
||||
extern crate arena;
|
||||
#[macro_use]
|
||||
#[no_link]
|
||||
extern crate rustc_bitflags;
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
|
||||
use self::PatternBindingMode::*;
|
||||
@ -915,18 +912,9 @@ impl<'a> fmt::Debug for ModuleS<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug)]
|
||||
flags DefModifiers: u8 {
|
||||
const IMPORTABLE = 1 << 1,
|
||||
const GLOB_IMPORTED = 1 << 3,
|
||||
}
|
||||
}
|
||||
|
||||
// Records a possibly-private value, type, or module definition.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NameBinding<'a> {
|
||||
modifiers: DefModifiers,
|
||||
kind: NameBindingKind<'a>,
|
||||
span: Option<Span>,
|
||||
vis: ty::Visibility,
|
||||
@ -938,7 +926,7 @@ enum NameBindingKind<'a> {
|
||||
Module(Module<'a>),
|
||||
Import {
|
||||
binding: &'a NameBinding<'a>,
|
||||
id: NodeId,
|
||||
directive: &'a ImportDirective<'a>,
|
||||
// Some(error) if using this imported name causes the import to be a privacy error
|
||||
privacy_error: Option<Box<PrivacyError<'a>>>,
|
||||
},
|
||||
@ -950,7 +938,6 @@ struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>);
|
||||
impl<'a> NameBinding<'a> {
|
||||
fn create_from_module(module: Module<'a>, span: Option<Span>) -> Self {
|
||||
NameBinding {
|
||||
modifiers: DefModifiers::IMPORTABLE,
|
||||
kind: NameBindingKind::Module(module),
|
||||
span: span,
|
||||
vis: module.vis,
|
||||
@ -973,10 +960,6 @@ impl<'a> NameBinding<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn defined_with(&self, modifiers: DefModifiers) -> bool {
|
||||
self.modifiers.contains(modifiers)
|
||||
}
|
||||
|
||||
fn is_pseudo_public(&self) -> bool {
|
||||
self.pseudo_vis() == ty::Visibility::Public
|
||||
}
|
||||
@ -1003,6 +986,20 @@ impl<'a> NameBinding<'a> {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_glob_import(&self) -> bool {
|
||||
match self.kind {
|
||||
NameBindingKind::Import { directive, .. } => directive.is_glob(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_importable(&self) -> bool {
|
||||
match self.def().unwrap() {
|
||||
Def::AssociatedConst(..) | Def::Method(..) | Def::AssociatedTy(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Interns the names of the primitive types.
|
||||
@ -1228,12 +1225,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
self.used_crates.insert(krate);
|
||||
}
|
||||
|
||||
let (import_id, privacy_error) = match binding.kind {
|
||||
NameBindingKind::Import { id, ref privacy_error, .. } => (id, privacy_error),
|
||||
let (directive, privacy_error) = match binding.kind {
|
||||
NameBindingKind::Import { directive, ref privacy_error, .. } =>
|
||||
(directive, privacy_error),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
self.used_imports.insert((import_id, ns));
|
||||
self.used_imports.insert((directive.id, ns));
|
||||
if let Some(error) = privacy_error.as_ref() {
|
||||
self.privacy_errors.push((**error).clone());
|
||||
}
|
||||
@ -1241,14 +1239,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
if !self.make_glob_map {
|
||||
return;
|
||||
}
|
||||
if self.glob_map.contains_key(&import_id) {
|
||||
self.glob_map.get_mut(&import_id).unwrap().insert(name);
|
||||
if self.glob_map.contains_key(&directive.id) {
|
||||
self.glob_map.get_mut(&directive.id).unwrap().insert(name);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut new_set = FnvHashSet();
|
||||
new_set.insert(name);
|
||||
self.glob_map.insert(import_id, new_set);
|
||||
self.glob_map.insert(directive.id, new_set);
|
||||
}
|
||||
|
||||
fn get_trait_name(&self, did: DefId) -> Name {
|
||||
@ -2408,7 +2406,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if let Err(false) = self.resolve_path(pat_id, &path, 0, ValueNS) {
|
||||
resolve_error(
|
||||
self,
|
||||
path.span,
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
use self::ImportDirectiveSubclass::*;
|
||||
|
||||
use DefModifiers;
|
||||
use Module;
|
||||
use Namespace::{self, TypeNS, ValueNS};
|
||||
use {NameBinding, NameBindingKind, PrivacyError};
|
||||
@ -59,11 +58,11 @@ impl ImportDirectiveSubclass {
|
||||
/// One import directive.
|
||||
#[derive(Debug,Clone)]
|
||||
pub struct ImportDirective<'a> {
|
||||
pub id: NodeId,
|
||||
module_path: Vec<Name>,
|
||||
target_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
|
||||
subclass: ImportDirectiveSubclass,
|
||||
span: Span,
|
||||
id: NodeId,
|
||||
vis: ty::Visibility, // see note in ImportResolutionPerNamespace about how to use this
|
||||
is_prelude: bool,
|
||||
}
|
||||
@ -71,24 +70,22 @@ pub struct ImportDirective<'a> {
|
||||
impl<'a> ImportDirective<'a> {
|
||||
// Given the binding to which this directive resolves in a particular namespace,
|
||||
// this returns the binding for the name this directive defines in that namespace.
|
||||
fn import(&self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
|
||||
fn import(&'a self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
|
||||
-> NameBinding<'a> {
|
||||
let mut modifiers = DefModifiers::IMPORTABLE;
|
||||
if let GlobImport = self.subclass {
|
||||
modifiers = modifiers | DefModifiers::GLOB_IMPORTED;
|
||||
}
|
||||
|
||||
NameBinding {
|
||||
kind: NameBindingKind::Import {
|
||||
binding: binding,
|
||||
id: self.id,
|
||||
directive: self,
|
||||
privacy_error: privacy_error,
|
||||
},
|
||||
span: Some(self.span),
|
||||
modifiers: modifiers,
|
||||
vis: self.vis,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_glob(&self) -> bool {
|
||||
match self.subclass { ImportDirectiveSubclass::GlobImport => true, _ => false }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@ -141,9 +138,9 @@ impl<'a> SingleImports<'a> {
|
||||
impl<'a> NameResolution<'a> {
|
||||
fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> {
|
||||
if let Some(old_binding) = self.binding {
|
||||
if binding.defined_with(DefModifiers::GLOB_IMPORTED) {
|
||||
if binding.is_glob_import() {
|
||||
self.duplicate_globs.push(binding);
|
||||
} else if old_binding.defined_with(DefModifiers::GLOB_IMPORTED) {
|
||||
} else if old_binding.is_glob_import() {
|
||||
self.duplicate_globs.push(old_binding);
|
||||
self.binding = Some(binding);
|
||||
} else {
|
||||
@ -160,7 +157,7 @@ impl<'a> NameResolution<'a> {
|
||||
fn binding(&self) -> Option<&'a NameBinding<'a>> {
|
||||
self.binding.and_then(|binding| match self.single_imports {
|
||||
SingleImports::None => Some(binding),
|
||||
_ if !binding.defined_with(DefModifiers::GLOB_IMPORTED) => Some(binding),
|
||||
_ if !binding.is_glob_import() => Some(binding),
|
||||
_ => None, // The binding could be shadowed by a single import, so it is not known.
|
||||
})
|
||||
}
|
||||
@ -170,7 +167,7 @@ impl<'a> NameResolution<'a> {
|
||||
fn try_result(&self, ns: Namespace, allow_private_imports: bool)
|
||||
-> Option<ResolveResult<&'a NameBinding<'a>>> {
|
||||
match self.binding {
|
||||
Some(binding) if !binding.defined_with(DefModifiers::GLOB_IMPORTED) =>
|
||||
Some(binding) if !binding.is_glob_import() =>
|
||||
return Some(Success(binding)),
|
||||
_ => {} // Items and single imports are not shadowable
|
||||
};
|
||||
@ -337,7 +334,7 @@ impl<'a> ::ModuleS<'a> {
|
||||
}
|
||||
|
||||
fn define_in_glob_importers(&self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>) {
|
||||
if !binding.defined_with(DefModifiers::IMPORTABLE) || !binding.is_pseudo_public() { return }
|
||||
if !binding.is_importable() || !binding.is_pseudo_public() { return }
|
||||
for &(importer, directive) in self.glob_importers.borrow_mut().iter() {
|
||||
let _ = importer.try_define_child(name, ns, directive.import(binding, None));
|
||||
}
|
||||
@ -410,7 +407,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
// resolution for it so that later resolve stages won't complain.
|
||||
if let SingleImport { target, .. } = e.import_directive.subclass {
|
||||
let dummy_binding = self.resolver.arenas.alloc_name_binding(NameBinding {
|
||||
modifiers: DefModifiers::GLOB_IMPORTED,
|
||||
kind: NameBindingKind::Def(Def::Err),
|
||||
span: None,
|
||||
vis: ty::Visibility::Public,
|
||||
@ -517,7 +513,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
|
||||
determined.set(true);
|
||||
if let Success(binding) = *result {
|
||||
if !binding.defined_with(DefModifiers::IMPORTABLE) {
|
||||
if !binding.is_importable() {
|
||||
let msg = format!("`{}` is not directly importable", target);
|
||||
span_err!(self.resolver.session, directive.span, E0253, "{}", &msg);
|
||||
}
|
||||
@ -662,7 +658,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
resolution.borrow().binding().map(|binding| (*name, binding))
|
||||
}).collect::<Vec<_>>();
|
||||
for ((name, ns), binding) in bindings {
|
||||
if binding.defined_with(DefModifiers::IMPORTABLE) && binding.is_pseudo_public() {
|
||||
if binding.is_importable() && binding.is_pseudo_public() {
|
||||
let _ = module_.try_define_child(name, ns, directive.import(binding, None));
|
||||
}
|
||||
}
|
||||
@ -705,14 +701,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if let NameBindingKind::Import { binding: orig_binding, id, .. } = binding.kind {
|
||||
if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
|
||||
if ns == TypeNS && orig_binding.is_variant() &&
|
||||
!orig_binding.vis.is_at_least(binding.vis, &self.resolver.ast_map) {
|
||||
let msg = format!("variant `{}` is private, and cannot be reexported \
|
||||
(error E0364), consider declaring its enum as `pub`",
|
||||
name);
|
||||
let lint = lint::builtin::PRIVATE_IN_PUBLIC;
|
||||
self.resolver.session.add_lint(lint, id, binding.span.unwrap(), msg);
|
||||
self.resolver.session.add_lint(lint, directive.id, binding.span.unwrap(), msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2717,7 +2717,7 @@ Rust does not currently support this. A simple example that causes this error:
|
||||
|
||||
```compile_fail
|
||||
fn main() {
|
||||
let _: Box<std::io::Read+std::io::Write>;
|
||||
let _: Box<std::io::Read + std::io::Write>;
|
||||
}
|
||||
```
|
||||
|
||||
@ -2727,7 +2727,7 @@ following compiles correctly:
|
||||
|
||||
```
|
||||
fn main() {
|
||||
let _: Box<std::io::Read+Copy+Sync>;
|
||||
let _: Box<std::io::Read + Send + Sync>;
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
@ -1030,7 +1030,7 @@ impl f32 {
|
||||
/// let abs_difference_1 = (f.1 - x.cos()).abs();
|
||||
///
|
||||
/// assert!(abs_difference_0 <= f32::EPSILON);
|
||||
/// assert!(abs_difference_0 <= f32::EPSILON);
|
||||
/// assert!(abs_difference_1 <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -903,7 +903,7 @@ impl f64 {
|
||||
/// let abs_difference_1 = (f.1 - x.cos()).abs();
|
||||
///
|
||||
/// assert!(abs_difference_0 < 1e-10);
|
||||
/// assert!(abs_difference_0 < 1e-10);
|
||||
/// assert!(abs_difference_1 < 1e-10);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -81,6 +81,8 @@ type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute> >);
|
||||
pub enum PathParsingMode {
|
||||
/// A path with no type parameters; e.g. `foo::bar::Baz`
|
||||
NoTypesAllowed,
|
||||
/// Same as `NoTypesAllowed`, but may end with `::{` or `::*`, which are left unparsed
|
||||
ImportPrefix,
|
||||
/// A path with a lifetime and type parameters, with no double colons
|
||||
/// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
|
||||
LifetimeAndTypesWithoutColons,
|
||||
@ -591,20 +593,6 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_path_list_item(&mut self) -> PResult<'a, ast::PathListItem> {
|
||||
let lo = self.span.lo;
|
||||
let node = if self.eat_keyword(keywords::SelfValue) {
|
||||
let rename = self.parse_rename()?;
|
||||
ast::PathListItemKind::Mod { id: ast::DUMMY_NODE_ID, rename: rename }
|
||||
} else {
|
||||
let ident = self.parse_ident()?;
|
||||
let rename = self.parse_rename()?;
|
||||
ast::PathListItemKind::Ident { name: ident, rename: rename, id: ast::DUMMY_NODE_ID }
|
||||
};
|
||||
let hi = self.last_span.hi;
|
||||
Ok(spanned(lo, hi, node))
|
||||
}
|
||||
|
||||
/// Check if the next token is `tok`, and return `true` if so.
|
||||
///
|
||||
/// This method will automatically add `tok` to `expected_tokens` if `tok` is not
|
||||
@ -1763,8 +1751,8 @@ impl<'a> Parser<'a> {
|
||||
LifetimeAndTypesWithColons => {
|
||||
self.parse_path_segments_with_colons()?
|
||||
}
|
||||
NoTypesAllowed => {
|
||||
self.parse_path_segments_without_types()?
|
||||
NoTypesAllowed | ImportPrefix => {
|
||||
self.parse_path_segments_without_types(mode == ImportPrefix)?
|
||||
}
|
||||
};
|
||||
path.segments.extend(segments);
|
||||
@ -1801,8 +1789,8 @@ impl<'a> Parser<'a> {
|
||||
LifetimeAndTypesWithColons => {
|
||||
self.parse_path_segments_with_colons()?
|
||||
}
|
||||
NoTypesAllowed => {
|
||||
self.parse_path_segments_without_types()?
|
||||
NoTypesAllowed | ImportPrefix => {
|
||||
self.parse_path_segments_without_types(mode == ImportPrefix)?
|
||||
}
|
||||
};
|
||||
|
||||
@ -1920,7 +1908,8 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Examples:
|
||||
/// - `a::b::c`
|
||||
pub fn parse_path_segments_without_types(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
|
||||
pub fn parse_path_segments_without_types(&mut self, import_prefix: bool)
|
||||
-> PResult<'a, Vec<ast::PathSegment>> {
|
||||
let mut segments = Vec::new();
|
||||
loop {
|
||||
// First, parse an identifier.
|
||||
@ -1932,9 +1921,11 @@ impl<'a> Parser<'a> {
|
||||
parameters: ast::PathParameters::none()
|
||||
});
|
||||
|
||||
// If we do not see a `::`, stop.
|
||||
if !self.eat(&token::ModSep) {
|
||||
// If we do not see a `::` or see `::{`/`::*`, stop.
|
||||
if !self.check(&token::ModSep) || import_prefix && self.is_import_coupler() {
|
||||
return Ok(segments);
|
||||
} else {
|
||||
self.bump();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6127,106 +6118,67 @@ impl<'a> Parser<'a> {
|
||||
self.parse_item_(attrs, true, false)
|
||||
}
|
||||
|
||||
fn parse_path_list_items(&mut self) -> PResult<'a, Vec<ast::PathListItem>> {
|
||||
self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
|
||||
&token::CloseDelim(token::Brace),
|
||||
SeqSep::trailing_allowed(token::Comma), |this| {
|
||||
let lo = this.span.lo;
|
||||
let node = if this.eat_keyword(keywords::SelfValue) {
|
||||
let rename = this.parse_rename()?;
|
||||
ast::PathListItemKind::Mod { id: ast::DUMMY_NODE_ID, rename: rename }
|
||||
} else {
|
||||
let ident = this.parse_ident()?;
|
||||
let rename = this.parse_rename()?;
|
||||
ast::PathListItemKind::Ident { name: ident, rename: rename, id: ast::DUMMY_NODE_ID }
|
||||
};
|
||||
let hi = this.last_span.hi;
|
||||
Ok(spanned(lo, hi, node))
|
||||
})
|
||||
}
|
||||
|
||||
/// Matches view_path : MOD? non_global_path as IDENT
|
||||
/// | MOD? non_global_path MOD_SEP LBRACE RBRACE
|
||||
/// | MOD? non_global_path MOD_SEP LBRACE ident_seq RBRACE
|
||||
/// | MOD? non_global_path MOD_SEP STAR
|
||||
/// | MOD? non_global_path
|
||||
/// `::{` or `::*`
|
||||
fn is_import_coupler(&mut self) -> bool {
|
||||
self.check(&token::ModSep) &&
|
||||
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
|
||||
*t == token::BinOp(token::Star))
|
||||
}
|
||||
|
||||
/// Matches ViewPath:
|
||||
/// MOD_SEP? non_global_path
|
||||
/// MOD_SEP? non_global_path as IDENT
|
||||
/// MOD_SEP? non_global_path MOD_SEP STAR
|
||||
/// MOD_SEP? non_global_path MOD_SEP LBRACE item_seq RBRACE
|
||||
/// MOD_SEP? LBRACE item_seq RBRACE
|
||||
fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
|
||||
let lo = self.span.lo;
|
||||
|
||||
// Allow a leading :: because the paths are absolute either way.
|
||||
// This occurs with "use $crate::..." in macros.
|
||||
let is_global = self.eat(&token::ModSep);
|
||||
|
||||
if self.check(&token::OpenDelim(token::Brace)) {
|
||||
// use {foo,bar}
|
||||
let idents = self.parse_unspanned_seq(
|
||||
&token::OpenDelim(token::Brace),
|
||||
&token::CloseDelim(token::Brace),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| p.parse_path_list_item())?;
|
||||
let path = ast::Path {
|
||||
if self.check(&token::OpenDelim(token::Brace)) || self.is_import_coupler() {
|
||||
// `{foo, bar}` or `::{foo, bar}`
|
||||
let prefix = ast::Path {
|
||||
global: self.eat(&token::ModSep),
|
||||
segments: Vec::new(),
|
||||
span: mk_sp(lo, self.span.hi),
|
||||
global: is_global,
|
||||
segments: Vec::new()
|
||||
};
|
||||
return Ok(P(spanned(lo, self.span.hi, ViewPathList(path, idents))));
|
||||
}
|
||||
|
||||
let first_ident = self.parse_ident()?;
|
||||
let mut path = vec!(first_ident);
|
||||
if let token::ModSep = self.token {
|
||||
// foo::bar or foo::{a,b,c} or foo::*
|
||||
while self.check(&token::ModSep) {
|
||||
let items = self.parse_path_list_items()?;
|
||||
Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items))))
|
||||
} else {
|
||||
let prefix = self.parse_path(ImportPrefix)?;
|
||||
if self.is_import_coupler() {
|
||||
// `foo::bar::{a, b}` or `foo::bar::*`
|
||||
self.bump();
|
||||
|
||||
match self.token {
|
||||
token::Ident(..) => {
|
||||
let ident = self.parse_ident()?;
|
||||
path.push(ident);
|
||||
}
|
||||
|
||||
// foo::bar::{a,b,c}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
let idents = self.parse_unspanned_seq(
|
||||
&token::OpenDelim(token::Brace),
|
||||
&token::CloseDelim(token::Brace),
|
||||
SeqSep::trailing_allowed(token::Comma),
|
||||
|p| p.parse_path_list_item()
|
||||
)?;
|
||||
let path = ast::Path {
|
||||
span: mk_sp(lo, self.span.hi),
|
||||
global: is_global,
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
return Ok(P(spanned(lo, self.span.hi, ViewPathList(path, idents))));
|
||||
}
|
||||
|
||||
// foo::bar::*
|
||||
token::BinOp(token::Star) => {
|
||||
if self.check(&token::BinOp(token::Star)) {
|
||||
self.bump();
|
||||
let path = ast::Path {
|
||||
span: mk_sp(lo, self.span.hi),
|
||||
global: is_global,
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
return Ok(P(spanned(lo, self.span.hi, ViewPathGlob(path))));
|
||||
}
|
||||
|
||||
// fall-through for case foo::bar::;
|
||||
token::Semi => {
|
||||
self.span_err(self.span, "expected identifier or `{` or `*`, found `;`");
|
||||
}
|
||||
|
||||
_ => break
|
||||
Ok(P(spanned(lo, self.span.hi, ViewPathGlob(prefix))))
|
||||
} else {
|
||||
let items = self.parse_path_list_items()?;
|
||||
Ok(P(spanned(lo, self.span.hi, ViewPathList(prefix, items))))
|
||||
}
|
||||
} else {
|
||||
// `foo::bar` or `foo::bar as baz`
|
||||
let rename = self.parse_rename()?.
|
||||
unwrap_or(prefix.segments.last().unwrap().identifier);
|
||||
Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename, prefix))))
|
||||
}
|
||||
}
|
||||
let mut rename_to = path[path.len() - 1];
|
||||
let path = ast::Path {
|
||||
span: mk_sp(lo, self.last_span.hi),
|
||||
global: is_global,
|
||||
segments: path.into_iter().map(|identifier| {
|
||||
ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect()
|
||||
};
|
||||
rename_to = self.parse_rename()?.unwrap_or(rename_to);
|
||||
Ok(P(spanned(lo, self.last_span.hi, ViewPathSimple(rename_to, path))))
|
||||
}
|
||||
|
||||
fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> {
|
||||
|
26
src/test/compile-fail/import-prefix-macro-1.rs
Normal file
26
src/test/compile-fail/import-prefix-macro-1.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod a {
|
||||
pub mod b {
|
||||
pub mod c {
|
||||
pub struct S;
|
||||
pub struct Z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! import {
|
||||
($p: path) => (use $p {S, Z}); //~ERROR expected one of `::`, `;`, or `as`, found `{`
|
||||
}
|
||||
|
||||
import! { a::b::c }
|
||||
|
||||
fn main() {}
|
26
src/test/compile-fail/import-prefix-macro-2.rs
Normal file
26
src/test/compile-fail/import-prefix-macro-2.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod a {
|
||||
pub mod b {
|
||||
pub mod c {
|
||||
pub struct S;
|
||||
pub struct Z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! import {
|
||||
($p: path) => (use ::$p {S, Z}); //~ERROR expected identifier, found `a::b::c`
|
||||
}
|
||||
|
||||
import! { a::b::c }
|
||||
|
||||
fn main() {}
|
25
src/test/compile-fail/import-ty-params.rs
Normal file
25
src/test/compile-fail/import-ty-params.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod a {
|
||||
pub mod b {
|
||||
pub mod c {
|
||||
pub struct S<T>(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! import {
|
||||
($p: path) => (use $p;);
|
||||
}
|
||||
|
||||
import! { a::b::c::S<u8> } //~ERROR type or lifetime parameter is found in import path
|
||||
|
||||
fn main() {}
|
@ -42,4 +42,8 @@ fn main() {
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `char`
|
||||
//~| found `bool`
|
||||
|
||||
match () {
|
||||
E::V => {} //~ ERROR failed to resolve. Use of undeclared type or module `E`
|
||||
}
|
||||
}
|
||||
|
13
src/test/compile-fail/self_type_keyword-2.rs
Normal file
13
src/test/compile-fail/self_type_keyword-2.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2015 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 self::Self as Foo; //~ ERROR unresolved import `self::Self`
|
||||
|
||||
pub fn main() {}
|
@ -39,9 +39,6 @@ pub fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
use self::Self as Foo;
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
|
||||
use std::option::Option as Self;
|
||||
//~^ ERROR expected identifier, found keyword `Self`
|
||||
|
||||
|
@ -10,4 +10,4 @@
|
||||
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
use std::any::; //~ ERROR expected identifier or `{` or `*`, found `;`
|
||||
use std::any::; //~ ERROR expected identifier, found `;`
|
||||
|
35
src/test/run-pass/import-prefix-macro.rs
Normal file
35
src/test/run-pass/import-prefix-macro.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod a {
|
||||
pub mod b {
|
||||
pub mod c {
|
||||
pub struct S;
|
||||
pub struct Z;
|
||||
}
|
||||
pub struct W;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! import {
|
||||
(1 $p: path) => (use $p;);
|
||||
(2 $p: path) => (use $p::{Z};);
|
||||
(3 $p: path) => (use $p::*;);
|
||||
}
|
||||
|
||||
import! { 1 a::b::c::S }
|
||||
import! { 2 a::b::c }
|
||||
import! { 3 a::b }
|
||||
|
||||
fn main() {
|
||||
let s = S;
|
||||
let z = Z;
|
||||
let w = W;
|
||||
}
|
Loading…
Reference in New Issue
Block a user