1
Fork 0

Auto merge of #70205 - Centril:rollup-0jq9k4s, r=Centril

Rollup of 16 pull requests

Successful merges:

 - #65097 (Make std::sync::Arc compatible with ThreadSanitizer)
 - #69033 (Use generator resume arguments in the async/await lowering)
 - #69997 (add `Option::{zip,zip_with}` methods under "option_zip" gate)
 - #70038 (Remove the call that makes miri fail)
 - #70058 (can_begin_literal_maybe_minus: `true` on `"-"? lit` NTs.)
 - #70111 (BTreeMap: remove shared root)
 - #70139 (add delay_span_bug to TransmuteSizeDiff, just to be sure)
 - #70165 (Remove the erase regions MIR transform)
 - #70166 (Derive PartialEq, Eq and Hash for RangeInclusive)
 - #70176 (Add tests for #58319 and #65131)
 - #70177 (Fix oudated comment for NamedRegionMap)
 - #70184 (expand_include: set `.directory` to dir of included file.)
 - #70187 (more clippy fixes)
 - #70188 (Clean up E0439 explanation)
 - #70189 (Abi::is_signed: assert that we are a Scalar)
 - #70194 (#[must_use] on split_off())

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-03-21 04:34:04 +00:00
commit 5f13820478
136 changed files with 1479 additions and 644 deletions

View file

@ -370,12 +370,17 @@ class RustStdBTreeSetPrinter(object):
("(len: %i)" % self.__val.get_wrapped_value()['map']['length'])) ("(len: %i)" % self.__val.get_wrapped_value()['map']['length']))
def children(self): def children(self):
root = self.__val.get_wrapped_value()['map']['root'] prev_idx = None
node_ptr = root['node'] innermap = GdbValue(self.__val.get_wrapped_value()['map'])
i = 0 if innermap.get_wrapped_value()['length'] > 0:
for child in children_of_node(node_ptr, root['height'], False): root = GdbValue(innermap.get_wrapped_value()['root'])
yield (str(i), child) type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1]
i = i + 1 root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
node_ptr = root['node']
i = 0
for child in children_of_node(node_ptr, root['height'], False):
yield (str(i), child)
i = i + 1
class RustStdBTreeMapPrinter(object): class RustStdBTreeMapPrinter(object):
@ -391,13 +396,16 @@ class RustStdBTreeMapPrinter(object):
("(len: %i)" % self.__val.get_wrapped_value()['length'])) ("(len: %i)" % self.__val.get_wrapped_value()['length']))
def children(self): def children(self):
root = self.__val.get_wrapped_value()['root'] if self.__val.get_wrapped_value()['length'] > 0:
node_ptr = root['node'] root = GdbValue(self.__val.get_wrapped_value()['root'])
i = 0 type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1]
for child in children_of_node(node_ptr, root['height'], True): root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
yield (str(i), child[0]) node_ptr = root['node']
yield (str(i), child[1]) i = 0
i = i + 1 for child in children_of_node(node_ptr, root['height'], True):
yield (str(i), child[0])
yield (str(i), child[1])
i = i + 1
class RustStdStringPrinter(object): class RustStdStringPrinter(object):

View file

@ -122,7 +122,7 @@ use UnderflowResult::*;
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct BTreeMap<K, V> { pub struct BTreeMap<K, V> {
root: node::Root<K, V>, root: Option<node::Root<K, V>>,
length: usize, length: usize,
} }
@ -147,10 +147,11 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
{ {
match node.force() { match node.force() {
Leaf(leaf) => { Leaf(leaf) => {
let mut out_tree = BTreeMap { root: node::Root::new_leaf(), length: 0 }; let mut out_tree = BTreeMap { root: Some(node::Root::new_leaf()), length: 0 };
{ {
let mut out_node = match out_tree.root.as_mut().force() { let root = out_tree.root.as_mut().unwrap();
let mut out_node = match root.as_mut().force() {
Leaf(leaf) => leaf, Leaf(leaf) => leaf,
Internal(_) => unreachable!(), Internal(_) => unreachable!(),
}; };
@ -169,9 +170,14 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
} }
Internal(internal) => { Internal(internal) => {
let mut out_tree = clone_subtree(internal.first_edge().descend()); let mut out_tree = clone_subtree(internal.first_edge().descend());
out_tree.ensure_root_is_owned();
{ {
let mut out_node = out_tree.root.push_level(); // Ideally we'd use the return of ensure_root_is_owned
// instead of re-unwrapping here but unfortunately that
// borrows all of out_tree and we need access to the
// length below.
let mut out_node = out_tree.root.as_mut().unwrap().push_level();
let mut in_edge = internal.first_edge(); let mut in_edge = internal.first_edge();
while let Ok(kv) = in_edge.right_kv() { while let Ok(kv) = in_edge.right_kv() {
let (k, v) = kv.into_kv(); let (k, v) = kv.into_kv();
@ -190,7 +196,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
(root, length) (root, length)
}; };
out_node.push(k, v, subroot); out_node.push(k, v, subroot.unwrap_or_else(|| node::Root::new_leaf()));
out_tree.length += 1 + sublength; out_tree.length += 1 + sublength;
} }
} }
@ -203,9 +209,9 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
if self.is_empty() { if self.is_empty() {
// Ideally we'd call `BTreeMap::new` here, but that has the `K: // Ideally we'd call `BTreeMap::new` here, but that has the `K:
// Ord` constraint, which this method lacks. // Ord` constraint, which this method lacks.
BTreeMap { root: node::Root::shared_empty_root(), length: 0 } BTreeMap { root: None, length: 0 }
} else { } else {
clone_subtree(self.root.as_ref()) clone_subtree(self.root.as_ref().unwrap().as_ref())
} }
} }
@ -271,14 +277,14 @@ where
type Key = K; type Key = K;
fn get(&self, key: &Q) -> Option<&K> { fn get(&self, key: &Q) -> Option<&K> {
match search::search_tree(self.root.as_ref(), key) { match search::search_tree(self.root.as_ref()?.as_ref(), key) {
Found(handle) => Some(handle.into_kv().0), Found(handle) => Some(handle.into_kv().0),
GoDown(_) => None, GoDown(_) => None,
} }
} }
fn take(&mut self, key: &Q) -> Option<K> { fn take(&mut self, key: &Q) -> Option<K> {
match search::search_tree(self.root.as_mut(), key) { match search::search_tree(self.root.as_mut()?.as_mut(), key) {
Found(handle) => Some( Found(handle) => Some(
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData } OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
.remove_kv() .remove_kv()
@ -290,7 +296,7 @@ where
fn replace(&mut self, key: K) -> Option<K> { fn replace(&mut self, key: K) -> Option<K> {
self.ensure_root_is_owned(); self.ensure_root_is_owned();
match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut(), &key) { match search::search_tree::<marker::Mut<'_>, K, (), K>(self.root.as_mut()?.as_mut(), &key) {
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
GoDown(handle) => { GoDown(handle) => {
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData } VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
@ -344,15 +350,18 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
/// [`BTreeMap`]: struct.BTreeMap.html /// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<K, V> { pub struct IntoIter<K, V> {
front: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>, front: Option<Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>>,
back: Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>, back: Option<Handle<NodeRef<marker::Owned, K, V, marker::Leaf>, marker::Edge>>,
length: usize, length: usize,
} }
#[stable(feature = "collection_debug", since = "1.17.0")] #[stable(feature = "collection_debug", since = "1.17.0")]
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> { impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IntoIter<K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let range = Range { front: self.front.reborrow(), back: self.back.reborrow() }; let range = Range {
front: self.front.as_ref().map(|f| f.reborrow()),
back: self.back.as_ref().map(|b| b.reborrow()),
};
f.debug_list().entries(range).finish() f.debug_list().entries(range).finish()
} }
} }
@ -417,8 +426,8 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> {
/// [`BTreeMap`]: struct.BTreeMap.html /// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "btree_range", since = "1.17.0")] #[stable(feature = "btree_range", since = "1.17.0")]
pub struct Range<'a, K: 'a, V: 'a> { pub struct Range<'a, K: 'a, V: 'a> {
front: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>, front: Option<Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>>,
back: Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>, back: Option<Handle<NodeRef<marker::Immut<'a>, K, V, marker::Leaf>, marker::Edge>>,
} }
#[stable(feature = "collection_debug", since = "1.17.0")] #[stable(feature = "collection_debug", since = "1.17.0")]
@ -437,8 +446,8 @@ impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Range<'_, K, V> {
/// [`BTreeMap`]: struct.BTreeMap.html /// [`BTreeMap`]: struct.BTreeMap.html
#[stable(feature = "btree_range", since = "1.17.0")] #[stable(feature = "btree_range", since = "1.17.0")]
pub struct RangeMut<'a, K: 'a, V: 'a> { pub struct RangeMut<'a, K: 'a, V: 'a> {
front: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, front: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
back: Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, back: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
// Be invariant in `K` and `V` // Be invariant in `K` and `V`
_marker: PhantomData<&'a mut (K, V)>, _marker: PhantomData<&'a mut (K, V)>,
@ -447,7 +456,10 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
#[stable(feature = "collection_debug", since = "1.17.0")] #[stable(feature = "collection_debug", since = "1.17.0")]
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> { impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RangeMut<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let range = Range { front: self.front.reborrow(), back: self.back.reborrow() }; let range = Range {
front: self.front.as_ref().map(|f| f.reborrow()),
back: self.back.as_ref().map(|b| b.reborrow()),
};
f.debug_list().entries(range).finish() f.debug_list().entries(range).finish()
} }
} }
@ -544,7 +556,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> BTreeMap<K, V> { pub fn new() -> BTreeMap<K, V> {
BTreeMap { root: node::Root::shared_empty_root(), length: 0 } BTreeMap { root: None, length: 0 }
} }
/// Clears the map, removing all elements. /// Clears the map, removing all elements.
@ -589,7 +601,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>, K: Borrow<Q>,
Q: Ord, Q: Ord,
{ {
match search::search_tree(self.root.as_ref(), key) { match search::search_tree(self.root.as_ref()?.as_ref(), key) {
Found(handle) => Some(handle.into_kv().1), Found(handle) => Some(handle.into_kv().1),
GoDown(_) => None, GoDown(_) => None,
} }
@ -616,7 +628,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>, K: Borrow<Q>,
Q: Ord, Q: Ord,
{ {
match search::search_tree(self.root.as_ref(), k) { match search::search_tree(self.root.as_ref()?.as_ref(), k) {
Found(handle) => Some(handle.into_kv()), Found(handle) => Some(handle.into_kv()),
GoDown(_) => None, GoDown(_) => None,
} }
@ -645,7 +657,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
T: Ord, T: Ord,
K: Borrow<T>, K: Borrow<T>,
{ {
let front = self.root.as_ref().first_leaf_edge(); let front = self.root.as_ref()?.as_ref().first_leaf_edge();
front.right_kv().ok().map(Handle::into_kv) front.right_kv().ok().map(Handle::into_kv)
} }
@ -674,7 +686,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
T: Ord, T: Ord,
K: Borrow<T>, K: Borrow<T>,
{ {
let front = self.root.as_mut().first_leaf_edge(); let front = self.root.as_mut()?.as_mut().first_leaf_edge();
if let Ok(kv) = front.right_kv() { if let Ok(kv) = front.right_kv() {
Some(OccupiedEntry { Some(OccupiedEntry {
handle: kv.forget_node_type(), handle: kv.forget_node_type(),
@ -708,7 +720,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
T: Ord, T: Ord,
K: Borrow<T>, K: Borrow<T>,
{ {
let back = self.root.as_ref().last_leaf_edge(); let back = self.root.as_ref()?.as_ref().last_leaf_edge();
back.left_kv().ok().map(Handle::into_kv) back.left_kv().ok().map(Handle::into_kv)
} }
@ -737,7 +749,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
T: Ord, T: Ord,
K: Borrow<T>, K: Borrow<T>,
{ {
let back = self.root.as_mut().last_leaf_edge(); let back = self.root.as_mut()?.as_mut().last_leaf_edge();
if let Ok(kv) = back.left_kv() { if let Ok(kv) = back.left_kv() {
Some(OccupiedEntry { Some(OccupiedEntry {
handle: kv.forget_node_type(), handle: kv.forget_node_type(),
@ -801,7 +813,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>, K: Borrow<Q>,
Q: Ord, Q: Ord,
{ {
match search::search_tree(self.root.as_mut(), key) { match search::search_tree(self.root.as_mut()?.as_mut(), key) {
Found(handle) => Some(handle.into_kv_mut().1), Found(handle) => Some(handle.into_kv_mut().1),
GoDown(_) => None, GoDown(_) => None,
} }
@ -896,7 +908,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>, K: Borrow<Q>,
Q: Ord, Q: Ord,
{ {
match search::search_tree(self.root.as_mut(), key) { match search::search_tree(self.root.as_mut()?.as_mut(), key) {
Found(handle) => Some( Found(handle) => Some(
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData } OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
.remove_entry(), .remove_entry(),
@ -992,11 +1004,15 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<T>, K: Borrow<T>,
R: RangeBounds<T>, R: RangeBounds<T>,
{ {
let root1 = self.root.as_ref(); if let Some(root) = &self.root {
let root2 = self.root.as_ref(); let root1 = root.as_ref();
let (f, b) = range_search(root1, root2, range); let root2 = root.as_ref();
let (f, b) = range_search(root1, root2, range);
Range { front: f, back: b } Range { front: Some(f), back: Some(b) }
} else {
Range { front: None, back: None }
}
} }
/// Constructs a mutable double-ended iterator over a sub-range of elements in the map. /// Constructs a mutable double-ended iterator over a sub-range of elements in the map.
@ -1036,11 +1052,15 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<T>, K: Borrow<T>,
R: RangeBounds<T>, R: RangeBounds<T>,
{ {
let root1 = self.root.as_mut(); if let Some(root) = &mut self.root {
let root2 = unsafe { ptr::read(&root1) }; let root1 = root.as_mut();
let (f, b) = range_search(root1, root2, range); let root2 = unsafe { ptr::read(&root1) };
let (f, b) = range_search(root1, root2, range);
RangeMut { front: f, back: b, _marker: PhantomData } RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }
} else {
RangeMut { front: None, back: None, _marker: PhantomData }
}
} }
/// Gets the given key's corresponding entry in the map for in-place manipulation. /// Gets the given key's corresponding entry in the map for in-place manipulation.
@ -1065,7 +1085,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
// FIXME(@porglezomp) Avoid allocating if we don't insert // FIXME(@porglezomp) Avoid allocating if we don't insert
self.ensure_root_is_owned(); self.ensure_root_is_owned();
match search::search_tree(self.root.as_mut(), &key) { match search::search_tree(self.root.as_mut().unwrap().as_mut(), &key) {
Found(handle) => { Found(handle) => {
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }) Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
} }
@ -1077,7 +1097,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) { fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
self.ensure_root_is_owned(); self.ensure_root_is_owned();
let mut cur_node = self.root.as_mut().last_leaf_edge().into_node(); let mut cur_node = self.root.as_mut().unwrap().as_mut().last_leaf_edge().into_node();
// Iterate through all key-value pairs, pushing them into nodes at the right level. // Iterate through all key-value pairs, pushing them into nodes at the right level.
for (key, value) in iter { for (key, value) in iter {
// Try to push key-value pair into the current leaf node. // Try to push key-value pair into the current leaf node.
@ -1126,7 +1146,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
fn fix_right_edge(&mut self) { fn fix_right_edge(&mut self) {
// Handle underfull nodes, start from the top. // Handle underfull nodes, start from the top.
let mut cur_node = self.root.as_mut(); let mut cur_node = self.root.as_mut().unwrap().as_mut();
while let Internal(internal) = cur_node.force() { while let Internal(internal) = cur_node.force() {
// Check if right-most child is underfull. // Check if right-most child is underfull.
let mut last_edge = internal.last_edge(); let mut last_edge = internal.last_edge();
@ -1187,14 +1207,14 @@ impl<K: Ord, V> BTreeMap<K, V> {
let total_num = self.len(); let total_num = self.len();
let mut right = Self::new(); let mut right = Self::new();
right.root = node::Root::new_leaf(); let right_root = right.ensure_root_is_owned();
for _ in 0..(self.root.as_ref().height()) { for _ in 0..(self.root.as_ref().unwrap().as_ref().height()) {
right.root.push_level(); right_root.push_level();
} }
{ {
let mut left_node = self.root.as_mut(); let mut left_node = self.root.as_mut().unwrap().as_mut();
let mut right_node = right.root.as_mut(); let mut right_node = right.root.as_mut().unwrap().as_mut();
loop { loop {
let mut split_edge = match search::search_node(left_node, key) { let mut split_edge = match search::search_node(left_node, key) {
@ -1223,7 +1243,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
self.fix_right_border(); self.fix_right_border();
right.fix_left_border(); right.fix_left_border();
if self.root.as_ref().height() < right.root.as_ref().height() { if self.root.as_ref().unwrap().as_ref().height()
< right.root.as_ref().unwrap().as_ref().height()
{
self.recalc_length(); self.recalc_length();
right.length = total_num - self.len(); right.length = total_num - self.len();
} else { } else {
@ -1261,19 +1283,19 @@ impl<K: Ord, V> BTreeMap<K, V> {
res res
} }
self.length = dfs(self.root.as_ref()); self.length = dfs(self.root.as_ref().unwrap().as_ref());
} }
/// Removes empty levels on the top. /// Removes empty levels on the top.
fn fix_top(&mut self) { fn fix_top(&mut self) {
loop { loop {
{ {
let node = self.root.as_ref(); let node = self.root.as_ref().unwrap().as_ref();
if node.height() == 0 || node.len() > 0 { if node.height() == 0 || node.len() > 0 {
break; break;
} }
} }
self.root.pop_level(); self.root.as_mut().unwrap().pop_level();
} }
} }
@ -1281,7 +1303,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
self.fix_top(); self.fix_top();
{ {
let mut cur_node = self.root.as_mut(); let mut cur_node = self.root.as_mut().unwrap().as_mut();
while let Internal(node) = cur_node.force() { while let Internal(node) = cur_node.force() {
let mut last_kv = node.last_kv(); let mut last_kv = node.last_kv();
@ -1307,7 +1329,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
self.fix_top(); self.fix_top();
{ {
let mut cur_node = self.root.as_mut(); let mut cur_node = self.root.as_mut().unwrap().as_mut();
while let Internal(node) = cur_node.force() { while let Internal(node) = cur_node.force() {
let mut first_kv = node.first_kv(); let mut first_kv = node.first_kv();
@ -1326,13 +1348,6 @@ impl<K: Ord, V> BTreeMap<K, V> {
self.fix_top(); self.fix_top();
} }
/// If the root node is the shared root node, allocate our own node.
fn ensure_root_is_owned(&mut self) {
if self.root.is_shared_root() {
self.root = node::Root::new_leaf();
}
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -1458,12 +1473,21 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
type IntoIter = IntoIter<K, V>; type IntoIter = IntoIter<K, V>;
fn into_iter(self) -> IntoIter<K, V> { fn into_iter(self) -> IntoIter<K, V> {
let root1 = unsafe { ptr::read(&self.root).into_ref() }; if self.root.is_none() {
let root2 = unsafe { ptr::read(&self.root).into_ref() }; mem::forget(self);
return IntoIter { front: None, back: None, length: 0 };
}
let root1 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
let root2 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() };
let len = self.length; let len = self.length;
mem::forget(self); mem::forget(self);
IntoIter { front: root1.first_leaf_edge(), back: root2.last_leaf_edge(), length: len } IntoIter {
front: Some(root1.first_leaf_edge()),
back: Some(root2.last_leaf_edge()),
length: len,
}
} }
} }
@ -1478,9 +1502,9 @@ impl<K, V> Drop for IntoIter<K, V> {
// don't have to care about panics this time (they'll abort). // don't have to care about panics this time (they'll abort).
while let Some(_) = self.0.next() {} while let Some(_) = self.0.next() {}
// No need to avoid the shared root, because the tree was definitely not empty.
unsafe { unsafe {
let mut node = ptr::read(&self.0.front).into_node().forget_type(); let mut node =
unwrap_unchecked(ptr::read(&self.0.front)).into_node().forget_type();
while let Some(parent) = node.deallocate_and_ascend() { while let Some(parent) = node.deallocate_and_ascend() {
node = parent.into_node().forget_type(); node = parent.into_node().forget_type();
} }
@ -1495,14 +1519,13 @@ impl<K, V> Drop for IntoIter<K, V> {
} }
unsafe { unsafe {
let mut node = ptr::read(&self.front).into_node().forget_type(); if let Some(front) = ptr::read(&self.front) {
if node.is_shared_root() { let mut node = front.into_node().forget_type();
return; // Most of the nodes have been deallocated while traversing
} // but one pile from a leaf up to the root is left standing.
// Most of the nodes have been deallocated while traversing while let Some(parent) = node.deallocate_and_ascend() {
// but one pile from a leaf up to the root is left standing. node = parent.into_node().forget_type();
while let Some(parent) = node.deallocate_and_ascend() { }
node = parent.into_node().forget_type();
} }
} }
} }
@ -1517,7 +1540,7 @@ impl<K, V> Iterator for IntoIter<K, V> {
None None
} else { } else {
self.length -= 1; self.length -= 1;
Some(unsafe { self.front.next_unchecked() }) Some(unsafe { self.front.as_mut().unwrap().next_unchecked() })
} }
} }
@ -1533,7 +1556,7 @@ impl<K, V> DoubleEndedIterator for IntoIter<K, V> {
None None
} else { } else {
self.length -= 1; self.length -= 1;
Some(unsafe { self.back.next_back_unchecked() }) Some(unsafe { self.back.as_mut().unwrap().next_back_unchecked() })
} }
} }
} }
@ -1683,7 +1706,7 @@ impl<'a, K, V> Range<'a, K, V> {
} }
unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
self.front.next_unchecked() unwrap_unchecked(self.front.as_mut()).next_unchecked()
} }
} }
@ -1696,7 +1719,7 @@ impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> {
impl<'a, K, V> Range<'a, K, V> { impl<'a, K, V> Range<'a, K, V> {
unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
self.back.next_back_unchecked() unwrap_unchecked(self.back.as_mut()).next_back_unchecked()
} }
} }
@ -1734,7 +1757,7 @@ impl<'a, K, V> RangeMut<'a, K, V> {
} }
unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) { unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
self.front.next_unchecked() unwrap_unchecked(self.front.as_mut()).next_unchecked()
} }
} }
@ -1755,7 +1778,7 @@ impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
impl<'a, K, V> RangeMut<'a, K, V> { impl<'a, K, V> RangeMut<'a, K, V> {
unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) { unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) {
self.back.next_back_unchecked() unwrap_unchecked(self.back.as_mut()).next_back_unchecked()
} }
} }
@ -1969,8 +1992,8 @@ impl<K, V> BTreeMap<K, V> {
pub fn iter(&self) -> Iter<'_, K, V> { pub fn iter(&self) -> Iter<'_, K, V> {
Iter { Iter {
range: Range { range: Range {
front: self.root.as_ref().first_leaf_edge(), front: self.root.as_ref().map(|r| r.as_ref().first_leaf_edge()),
back: self.root.as_ref().last_leaf_edge(), back: self.root.as_ref().map(|r| r.as_ref().last_leaf_edge()),
}, },
length: self.length, length: self.length,
} }
@ -1999,13 +2022,17 @@ impl<K, V> BTreeMap<K, V> {
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
let root1 = self.root.as_mut();
let root2 = unsafe { ptr::read(&root1) };
IterMut { IterMut {
range: RangeMut { range: if let Some(root) = &mut self.root {
front: root1.first_leaf_edge(), let root1 = root.as_mut();
back: root2.last_leaf_edge(), let root2 = unsafe { ptr::read(&root1) };
_marker: PhantomData, RangeMut {
front: Some(root1.first_leaf_edge()),
back: Some(root2.last_leaf_edge()),
_marker: PhantomData,
}
} else {
RangeMut { front: None, back: None, _marker: PhantomData }
}, },
length: self.length, length: self.length,
} }
@ -2116,6 +2143,12 @@ impl<K, V> BTreeMap<K, V> {
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.len() == 0 self.len() == 0
} }
/// If the root node is the empty (non-allocated) root node, allocate our
/// own node.
fn ensure_root_is_owned(&mut self) -> &mut node::Root<K, V> {
self.root.get_or_insert_with(|| node::Root::new_leaf())
}
} }
impl<'a, K: Ord, V> Entry<'a, K, V> { impl<'a, K: Ord, V> Entry<'a, K, V> {

View file

@ -44,34 +44,7 @@ const B: usize = 6;
pub const MIN_LEN: usize = B - 1; pub const MIN_LEN: usize = B - 1;
pub const CAPACITY: usize = 2 * B - 1; pub const CAPACITY: usize = 2 * B - 1;
/// The underlying representation of leaf nodes. Note that it is often unsafe to actually store /// The underlying representation of leaf nodes.
/// 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.
///
/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
/// order to statically allocate a single dummy node to avoid allocations. This struct is
/// `repr(C)` to prevent them from being reordered. `LeafNode` does not just contain a
/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited
/// by `as_header`.)
#[repr(C)]
struct NodeHeader<K, V> {
/// 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 non-null.
parent_idx: MaybeUninit<u16>,
/// The number of keys and values this node stores.
///
/// This 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,
}
#[repr(C)] #[repr(C)]
struct LeafNode<K, V> { struct LeafNode<K, V> {
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
@ -111,21 +84,6 @@ impl<K, V> LeafNode<K, V> {
} }
} }
impl<K, V> NodeHeader<K, V> {
fn is_shared_root(&self) -> bool {
ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
}
}
// We need to implement Sync here in order to make a static instance.
unsafe impl Sync for NodeHeader<(), ()> {}
// An empty node used as a placeholder for the root node, to avoid allocations.
// We use just a header in order to save space, since no operation on an empty tree will
// ever take a pointer past the first key.
static EMPTY_ROOT_NODE: NodeHeader<(), ()> =
NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 };
/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden /// 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 /// 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 /// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the
@ -154,12 +112,9 @@ impl<K, V> InternalNode<K, V> {
} }
/// A managed, non-null pointer to a node. This is either an owned pointer to /// A managed, non-null pointer to a node. This is either an owned pointer to
/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned) /// `LeafNode<K, V>` or an owned pointer to `InternalNode<K, V>`.
/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE). ///
/// All of these types have a `NodeHeader<K, V>` prefix, meaning that they have at /// However, `BoxedNode` contains no information as to which of the two types
/// least the same size as `NodeHeader<K, V>` and store the same kinds of data at the same
/// offsets; and they have a pointer alignment at least as large as `NodeHeader<K, V>`'s.
/// However, `BoxedNode` contains no information as to which of the three types
/// of nodes it actually contains, and, partially due to this lack of information, /// of nodes it actually contains, and, partially due to this lack of information,
/// has no destructor. /// has no destructor.
struct BoxedNode<K, V> { struct BoxedNode<K, V> {
@ -184,8 +139,9 @@ impl<K, V> BoxedNode<K, V> {
} }
} }
/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor, /// An owned tree.
/// and must be cleaned up manually if it is an owned tree. ///
/// Note that this does not have a destructor, and must be cleaned up manually.
pub struct Root<K, V> { pub struct Root<K, V> {
node: BoxedNode<K, V>, node: BoxedNode<K, V>,
/// The number of levels below the root node. /// The number of levels below the root node.
@ -196,20 +152,6 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
unsafe impl<K: Send, V: Send> Send for Root<K, V> {} unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
impl<K, V> Root<K, V> { impl<K, V> Root<K, V> {
/// Whether the instance of `Root` wraps a shared, empty root node. If not,
/// the entire tree is uniquely owned by the owner of the `Root` instance.
pub fn is_shared_root(&self) -> bool {
self.as_ref().is_shared_root()
}
/// Returns a shared tree, wrapping a shared root node that is eternally empty.
pub fn shared_empty_root() -> Self {
Root {
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
height: 0,
}
}
/// Returns a new owned tree, with its own root node that is initially empty. /// Returns a new owned tree, with its own root node that is initially empty.
pub fn new_leaf() -> Self { pub fn new_leaf() -> Self {
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 } Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
@ -245,7 +187,6 @@ impl<K, V> Root<K, V> {
/// Adds 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`. /// 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> { pub fn push_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
debug_assert!(!self.is_shared_root());
let mut new_node = Box::new(unsafe { InternalNode::new() }); let mut new_node = Box::new(unsafe { InternalNode::new() });
new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) }); new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) });
@ -308,11 +249,6 @@ impl<K, V> Root<K, V> {
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the /// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the /// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
/// `NodeRef` could be pointing to either type of node. /// `NodeRef` could be pointing to either type of node.
/// Note that in case of a leaf node, this might still be the shared root!
/// Only turn this into a `LeafNode` reference if you know it is not the shared root!
/// Shared references must be dereferenceable *for the entire size of their pointee*,
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
/// Turning this into a `NodeHeader` reference is always safe.
pub struct NodeRef<BorrowType, K, V, Type> { pub struct NodeRef<BorrowType, K, V, Type> {
/// The number of levels below the node. /// The number of levels below the node.
height: usize, height: usize,
@ -354,7 +290,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
/// Note that, despite being safe, calling this function can have the side effect /// Note that, despite being safe, calling this function can have the side effect
/// of invalidating mutable references that unsafe code has created. /// of invalidating mutable references that unsafe code has created.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.as_header().len as usize self.as_leaf().len as usize
} }
/// Returns the height of this node in the whole tree. Zero height denotes the /// Returns the height of this node in the whole tree. Zero height denotes the
@ -374,35 +310,24 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData } NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
} }
/// Exposes the leaf "portion" of any leaf or internal node that is not the shared root. /// Exposes the leaf "portion" of any leaf or internal node.
/// If the node is a leaf, this function simply opens up its data. /// If the node is a leaf, this function simply opens up its data.
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has /// If the node is an internal node, so not a leaf, it does have all the data a leaf has
/// (header, keys and values), and this function exposes that. /// (header, keys and values), and this function exposes that.
/// Unsafe because the node must not be the shared root. For more information, fn as_leaf(&self) -> &LeafNode<K, V> {
/// see the `NodeRef` comments. // The node must be valid for at least the LeafNode portion.
unsafe fn as_leaf(&self) -> &LeafNode<K, V> { // This is not a reference in the NodeRef type because we don't know if
debug_assert!(!self.is_shared_root()); // it should be unique or shared.
self.node.as_ref() unsafe { self.node.as_ref() }
}
fn as_header(&self) -> &NodeHeader<K, V> {
unsafe { &*(self.node.as_ptr() as *const NodeHeader<K, V>) }
}
/// Returns whether the node is the shared, empty root.
pub fn is_shared_root(&self) -> bool {
self.as_header().is_shared_root()
} }
/// Borrows a view into the keys stored in the node. /// Borrows a view into the keys stored in the node.
/// Unsafe because the caller must ensure that the node is not the shared root. pub fn keys(&self) -> &[K] {
pub unsafe fn keys(&self) -> &[K] {
self.reborrow().into_key_slice() self.reborrow().into_key_slice()
} }
/// Borrows a view into the values stored in the node. /// Borrows a view into the values stored in the node.
/// Unsafe because the caller must ensure that the node is not the shared root. fn vals(&self) -> &[V] {
unsafe fn vals(&self) -> &[V] {
self.reborrow().into_val_slice() self.reborrow().into_val_slice()
} }
@ -416,7 +341,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
pub fn ascend( pub fn ascend(
self, self,
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> { ) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>; let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) { if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
Ok(Handle { Ok(Handle {
node: NodeRef { node: NodeRef {
@ -425,7 +350,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
root: self.root, root: self.root,
_marker: PhantomData, _marker: PhantomData,
}, },
idx: unsafe { usize::from(*self.as_header().parent_idx.as_ptr()) }, idx: unsafe { usize::from(*self.as_leaf().parent_idx.as_ptr()) },
_marker: PhantomData, _marker: PhantomData,
}) })
} else { } else {
@ -464,7 +389,6 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
pub unsafe fn deallocate_and_ascend( pub unsafe fn deallocate_and_ascend(
self, self,
) -> Option<Handle<NodeRef<marker::Owned, K, V, marker::Internal>, marker::Edge>> { ) -> Option<Handle<NodeRef<marker::Owned, K, V, marker::Internal>, marker::Edge>> {
assert!(!self.is_shared_root());
let height = self.height; let height = self.height;
let node = self.node; let node = self.node;
let ret = self.ascend().ok(); let ret = self.ascend().ok();
@ -507,41 +431,37 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
/// (header, keys and values), and this function exposes that. /// (header, keys and values), and this function exposes that.
/// ///
/// Returns a raw ptr to avoid asserting exclusive access to the entire node. /// Returns a raw ptr to avoid asserting exclusive access to the entire node.
/// This also implies you can invoke this member on the shared root, but the resulting pointer
/// might not be properly aligned and definitely would not allow accessing keys and values.
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> { fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
self.node.as_ptr() self.node.as_ptr()
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn keys_mut(&mut self) -> &mut [K] {
unsafe fn keys_mut(&mut self) -> &mut [K] { // SAFETY: the caller will not be able to call further methods on self
self.reborrow_mut().into_key_slice_mut() // until the key slice reference is dropped, as we have unique access
// for the lifetime of the borrow.
unsafe { self.reborrow_mut().into_key_slice_mut() }
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn vals_mut(&mut self) -> &mut [V] {
unsafe fn vals_mut(&mut self) -> &mut [V] { // SAFETY: the caller will not be able to call further methods on self
self.reborrow_mut().into_val_slice_mut() // until the value slice reference is dropped, as we have unique access
// for the lifetime of the borrow.
unsafe { self.reborrow_mut().into_val_slice_mut() }
} }
} }
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> { impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_key_slice(self) -> &'a [K] {
unsafe fn into_key_slice(self) -> &'a [K] { unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) }
debug_assert!(!self.is_shared_root());
// We cannot be the shared root, so `as_leaf` is okay.
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_val_slice(self) -> &'a [V] {
unsafe fn into_val_slice(self) -> &'a [V] { unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
debug_assert!(!self.is_shared_root());
// We cannot be the shared root, so `as_leaf` is okay.
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len())
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_slices(self) -> (&'a [K], &'a [V]) {
unsafe fn into_slices(self) -> (&'a [K], &'a [V]) { // SAFETY: equivalent to reborrow() except not requiring Type: 'a
let k = ptr::read(&self); let k = unsafe { ptr::read(&self) };
(k.into_key_slice(), self.into_val_slice()) (k.into_key_slice(), self.into_val_slice())
} }
} }
@ -553,28 +473,27 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
unsafe { &mut *(self.root as *mut Root<K, V>) } unsafe { &mut *(self.root as *mut Root<K, V>) }
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_key_slice_mut(mut self) -> &'a mut [K] {
unsafe fn into_key_slice_mut(mut self) -> &'a mut [K] { // SAFETY: The keys of a node must always be initialized up to length.
debug_assert!(!self.is_shared_root()); unsafe {
// We cannot be the shared root, so `as_leaf_mut` is okay. slice::from_raw_parts_mut(
slice::from_raw_parts_mut( MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys), self.len(),
self.len(), )
) }
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_val_slice_mut(mut self) -> &'a mut [V] {
unsafe fn into_val_slice_mut(mut self) -> &'a mut [V] { // SAFETY: The values of a node must always be initialized up to length.
debug_assert!(!self.is_shared_root()); unsafe {
slice::from_raw_parts_mut( slice::from_raw_parts_mut(
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals), MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
self.len(), self.len(),
) )
}
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
unsafe fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
debug_assert!(!self.is_shared_root());
// We cannot use the getters here, because calling the second one // We cannot use the getters here, because calling the second one
// invalidates the reference returned by the first. // invalidates the reference returned by the first.
// More precisely, it is the call to `len` that is the culprit, // More precisely, it is the call to `len` that is the culprit,
@ -582,8 +501,13 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
// overlap with the keys (and even the values, for ZST keys). // overlap with the keys (and even the values, for ZST keys).
let len = self.len(); let len = self.len();
let leaf = self.as_leaf_mut(); let leaf = self.as_leaf_mut();
let keys = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len); // SAFETY: The keys and values of a node must always be initialized up to length.
let vals = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len); let keys = unsafe {
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len)
};
let vals = unsafe {
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len)
};
(keys, vals) (keys, vals)
} }
} }
@ -592,7 +516,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
/// Adds a key/value pair the end of the node. /// Adds a key/value pair the end of the node.
pub fn push(&mut self, key: K, val: V) { pub fn push(&mut self, key: K, val: V) {
assert!(self.len() < CAPACITY); assert!(self.len() < CAPACITY);
debug_assert!(!self.is_shared_root());
let idx = self.len(); let idx = self.len();
@ -607,7 +530,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
/// Adds a key/value pair to the beginning of the node. /// Adds a key/value pair to the beginning of the node.
pub fn push_front(&mut self, key: K, val: V) { pub fn push_front(&mut self, key: K, val: V) {
assert!(self.len() < CAPACITY); assert!(self.len() < CAPACITY);
debug_assert!(!self.is_shared_root());
unsafe { unsafe {
slice_insert(self.keys_mut(), 0, key); slice_insert(self.keys_mut(), 0, key);
@ -624,7 +546,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) { pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
assert!(edge.height == self.height - 1); assert!(edge.height == self.height - 1);
assert!(self.len() < CAPACITY); assert!(self.len() < CAPACITY);
debug_assert!(!self.is_shared_root());
let idx = self.len(); let idx = self.len();
@ -658,7 +579,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) { pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
assert!(edge.height == self.height - 1); assert!(edge.height == self.height - 1);
assert!(self.len() < CAPACITY); assert!(self.len() < CAPACITY);
debug_assert!(!self.is_shared_root());
unsafe { unsafe {
slice_insert(self.keys_mut(), 0, key); slice_insert(self.keys_mut(), 0, key);
@ -744,8 +664,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
} }
} }
/// Unsafe because the caller must ensure that the node is not the shared root. fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
unsafe fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
(self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr()) (self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr())
} }
} }
@ -904,7 +823,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
fn insert_fit(&mut self, key: K, val: V) -> *mut V { fn insert_fit(&mut self, key: K, val: V) -> *mut V {
// Necessary for correctness, but in a private module // Necessary for correctness, but in a private module
debug_assert!(self.node.len() < CAPACITY); debug_assert!(self.node.len() < CAPACITY);
debug_assert!(!self.node.is_shared_root());
unsafe { unsafe {
slice_insert(self.node.keys_mut(), self.idx, key); slice_insert(self.node.keys_mut(), self.idx, key);
@ -1081,7 +999,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
/// - All the key/value pairs to the right of this handle are put into a newly /// - All the key/value pairs to the right of this handle are put into a newly
/// allocated node. /// allocated node.
pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) { pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
assert!(!self.node.is_shared_root());
unsafe { unsafe {
let mut new_node = Box::new(LeafNode::new()); let mut new_node = Box::new(LeafNode::new());
@ -1113,7 +1030,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
pub fn remove( pub fn remove(
mut self, mut self,
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) { ) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
assert!(!self.node.is_shared_root());
unsafe { unsafe {
let k = slice_remove(self.node.keys_mut(), self.idx); let k = slice_remove(self.node.keys_mut(), self.idx);
let v = slice_remove(self.node.vals_mut(), self.idx); let v = slice_remove(self.node.vals_mut(), self.idx);

View file

@ -67,19 +67,16 @@ where
Q: Ord, Q: Ord,
K: Borrow<Q>, K: Borrow<Q>,
{ {
// This function is defined over all borrow types (immutable, mutable, owned), // This function is defined over all borrow types (immutable, mutable, owned).
// and may be called on the shared root in each case.
// Using `keys()` is fine here even if BorrowType is mutable, as all we return // Using `keys()` is fine here even if BorrowType is mutable, as all we return
// is an index -- not a reference. // is an index -- not a reference.
let len = node.len(); let len = node.len();
if len > 0 { let keys = node.keys();
let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root for (i, k) in keys.iter().enumerate() {
for (i, k) in keys.iter().enumerate() { match key.cmp(k.borrow()) {
match key.cmp(k.borrow()) { Ordering::Greater => {}
Ordering::Greater => {} Ordering::Equal => return (i, true),
Ordering::Equal => return (i, true), Ordering::Less => return (i, false),
Ordering::Less => return (i, false),
}
} }
} }
(len, false) (len, false)

View file

@ -80,6 +80,7 @@
#![feature(box_into_raw_non_null)] #![feature(box_into_raw_non_null)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)] #![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)] #![feature(coerce_unsized)]
#![feature(const_generic_impls_guard)] #![feature(const_generic_impls_guard)]

View file

@ -40,6 +40,23 @@ mod tests;
/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references.
const MAX_REFCOUNT: usize = (isize::MAX) as usize; const MAX_REFCOUNT: usize = (isize::MAX) as usize;
#[cfg(not(sanitize = "thread"))]
macro_rules! acquire {
($x:expr) => {
atomic::fence(Acquire)
};
}
// ThreadSanitizer does not support memory fences. To avoid false positive
// reports in Arc / Weak implementation use atomic loads for synchronization
// instead.
#[cfg(sanitize = "thread")]
macro_rules! acquire {
($x:expr) => {
$x.load(Acquire)
};
}
/// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically /// A thread-safe reference-counting pointer. 'Arc' stands for 'Atomically
/// Reference Counted'. /// Reference Counted'.
/// ///
@ -402,7 +419,7 @@ impl<T> Arc<T> {
return Err(this); return Err(this);
} }
atomic::fence(Acquire); acquire!(this.inner().strong);
unsafe { unsafe {
let elem = ptr::read(&this.ptr.as_ref().data); let elem = ptr::read(&this.ptr.as_ref().data);
@ -739,7 +756,7 @@ impl<T: ?Sized> Arc<T> {
ptr::drop_in_place(&mut self.ptr.as_mut().data); ptr::drop_in_place(&mut self.ptr.as_mut().data);
if self.inner().weak.fetch_sub(1, Release) == 1 { if self.inner().weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire); acquire!(self.inner().weak);
Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref()))
} }
} }
@ -1243,7 +1260,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> {
// //
// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
// [2]: (https://github.com/rust-lang/rust/pull/41714) // [2]: (https://github.com/rust-lang/rust/pull/41714)
atomic::fence(Acquire); acquire!(self.inner().strong);
unsafe { unsafe {
self.drop_slow(); self.drop_slow();
@ -1701,7 +1718,7 @@ impl<T: ?Sized> Drop for Weak<T> {
let inner = if let Some(inner) = self.inner() { inner } else { return }; let inner = if let Some(inner) = self.inner() { inner } else { return };
if inner.weak.fetch_sub(1, Release) == 1 { if inner.weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire); acquire!(inner.weak);
unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) } unsafe { Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) }
} }
} }

View file

@ -67,7 +67,7 @@ fn test_basic_large() {
#[test] #[test]
fn test_basic_small() { fn test_basic_small() {
let mut map = BTreeMap::new(); let mut map = BTreeMap::new();
// Empty, shared root: // Empty, root is absent (None):
assert_eq!(map.remove(&1), None); assert_eq!(map.remove(&1), None);
assert_eq!(map.len(), 0); assert_eq!(map.len(), 0);
assert_eq!(map.get(&1), None); assert_eq!(map.get(&1), None);
@ -123,7 +123,7 @@ fn test_basic_small() {
assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]); assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
assert_eq!(map.remove(&2), Some(4)); assert_eq!(map.remove(&2), Some(4));
// Empty but private root: // Empty but root is owned (Some(...)):
assert_eq!(map.len(), 0); assert_eq!(map.len(), 0);
assert_eq!(map.get(&1), None); assert_eq!(map.get(&1), None);
assert_eq!(map.get_mut(&1), None); assert_eq!(map.get_mut(&1), None);
@ -263,13 +263,6 @@ fn test_iter_mut_mutation() {
do_test_iter_mut_mutation::<Align32>(144); do_test_iter_mut_mutation::<Align32>(144);
} }
#[test]
fn test_into_key_slice_with_shared_root_past_bounds() {
let mut map: BTreeMap<Align32, ()> = BTreeMap::new();
assert_eq!(map.get(&Align32(1)), None);
assert_eq!(map.get_mut(&Align32(1)), None);
}
#[test] #[test]
fn test_values_mut() { fn test_values_mut() {
let mut a = BTreeMap::new(); let mut a = BTreeMap::new();

View file

@ -1377,6 +1377,7 @@ impl<T> Vec<T> {
/// assert_eq!(vec2, [2, 3]); /// assert_eq!(vec2, [2, 3]);
/// ``` /// ```
#[inline] #[inline]
#[must_use = "use `.truncate()` if you don't need the other half"]
#[stable(feature = "split_off", since = "1.4.0")] #[stable(feature = "split_off", since = "1.4.0")]
pub fn split_off(&mut self, at: usize) -> Self { pub fn split_off(&mut self, at: usize) -> Self {
assert!(at <= self.len(), "`at` out of bounds"); assert!(at <= self.len(), "`at` out of bounds");

View file

@ -2,6 +2,84 @@
//! Asynchronous values. //! Asynchronous values.
#[cfg(not(bootstrap))]
use crate::{
ops::{Generator, GeneratorState},
pin::Pin,
ptr::NonNull,
task::{Context, Poll},
};
mod future; mod future;
#[stable(feature = "futures_api", since = "1.36.0")] #[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future; pub use self::future::Future;
/// This type is needed because:
///
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
/// a raw pointer (see https://github.com/rust-lang/rust/issues/68923).
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
/// non-Send/Sync as well, and we don't want that.
///
/// It also simplifies the HIR lowering of `.await`.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[derive(Debug, Copy, Clone)]
pub struct ResumeTy(NonNull<Context<'static>>);
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Send for ResumeTy {}
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Sync for ResumeTy {}
/// Wrap a generator in a future.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn`
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where
T: Generator<ResumeTy, Yield = ()>,
{
struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
// We rely on the fact that async/await futures are immovable in order to create
// self-referential borrows in the underlying generator.
impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
type Output = T::Return;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// Safety: Safe because we're !Unpin + !Drop, and this is just a field projection.
let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
// Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
// `.await` lowering will safely cast that back to a `&mut Context`.
match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
GeneratorState::Yielded(()) => Poll::Pending,
GeneratorState::Complete(x) => Poll::Ready(x),
}
}
}
GenFuture(gen)
}
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub unsafe fn poll_with_context<F>(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll<F::Output>
where
F: Future,
{
F::poll(f, cx.0.as_mut())
}

View file

@ -114,6 +114,6 @@ pub fn black_box<T>(dummy: T) -> T {
// more than we want, but it's so far good enough. // more than we want, but it's so far good enough.
unsafe { unsafe {
asm!("" : : "r"(&dummy)); asm!("" : : "r"(&dummy));
return dummy; dummy
} }
} }

View file

@ -140,6 +140,7 @@
#![feature(associated_type_bounds)] #![feature(associated_type_bounds)]
#![feature(const_type_id)] #![feature(const_type_id)]
#![feature(const_caller_location)] #![feature(const_caller_location)]
#![feature(option_zip)]
#![feature(no_niche)] // rust-lang/rust#68303 #![feature(no_niche)] // rust-lang/rust#68303
#[prelude_import] #[prelude_import]

View file

@ -1,5 +1,5 @@
use crate::fmt; use crate::fmt;
use crate::hash::{Hash, Hasher}; use crate::hash::Hash;
/// An unbounded range (`..`). /// An unbounded range (`..`).
/// ///
@ -330,7 +330,7 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive /// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive
/// ``` /// ```
#[doc(alias = "..=")] #[doc(alias = "..=")]
#[derive(Clone)] // not Copy -- see #27186 #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
#[stable(feature = "inclusive_range", since = "1.26.0")] #[stable(feature = "inclusive_range", since = "1.26.0")]
pub struct RangeInclusive<Idx> { pub struct RangeInclusive<Idx> {
// Note that the fields here are not public to allow changing the // Note that the fields here are not public to allow changing the
@ -350,26 +350,6 @@ pub struct RangeInclusive<Idx> {
pub(crate) exhausted: bool, pub(crate) exhausted: bool,
} }
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.start == other.start && self.end == other.end && self.exhausted == other.exhausted
}
}
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.start.hash(state);
self.end.hash(state);
self.exhausted.hash(state);
}
}
impl<Idx> RangeInclusive<Idx> { impl<Idx> RangeInclusive<Idx> {
/// Creates a new inclusive range. Equivalent to writing `start..=end`. /// Creates a new inclusive range. Equivalent to writing `start..=end`.
/// ///

View file

@ -913,6 +913,63 @@ impl<T> Option<T> {
pub fn replace(&mut self, value: T) -> Option<T> { pub fn replace(&mut self, value: T) -> Option<T> {
mem::replace(self, Some(value)) mem::replace(self, Some(value))
} }
/// Zips `self` with another `Option`.
///
/// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some((s, o))`.
/// Otherwise, `None` is returned.
///
/// # Examples
///
/// ```
/// #![feature(option_zip)]
/// let x = Some(1);
/// let y = Some("hi");
/// let z = None::<u8>;
///
/// assert_eq!(x.zip(y), Some((1, "hi")));
/// assert_eq!(x.zip(z), None);
/// ```
#[unstable(feature = "option_zip", issue = "70086")]
pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> {
self.zip_with(other, |a, b| (a, b))
}
/// Zips `self` and another `Option` with function `f`.
///
/// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`.
/// Otherwise, `None` is returned.
///
/// # Examples
///
/// ```
/// #![feature(option_zip)]
///
/// #[derive(Debug, PartialEq)]
/// struct Point {
/// x: f64,
/// y: f64,
/// }
///
/// impl Point {
/// fn new(x: f64, y: f64) -> Self {
/// Self { x, y }
/// }
/// }
///
/// let x = Some(17.5);
/// let y = Some(42.7);
///
/// assert_eq!(x.zip_with(y, Point::new), Some(Point { x: 17.5, y: 42.7 }));
/// assert_eq!(x.zip_with(None, Point::new), None);
/// ```
#[unstable(feature = "option_zip", issue = "70086")]
pub fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R>
where
F: FnOnce(T, U) -> R,
{
Some(f(self?, other?))
}
} }
impl<T: Copy> Option<&T> { impl<T: Copy> Option<&T> {

View file

@ -129,21 +129,3 @@ fn test_discriminant_send_sync() {
is_send_sync::<Discriminant<Regular>>(); is_send_sync::<Discriminant<Regular>>();
is_send_sync::<Discriminant<NotSendSync>>(); is_send_sync::<Discriminant<NotSendSync>>();
} }
#[test]
fn test_const_forget() {
const _: () = forget(0i32);
const _: () = forget(Vec::<Vec<Box<i32>>>::new());
// Writing this function signature without const-forget
// triggers compiler errors:
// 1) That we use a non-const fn inside a const fn
// 2) without the forget, it complains about the destructor of Box
const fn const_forget_box<T>(x: Box<T>) {
forget(x);
}
// Call the forget_box at runtime,
// as we can't const-construct a box yet.
const_forget_box(Box::new(0i32));
}

View file

@ -85,7 +85,7 @@ impl LintLevelSets {
level = cmp::min(*driver_level, level); level = cmp::min(*driver_level, level);
} }
return (level, src); (level, src)
} }
pub fn get_lint_id_level( pub fn get_lint_id_level(

View file

@ -467,7 +467,7 @@ impl<'tcx> ScopeTree {
} }
debug!("temporary_scope({:?}) = None", expr_id); debug!("temporary_scope({:?}) = None", expr_id);
return None; None
} }
/// Returns the lifetime of the variable `id`. /// Returns the lifetime of the variable `id`.
@ -498,7 +498,7 @@ impl<'tcx> ScopeTree {
debug!("is_subscope_of({:?}, {:?})=true", subscope, superscope); debug!("is_subscope_of({:?}, {:?})=true", subscope, superscope);
return true; true
} }
/// Returns the ID of the innermost containing body. /// Returns the ID of the innermost containing body.

View file

@ -1447,11 +1447,11 @@ impl<'tcx> TyCtxt<'tcx> {
_ => return None, _ => return None,
}; };
return Some(FreeRegionInfo { Some(FreeRegionInfo {
def_id: suitable_region_binding_scope, def_id: suitable_region_binding_scope,
boundregion: bound_region, boundregion: bound_region,
is_impl_item, is_impl_item,
}); })
} }
pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> { pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> {

View file

@ -440,7 +440,7 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
(Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize( (Some(sz_a_val), Some(sz_b_val)) => Err(TypeError::FixedArraySize(
expected_found(relation, &sz_a_val, &sz_b_val), expected_found(relation, &sz_a_val, &sz_b_val),
)), )),
_ => return Err(err), _ => Err(err),
} }
} }
} }

View file

@ -1612,7 +1612,7 @@ impl<'tcx> PolyExistentialProjection<'tcx> {
} }
pub fn item_def_id(&self) -> DefId { pub fn item_def_id(&self) -> DefId {
return self.skip_binder().item_def_id; self.skip_binder().item_def_id
} }
} }
@ -2000,8 +2000,8 @@ impl<'tcx> TyS<'tcx> {
#[inline] #[inline]
pub fn is_unsafe_ptr(&self) -> bool { pub fn is_unsafe_ptr(&self) -> bool {
match self.kind { match self.kind {
RawPtr(_) => return true, RawPtr(_) => true,
_ => return false, _ => false,
} }
} }

View file

@ -524,7 +524,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
self.root_ty = None; self.root_ty = None;
} }
return t1; t1
} }
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {

View file

@ -424,7 +424,7 @@ impl Token {
NtExpr(..) | NtBlock(..) | NtLiteral(..) => true, NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
_ => false, _ => false,
}, },
_ => self.can_begin_literal_or_bool(), _ => self.can_begin_literal_maybe_minus(),
} }
} }
@ -448,13 +448,22 @@ impl Token {
/// Returns `true` if the token is any literal, a minus (which can prefix a literal, /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
/// for example a '-42', or one of the boolean idents). /// for example a '-42', or one of the boolean idents).
/// ///
/// Keep this in sync with `Lit::from_token`. /// In other words, would this token be a valid start of `parse_literal_maybe_minus`?
pub fn can_begin_literal_or_bool(&self) -> bool { ///
/// Keep this in sync with and `Lit::from_token`, excluding unary negation.
pub fn can_begin_literal_maybe_minus(&self) -> bool {
match self.uninterpolate().kind { match self.uninterpolate().kind {
Literal(..) | BinOp(Minus) => true, Literal(..) | BinOp(Minus) => true,
Ident(name, false) if name.is_bool_lit() => true, Ident(name, false) if name.is_bool_lit() => true,
Interpolated(ref nt) => match &**nt { Interpolated(ref nt) => match &**nt {
NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)), NtLiteral(_) => true,
NtExpr(e) => match &e.kind {
ast::ExprKind::Lit(_) => true,
ast::ExprKind::Unary(ast::UnOp::Neg, e) => {
matches!(&e.kind, ast::ExprKind::Lit(_))
}
_ => false,
},
_ => false, _ => false,
}, },
_ => false, _ => false,

View file

@ -189,7 +189,7 @@ impl Lit {
/// Converts arbitrary token into an AST literal. /// Converts arbitrary token into an AST literal.
/// ///
/// Keep this in sync with `Token::can_begin_literal_or_bool`. /// Keep this in sync with `Token::can_begin_literal_or_bool` excluding unary negation.
pub fn from_token(token: &Token) -> Result<Lit, LitError> { pub fn from_token(token: &Token) -> Result<Lit, LitError> {
let lit = match token.uninterpolate().kind { let lit = match token.uninterpolate().kind {
token::Ident(name, false) if name.is_bool_lit() => { token::Ident(name, false) if name.is_bool_lit() => {

View file

@ -470,6 +470,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
} }
/// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
///
/// This results in:
///
/// ```text
/// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
/// <body>
/// })
/// ```
pub(super) fn make_async_expr( pub(super) fn make_async_expr(
&mut self, &mut self,
capture_clause: CaptureBy, capture_clause: CaptureBy,
@ -480,17 +489,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let output = match ret_ty { let output = match ret_ty {
Some(ty) => FnRetTy::Ty(ty), Some(ty) => hir::FnRetTy::Return(self.lower_ty(&ty, ImplTraitContext::disallowed())),
None => FnRetTy::Default(span), None => hir::FnRetTy::DefaultReturn(span),
}; };
let ast_decl = FnDecl { inputs: vec![], output };
let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); // Resume argument type. We let the compiler infer this to simplify the lowering. It is
let body_id = self.lower_fn_body(&ast_decl, |this| { // fully constrained by `future::from_generator`.
this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind)); let input_ty = hir::Ty { hir_id: self.next_id(), kind: hir::TyKind::Infer, span };
body(this)
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
let decl = self.arena.alloc(hir::FnDecl {
inputs: arena_vec![self; input_ty],
output,
c_variadic: false,
implicit_self: hir::ImplicitSelfKind::None,
}); });
// `static || -> <ret_ty> { body }`: // Lower the argument pattern/ident. The ident is used again in the `.await` lowering.
let (pat, task_context_hid) = self.pat_ident_binding_mode(
span,
Ident::with_dummy_span(sym::_task_context),
hir::BindingAnnotation::Mutable,
);
let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, span };
let params = arena_vec![self; param];
let body_id = self.lower_body(move |this| {
this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind));
let old_ctx = this.task_context;
this.task_context = Some(task_context_hid);
let res = body(this);
this.task_context = old_ctx;
(params, res)
});
// `static |_task_context| -> <ret_ty> { body }`:
let generator_kind = hir::ExprKind::Closure( let generator_kind = hir::ExprKind::Closure(
capture_clause, capture_clause,
decl, decl,
@ -523,13 +557,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
/// ```rust /// ```rust
/// match <expr> { /// match <expr> {
/// mut pinned => loop { /// mut pinned => loop {
/// match ::std::future::poll_with_tls_context(unsafe { /// match unsafe { ::std::future::poll_with_context(
/// <::std::pin::Pin>::new_unchecked(&mut pinned) /// <::std::pin::Pin>::new_unchecked(&mut pinned),
/// }) { /// task_context,
/// ) } {
/// ::std::task::Poll::Ready(result) => break result, /// ::std::task::Poll::Ready(result) => break result,
/// ::std::task::Poll::Pending => {} /// ::std::task::Poll::Pending => {}
/// } /// }
/// yield (); /// task_context = yield ();
/// } /// }
/// } /// }
/// ``` /// ```
@ -561,12 +596,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
let (pinned_pat, pinned_pat_hid) = let (pinned_pat, pinned_pat_hid) =
self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable); self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable);
// ::std::future::poll_with_tls_context(unsafe { let task_context_ident = Ident::with_dummy_span(sym::_task_context);
// ::std::pin::Pin::new_unchecked(&mut pinned)
// })` // unsafe {
// ::std::future::poll_with_context(
// ::std::pin::Pin::new_unchecked(&mut pinned),
// task_context,
// )
// }
let poll_expr = { let poll_expr = {
let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid); let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid);
let ref_mut_pinned = self.expr_mut_addr_of(span, pinned); let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
let task_context = if let Some(task_context_hid) = self.task_context {
self.expr_ident_mut(span, task_context_ident, task_context_hid)
} else {
// Use of `await` outside of an async context, we cannot use `task_context` here.
self.expr_err(span)
};
let pin_ty_id = self.next_id(); let pin_ty_id = self.next_id();
let new_unchecked_expr_kind = self.expr_call_std_assoc_fn( let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
pin_ty_id, pin_ty_id,
@ -575,14 +621,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
"new_unchecked", "new_unchecked",
arena_vec![self; ref_mut_pinned], arena_vec![self; ref_mut_pinned],
); );
let new_unchecked = let new_unchecked = self.expr(span, new_unchecked_expr_kind, ThinVec::new());
self.arena.alloc(self.expr(span, new_unchecked_expr_kind, ThinVec::new())); let call = self.expr_call_std_path(
let unsafe_expr = self.expr_unsafe(new_unchecked);
self.expr_call_std_path(
gen_future_span, gen_future_span,
&[sym::future, sym::poll_with_tls_context], &[sym::future, sym::poll_with_context],
arena_vec![self; unsafe_expr], arena_vec![self; new_unchecked, task_context],
) );
self.arena.alloc(self.expr_unsafe(call))
}; };
// `::std::task::Poll::Ready(result) => break result` // `::std::task::Poll::Ready(result) => break result`
@ -622,6 +667,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.stmt_expr(span, match_expr) self.stmt_expr(span, match_expr)
}; };
// task_context = yield ();
let yield_stmt = { let yield_stmt = {
let unit = self.expr_unit(span); let unit = self.expr_unit(span);
let yield_expr = self.expr( let yield_expr = self.expr(
@ -629,7 +675,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Yield(unit, hir::YieldSource::Await), hir::ExprKind::Yield(unit, hir::YieldSource::Await),
ThinVec::new(), ThinVec::new(),
); );
self.stmt_expr(span, yield_expr) let yield_expr = self.arena.alloc(yield_expr);
if let Some(task_context_hid) = self.task_context {
let lhs = self.expr_ident(span, task_context_ident, task_context_hid);
let assign =
self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, span), AttrVec::new());
self.stmt_expr(span, assign)
} else {
// Use of `await` outside of an async context. Return `yield_expr` so that we can
// proceed with type checking.
self.stmt(span, hir::StmtKind::Semi(yield_expr))
}
}; };
let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None); let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None);

View file

@ -814,7 +814,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
} }
/// Construct `ExprKind::Err` for the given `span`. /// Construct `ExprKind::Err` for the given `span`.
fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> { crate fn expr_err(&mut self, span: Span) -> hir::Expr<'hir> {
self.expr(span, hir::ExprKind::Err, AttrVec::new()) self.expr(span, hir::ExprKind::Err, AttrVec::new())
} }
@ -960,7 +960,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
id id
} }
fn lower_body( pub(super) fn lower_body(
&mut self, &mut self,
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>), f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
) -> hir::BodyId { ) -> hir::BodyId {

View file

@ -116,6 +116,10 @@ struct LoweringContext<'a, 'hir: 'a> {
generator_kind: Option<hir::GeneratorKind>, generator_kind: Option<hir::GeneratorKind>,
/// When inside an `async` context, this is the `HirId` of the
/// `task_context` local bound to the resume argument of the generator.
task_context: Option<hir::HirId>,
/// Used to get the current `fn`'s def span to point to when using `await` /// Used to get the current `fn`'s def span to point to when using `await`
/// outside of an `async fn`. /// outside of an `async fn`.
current_item: Option<Span>, current_item: Option<Span>,
@ -294,6 +298,7 @@ pub fn lower_crate<'a, 'hir>(
item_local_id_counters: Default::default(), item_local_id_counters: Default::default(),
node_id_to_hir_id: IndexVec::new(), node_id_to_hir_id: IndexVec::new(),
generator_kind: None, generator_kind: None,
task_context: None,
current_item: None, current_item: None,
lifetimes_to_define: Vec::new(), lifetimes_to_define: Vec::new(),
is_collecting_in_band_lifetimes: false, is_collecting_in_band_lifetimes: false,

View file

@ -87,7 +87,7 @@ fn decodable_substructure(
let blkarg = cx.ident_of("_d", trait_span); let blkarg = cx.ident_of("_d", trait_span);
let blkdecoder = cx.expr_ident(trait_span, blkarg); let blkdecoder = cx.expr_ident(trait_span, blkarg);
return match *substr.fields { match *substr.fields {
StaticStruct(_, ref summary) => { StaticStruct(_, ref summary) => {
let nfields = match *summary { let nfields = match *summary {
Unnamed(ref fields, _) => fields.len(), Unnamed(ref fields, _) => fields.len(),
@ -178,7 +178,7 @@ fn decodable_substructure(
) )
} }
_ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"), _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
}; }
} }
/// Creates a decoder for a single enum variant/struct: /// Creates a decoder for a single enum variant/struct:

View file

@ -53,7 +53,7 @@ fn default_substructure(
let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]); let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new()); let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
return match *substr.fields { match *substr.fields {
StaticStruct(_, ref summary) => match *summary { StaticStruct(_, ref summary) => match *summary {
Unnamed(ref fields, is_tuple) => { Unnamed(ref fields, is_tuple) => {
if !is_tuple { if !is_tuple {
@ -83,5 +83,5 @@ fn default_substructure(
DummyResult::raw_expr(trait_span, true) DummyResult::raw_expr(trait_span, true)
} }
_ => cx.span_bug(trait_span, "method in `derive(Default)`"), _ => cx.span_bug(trait_span, "method in `derive(Default)`"),
}; }
} }

View file

@ -173,7 +173,7 @@ fn encodable_substructure(
], ],
)); ));
return match *substr.fields { match *substr.fields {
Struct(_, ref fields) => { Struct(_, ref fields) => {
let emit_struct_field = cx.ident_of("emit_struct_field", trait_span); let emit_struct_field = cx.ident_of("emit_struct_field", trait_span);
let mut stmts = Vec::new(); let mut stmts = Vec::new();
@ -283,5 +283,5 @@ fn encodable_substructure(
} }
_ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"), _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"),
}; }
} }

View file

@ -489,7 +489,6 @@ impl<'a> TraitDef<'a> {
// set earlier; see // set earlier; see
// librustc_expand/expand.rs:MacroExpander::fully_expand_fragment() // librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
// librustc_expand/base.rs:Annotatable::derive_allowed() // librustc_expand/base.rs:Annotatable::derive_allowed()
return;
} }
} }
} }

View file

@ -359,7 +359,7 @@ pub mod printf {
// //
// Note: `move` used to capture copies of the cursors as they are *now*. // Note: `move` used to capture copies of the cursors as they are *now*.
let fallback = move || { let fallback = move || {
return Some(( Some((
Substitution::Format(Format { Substitution::Format(Format {
span: start.slice_between(next).unwrap(), span: start.slice_between(next).unwrap(),
parameter: None, parameter: None,
@ -371,7 +371,7 @@ pub mod printf {
position: InnerSpan::new(start.at, next.at), position: InnerSpan::new(start.at, next.at),
}), }),
next.slice_after(), next.slice_after(),
)); ))
}; };
// Next parsing state. // Next parsing state.

View file

@ -4,6 +4,7 @@ use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream; use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_expand::base::{self, *}; use rustc_expand::base::{self, *};
use rustc_expand::module::DirectoryOwnership;
use rustc_expand::panictry; use rustc_expand::panictry;
use rustc_parse::{self, new_sub_parser_from_file, parser::Parser}; use rustc_parse::{self, new_sub_parser_from_file, parser::Parser};
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
@ -11,6 +12,7 @@ use rustc_span::symbol::Symbol;
use rustc_span::{self, Pos, Span}; use rustc_span::{self, Pos, Span};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::rc::Rc;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
@ -101,7 +103,7 @@ pub fn expand_include<'cx>(
None => return DummyResult::any(sp), None => return DummyResult::any(sp),
}; };
// The file will be added to the code map by the parser // The file will be added to the code map by the parser
let file = match cx.resolve_path(file, sp) { let mut file = match cx.resolve_path(file, sp) {
Ok(f) => f, Ok(f) => f,
Err(mut err) => { Err(mut err) => {
err.emit(); err.emit();
@ -110,6 +112,15 @@ pub fn expand_include<'cx>(
}; };
let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp); let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp);
// If in the included file we have e.g., `mod bar;`,
// then the path of `bar.rs` should be relative to the directory of `file`.
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
file.pop();
cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None };
let mod_path = cx.current_expansion.module.mod_path.clone();
cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file });
struct ExpandResult<'a> { struct ExpandResult<'a> {
p: Parser<'a>, p: Parser<'a>,
} }

View file

@ -146,7 +146,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
} }
// ok, don't skip this // ok, don't skip this
return false; false
}) })
} }

View file

@ -83,7 +83,7 @@ pub fn encode(identifier: &str, bytecode: &[u8]) -> Vec<u8> {
encoded.push(0); encoded.push(0);
} }
return encoded; encoded
} }
pub struct DecodedBytecode<'a> { pub struct DecodedBytecode<'a> {
@ -132,7 +132,7 @@ impl<'a> DecodedBytecode<'a> {
pub fn bytecode(&self) -> Vec<u8> { pub fn bytecode(&self) -> Vec<u8> {
let mut data = Vec::new(); let mut data = Vec::new();
DeflateDecoder::new(self.encoded_bytecode).read_to_end(&mut data).unwrap(); DeflateDecoder::new(self.encoded_bytecode).read_to_end(&mut data).unwrap();
return data; data
} }
pub fn identifier(&self) -> &'a str { pub fn identifier(&self) -> &'a str {

View file

@ -96,15 +96,11 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
impl CodegenCx<'ll, 'tcx> { impl CodegenCx<'ll, 'tcx> {
pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
unsafe { unsafe { llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint) }
return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
}
} }
pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value { pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
unsafe { unsafe { llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint) }
return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
}
} }
pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value { pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
@ -330,7 +326,7 @@ pub fn val_ty(v: &Value) -> &Type {
pub fn bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { pub fn bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
unsafe { unsafe {
let ptr = bytes.as_ptr() as *const c_char; let ptr = bytes.as_ptr() as *const c_char;
return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True); llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True)
} }
} }

View file

@ -800,7 +800,7 @@ impl CodegenCx<'b, 'tcx> {
ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void); ifn!("llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void);
ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void); ifn!("llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
} }
return None; None
} }
} }

View file

@ -203,7 +203,7 @@ impl TypeMap<'ll, 'tcx> {
let key = self.unique_id_interner.intern(&unique_type_id); let key = self.unique_id_interner.intern(&unique_type_id);
self.type_to_unique_id.insert(type_, UniqueTypeId(key)); self.type_to_unique_id.insert(type_, UniqueTypeId(key));
return UniqueTypeId(key); UniqueTypeId(key)
} }
/// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
@ -314,7 +314,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> {
member_holding_stub, member_holding_stub,
member_descriptions, member_descriptions,
); );
return MetadataCreationResult::new(metadata_stub, true); MetadataCreationResult::new(metadata_stub, true)
} }
} }
} }
@ -364,7 +364,7 @@ fn fixed_vec_metadata(
) )
}; };
return MetadataCreationResult::new(metadata, false); MetadataCreationResult::new(metadata, false)
} }
fn vec_slice_metadata( fn vec_slice_metadata(
@ -445,7 +445,7 @@ fn subroutine_type_metadata(
return_if_metadata_created_in_meantime!(cx, unique_type_id); return_if_metadata_created_in_meantime!(cx, unique_type_id);
return MetadataCreationResult::new( MetadataCreationResult::new(
unsafe { unsafe {
llvm::LLVMRustDIBuilderCreateSubroutineType( llvm::LLVMRustDIBuilderCreateSubroutineType(
DIB(cx), DIB(cx),
@ -454,7 +454,7 @@ fn subroutine_type_metadata(
) )
}, },
false, false,
); )
} }
// FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill- // FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill-
@ -781,7 +781,7 @@ fn file_metadata_raw(
let key = (file_name, directory); let key = (file_name, directory);
match debug_context(cx).created_files.borrow_mut().entry(key) { match debug_context(cx).created_files.borrow_mut().entry(key) {
Entry::Occupied(o) => return o.get(), Entry::Occupied(o) => o.get(),
Entry::Vacant(v) => { Entry::Vacant(v) => {
let (file_name, directory) = v.key(); let (file_name, directory) = v.key();
debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory); debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
@ -831,7 +831,7 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
) )
}; };
return ty_metadata; ty_metadata
} }
fn foreign_type_metadata( fn foreign_type_metadata(
@ -1273,11 +1273,11 @@ fn prepare_union_metadata(
fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
// On MSVC we have to use the fallback mode, because LLVM doesn't // On MSVC we have to use the fallback mode, because LLVM doesn't
// lower variant parts to PDB. // lower variant parts to PDB.
return cx.sess().target.target.options.is_like_msvc cx.sess().target.target.options.is_like_msvc
// LLVM version 7 did not release with an important bug fix; // LLVM version 7 did not release with an important bug fix;
// but the required patch is in the LLVM 8. Rust LLVM reports // but the required patch is in the LLVM 8. Rust LLVM reports
// 8 as well. // 8 as well.
|| llvm_util::get_major_version() < 8; || llvm_util::get_major_version() < 8
} }
// FIXME(eddyb) maybe precompute this? Right now it's computed once // FIXME(eddyb) maybe precompute this? Right now it's computed once
@ -2075,7 +2075,7 @@ fn prepare_enum_metadata(
} }
}; };
return create_and_register_recursive_type_forward_declaration( create_and_register_recursive_type_forward_declaration(
cx, cx,
enum_type, enum_type,
unique_type_id, unique_type_id,
@ -2088,7 +2088,7 @@ fn prepare_enum_metadata(
containing_scope, containing_scope,
span, span,
}), }),
); )
} }
/// Creates debug information for a composite type, that is, anything that /// Creates debug information for a composite type, that is, anything that

View file

@ -444,7 +444,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
vec![] vec![]
}; };
return create_DIArray(DIB(cx), &template_params[..]); create_DIArray(DIB(cx), &template_params[..])
} }
fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> { fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {

View file

@ -24,9 +24,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>]) -> &'ll DIArray { pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>]) -> &'ll DIArray {
return unsafe { unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) }
llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
};
} }
#[inline] #[inline]

View file

@ -27,13 +27,13 @@ impl ArchiveRO {
/// If this archive is used with a mutable method, then an error will be /// If this archive is used with a mutable method, then an error will be
/// raised. /// raised.
pub fn open(dst: &Path) -> Result<ArchiveRO, String> { pub fn open(dst: &Path) -> Result<ArchiveRO, String> {
return unsafe { unsafe {
let s = path_to_c_string(dst); let s = path_to_c_string(dst);
let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| {
super::last_error().unwrap_or_else(|| "failed to open archive".to_owned()) super::last_error().unwrap_or_else(|| "failed to open archive".to_owned())
})?; })?;
Ok(ArchiveRO { raw: ar }) Ok(ArchiveRO { raw: ar })
}; }
} }
pub fn iter(&self) -> Iter<'_> { pub fn iter(&self) -> Iter<'_> {

View file

@ -119,7 +119,7 @@ impl Command {
for k in &self.env_remove { for k in &self.env_remove {
ret.env_remove(k); ret.env_remove(k);
} }
return ret; ret
} }
// extensions // extensions

View file

@ -852,7 +852,7 @@ impl CrateInfo {
info.missing_lang_items.insert(cnum, missing); info.missing_lang_items.insert(cnum, missing);
} }
return info; info
} }
} }
@ -887,7 +887,7 @@ pub fn provide_both(providers: &mut Providers<'_>) {
} }
} }
} }
return tcx.sess.opts.optimize; tcx.sess.opts.optimize
}; };
providers.dllimport_foreign_items = |tcx, krate| { providers.dllimport_foreign_items = |tcx, krate| {

View file

@ -125,9 +125,9 @@ impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
} else { } else {
self.node = Some(dom); self.node = Some(dom);
} }
return Some(node); Some(node)
} else { } else {
return None; None
} }
} }
} }

View file

@ -752,7 +752,7 @@ impl RustcDefaultCalls {
PrintRequest::NativeStaticLibs => {} PrintRequest::NativeStaticLibs => {}
} }
} }
return Compilation::Stop; Compilation::Stop
} }
} }

View file

@ -1,5 +1,6 @@
The length of the platform-intrinsic function `simd_shuffle` The length of the platform-intrinsic function `simd_shuffle` wasn't specified.
wasn't specified. Erroneous code example:
Erroneous code example:
```compile_fail,E0439 ```compile_fail,E0439
#![feature(platform_intrinsics)] #![feature(platform_intrinsics)]

View file

@ -778,7 +778,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool {
} }
sym::ty => token.can_begin_type(), sym::ty => token.can_begin_type(),
sym::ident => get_macro_ident(token).is_some(), sym::ident => get_macro_ident(token).is_some(),
sym::literal => token.can_begin_literal_or_bool(), sym::literal => token.can_begin_literal_maybe_minus(),
sym::vis => match token.kind { sym::vis => match token.kind {
// The follow-set of :vis + "priv" keyword + interpolated // The follow-set of :vis + "priv" keyword + interpolated
token::Comma | token::Ident(..) | token::Interpolated(_) => true, token::Comma | token::Ident(..) | token::Interpolated(_) => true,

View file

@ -175,6 +175,6 @@ impl AssertModuleSource<'tcx> {
return true; return true;
} }
debug!("check_config: no match found"); debug!("check_config: no match found");
return false; false
} }
} }

View file

@ -132,7 +132,6 @@ where
} }
Err(err) => { Err(err) => {
sess.err(&format!("failed to write dep-graph to `{}`: {}", path_buf.display(), err)); sess.err(&format!("failed to write dep-graph to `{}`: {}", path_buf.display(), err));
return;
} }
} }
} }

View file

@ -136,7 +136,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
} else { } else {
// Fast path for the common case. // Fast path for the common case.
self.relate(a.skip_binder(), b.skip_binder())?; self.relate(a.skip_binder(), b.skip_binder())?;
return Ok(a.clone()); Ok(a.clone())
} }
} }
} }

View file

@ -142,6 +142,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
.span_label(span_2, String::new()) .span_label(span_2, String::new())
.span_label(span, span_label) .span_label(span, span_label)
.emit(); .emit();
return Some(ErrorReported); Some(ErrorReported)
} }
} }

View file

@ -30,7 +30,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
let span = self.trace.cause.span; let span = self.trace.cause.span;
return self.infcx.commit_if_ok(|snapshot| { self.infcx.commit_if_ok(|snapshot| {
// First, we instantiate each bound region in the supertype with a // First, we instantiate each bound region in the supertype with a
// fresh placeholder region. // fresh placeholder region.
let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b); let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b);
@ -53,7 +53,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
debug!("higher_ranked_sub: OK result={:?}", result); debug!("higher_ranked_sub: OK result={:?}", result);
Ok(ty::Binder::bind(result)) Ok(ty::Binder::bind(result))
}); })
} }
} }

View file

@ -452,12 +452,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub); debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
*b_data = VarValue::Value(lub); *b_data = VarValue::Value(lub);
return true; true
} }
VarValue::ErrorValue => { VarValue::ErrorValue => false,
return false;
}
} }
} }
@ -804,7 +802,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
} }
} }
return graph; graph
} }
fn collect_error_for_expanding_node( fn collect_error_for_expanding_node(

View file

@ -877,7 +877,7 @@ where
// If sub-roots are equal, then `for_vid` and // If sub-roots are equal, then `for_vid` and
// `vid` are related via subtyping. // `vid` are related via subtyping.
debug!("TypeGeneralizer::tys: occurs check failed"); debug!("TypeGeneralizer::tys: occurs check failed");
return Err(TypeError::Mismatch); Err(TypeError::Mismatch)
} else { } else {
match variables.probe(vid) { match variables.probe(vid) {
TypeVariableValue::Known { value: u } => { TypeVariableValue::Known { value: u } => {
@ -898,7 +898,7 @@ where
let u = self.tcx().mk_ty_var(new_var_id); let u = self.tcx().mk_ty_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
return Ok(u); Ok(u)
} }
} }
} }

View file

@ -505,7 +505,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
self.undo_log.push(AddVar(vid)); self.undo_log.push(AddVar(vid));
} }
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin); debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
return vid; vid
} }
/// Returns the universe for the given variable. /// Returns the universe for the given variable.

View file

@ -527,10 +527,10 @@ impl Cursor<'_> {
if self.first() == '\'' { if self.first() == '\'' {
self.bump(); self.bump();
let kind = Char { terminated: true }; let kind = Char { terminated: true };
return Literal { kind, suffix_start: self.len_consumed() }; Literal { kind, suffix_start: self.len_consumed() }
} else {
Lifetime { starts_with_number }
} }
return Lifetime { starts_with_number };
} }
fn single_quoted_string(&mut self) -> bool { fn single_quoted_string(&mut self) -> bool {

View file

@ -269,7 +269,7 @@ impl EarlyLintPass for UnsafeCode {
}) })
} }
_ => return, _ => {}
} }
} }

View file

@ -273,7 +273,6 @@ fn lint_int_literal<'a, 'tcx>(
cx.sess() cx.sess()
.source_map() .source_map()
.span_to_snippet(lit.span) .span_to_snippet(lit.span)
.ok()
.expect("must get snippet from literal"), .expect("must get snippet from literal"),
t.name_str(), t.name_str(),
min, min,
@ -338,7 +337,6 @@ fn lint_uint_literal<'a, 'tcx>(
cx.sess() cx.sess()
.source_map() .source_map()
.span_to_snippet(lit.span) .span_to_snippet(lit.span)
.ok()
.expect("must get snippet from literal"), .expect("must get snippet from literal"),
t.name_str(), t.name_str(),
min, min,

View file

@ -543,7 +543,7 @@ impl EarlyLintPass for UnusedParens {
// Do not lint on `(..)` as that will result in the other arms being useless. // Do not lint on `(..)` as that will result in the other arms being useless.
Paren(_) Paren(_)
// The other cases do not contain sub-patterns. // The other cases do not contain sub-patterns.
| Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => return, | Wild | Rest | Lit(..) | MacCall(..) | Range(..) | Ident(.., None) | Path(..) => {},
// These are list-like patterns; parens can always be removed. // These are list-like patterns; parens can always be removed.
TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps { TupleStruct(_, ps) | Tuple(ps) | Slice(ps) | Or(ps) => for p in ps {
self.check_unused_parens_pat(cx, p, false, false); self.check_unused_parens_pat(cx, p, false, false);

View file

@ -264,7 +264,7 @@ impl<'a> CrateLoader<'a> {
ret = Some(cnum); ret = Some(cnum);
} }
}); });
return ret; ret
} }
fn verify_no_symbol_conflicts(&self, span: Span, root: &CrateRoot<'_>) { fn verify_no_symbol_conflicts(&self, span: Span, root: &CrateRoot<'_>) {

View file

@ -6,7 +6,7 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor;
crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> { crate fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
let mut collector = Collector { tcx, modules: Vec::new() }; let mut collector = Collector { tcx, modules: Vec::new() };
tcx.hir().krate().visit_all_item_likes(&mut collector); tcx.hir().krate().visit_all_item_likes(&mut collector);
return collector.modules; collector.modules
} }
struct Collector<'tcx> { struct Collector<'tcx> {

View file

@ -16,7 +16,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<String> {
} }
} }
return collector.args; collector.args
} }
struct Collector { struct Collector {

View file

@ -949,7 +949,7 @@ fn get_metadata_section(
let start = Instant::now(); let start = Instant::now();
let ret = get_metadata_section_imp(target, flavor, filename, loader); let ret = get_metadata_section_imp(target, flavor, filename, loader);
info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed()); info!("reading {:?} => {:?}", filename.file_name().unwrap(), start.elapsed());
return ret; ret
} }
/// A trivial wrapper for `Mmap` that implements `StableDeref`. /// A trivial wrapper for `Mmap` that implements `StableDeref`.

View file

@ -15,7 +15,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec<NativeLibrary> {
let mut collector = Collector { tcx, libs: Vec::new() }; let mut collector = Collector { tcx, libs: Vec::new() };
tcx.hir().krate().visit_all_item_likes(&mut collector); tcx.hir().krate().visit_all_item_likes(&mut collector);
collector.process_command_line(); collector.process_command_line();
return collector.libs; collector.libs
} }
crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {

View file

@ -170,7 +170,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
.iter() .iter()
.filter_map(|&(exported_symbol, export_level)| { .filter_map(|&(exported_symbol, export_level)| {
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
return Some((def_id, export_level)) Some((def_id, export_level))
} else { } else {
None None
} }

View file

@ -273,7 +273,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
assert_eq!(borrow_data.borrowed_place, *place); assert_eq!(borrow_data.borrowed_place, *place);
} }
return self.super_rvalue(rvalue, location); self.super_rvalue(rvalue, location)
} }
} }

View file

@ -500,7 +500,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
} }
} }
return None; None
} }
/// We've found an enum/struct/union type with the substitutions /// We've found an enum/struct/union type with the substitutions

View file

@ -64,13 +64,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
}; };
debug!(
"equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
normalized_input_tys, body.local_decls
);
// Equate expected input tys with those in the MIR. // Equate expected input tys with those in the MIR.
for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) { for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
// In MIR, argument N is stored in local N+1. // In MIR, argument N is stored in local N+1.
let local = Local::new(argument_index + 1); let local = Local::new(argument_index + 1);
debug!("equate_inputs_and_outputs: normalized_input_ty = {:?}", normalized_input_ty);
let mir_input_ty = body.local_decls[local].ty; let mir_input_ty = body.local_decls[local].ty;
let mir_input_span = body.local_decls[local].source_info.span; let mir_input_span = body.local_decls[local].source_info.span;
self.equate_normalized_input_or_output( self.equate_normalized_input_or_output(

View file

@ -56,7 +56,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
self.return_to_block(ret.map(|r| r.1))?; self.return_to_block(ret.map(|r| r.1))?;
self.dump_place(*dest); self.dump_place(*dest);
return Ok(true); Ok(true)
} }
/// "Intercept" a function call to a panic-related function /// "Intercept" a function call to a panic-related function

View file

@ -122,7 +122,7 @@ pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: Symbol) -> Opti
} }
} }
} }
return None; None
} }
pub struct MoveDataParamEnv<'tcx> { pub struct MoveDataParamEnv<'tcx> {
@ -171,7 +171,7 @@ where
return None; return None;
} }
} }
return None; None
}; };
let print_preflow_to = name_found(tcx.sess, attributes, sym::borrowck_graphviz_preflow); let print_preflow_to = name_found(tcx.sess, attributes, sym::borrowck_graphviz_preflow);

View file

@ -39,7 +39,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let loc_ty = self let loc_ty = self
.tcx .tcx
.type_of(self.tcx.require_lang_item(PanicLocationLangItem, None)) .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
.subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter())); .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
let loc_layout = self.layout_of(loc_ty).unwrap(); let loc_layout = self.layout_of(loc_ty).unwrap();
let location = self.allocate(loc_layout, MemoryKind::CallerLocation); let location = self.allocate(loc_layout, MemoryKind::CallerLocation);

View file

@ -604,7 +604,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
.not_undef() .not_undef()
.and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size)) .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size))
.map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?; .map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?;
let real_discr = if discr_val.layout.ty.is_signed() { let real_discr = if discr_val.layout.abi.is_signed() {
// going from layout tag type to typeck discriminant type // going from layout tag type to typeck discriminant type
// requires first sign extending with the discriminant layout // requires first sign extending with the discriminant layout
let sexted = sign_extend(bits_discr, discr_val.layout.size) as i128; let sexted = sign_extend(bits_discr, discr_val.layout.size) as i128;

View file

@ -64,7 +64,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ge => l >= r, Ge => l >= r,
_ => bug!("Invalid operation on char: {:?}", bin_op), _ => bug!("Invalid operation on char: {:?}", bin_op),
}; };
return (Scalar::from_bool(res), false, self.tcx.types.bool); (Scalar::from_bool(res), false, self.tcx.types.bool)
} }
fn binary_bool_op( fn binary_bool_op(
@ -87,7 +87,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
BitXor => l ^ r, BitXor => l ^ r,
_ => bug!("Invalid operation on bool: {:?}", bin_op), _ => bug!("Invalid operation on bool: {:?}", bin_op),
}; };
return (Scalar::from_bool(res), false, self.tcx.types.bool); (Scalar::from_bool(res), false, self.tcx.types.bool)
} }
fn binary_float_op<F: Float + Into<Scalar<M::PointerTag>>>( fn binary_float_op<F: Float + Into<Scalar<M::PointerTag>>>(
@ -113,7 +113,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Rem => ((l % r).value.into(), ty), Rem => ((l % r).value.into(), ty),
_ => bug!("invalid float op: `{:?}`", bin_op), _ => bug!("invalid float op: `{:?}`", bin_op),
}; };
return (val, false, ty); (val, false, ty)
} }
fn binary_int_op( fn binary_int_op(

View file

@ -212,9 +212,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
if self.layout.is_unsized() { if self.layout.is_unsized() {
// We need to consult `meta` metadata // We need to consult `meta` metadata
match self.layout.ty.kind { match self.layout.ty.kind {
ty::Slice(..) | ty::Str => { ty::Slice(..) | ty::Str => self.mplace.meta.unwrap_meta().to_machine_usize(cx),
return self.mplace.meta.unwrap_meta().to_machine_usize(cx);
}
_ => bug!("len not supported on unsized type {:?}", self.layout.ty), _ => bug!("len not supported on unsized type {:?}", self.layout.ty),
} }
} else { } else {
@ -920,6 +918,10 @@ where
// most likey we *are* running `typeck` right now. Investigate whether we can bail out // most likey we *are* running `typeck` right now. Investigate whether we can bail out
// on `typeck_tables().has_errors` at all const eval entry points. // on `typeck_tables().has_errors` at all const eval entry points.
debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest); debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
self.tcx.sess.delay_span_bug(
self.tcx.span,
"size-changing transmute, should have been caught by transmute checking",
);
throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty)); throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
} }
// Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want // Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want

View file

@ -240,7 +240,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match instance.def { match instance.def {
ty::InstanceDef::Intrinsic(..) => { ty::InstanceDef::Intrinsic(..) => {
assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic); assert!(caller_abi == Abi::RustIntrinsic || caller_abi == Abi::PlatformIntrinsic);
return M::call_intrinsic(self, span, instance, args, ret, unwind); M::call_intrinsic(self, span, instance, args, ret, unwind)
} }
ty::InstanceDef::VtableShim(..) ty::InstanceDef::VtableShim(..)
| ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ReifyShim(..)

View file

@ -751,7 +751,7 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx
bug!("cannot create local mono-item for {:?}", def_id) bug!("cannot create local mono-item for {:?}", def_id)
} }
return true; true
} }
/// For a given pair of source and target type that occur in an unsizing coercion, /// For a given pair of source and target type that occur in an unsizing coercion,

View file

@ -32,6 +32,7 @@ impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
let mut delete = DeleteNonCodegenStatements { tcx }; let mut delete = DeleteNonCodegenStatements { tcx };
delete.visit_body(body); delete.visit_body(body);
body.user_type_annotations.raw.clear();
} }
} }

View file

@ -483,7 +483,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
err.span_label(source_info.span, format!("{:?}", panic)); err.span_label(source_info.span, format!("{:?}", panic));
err.emit() err.emit()
}); });
return None; None
} }
fn check_unary_op( fn check_unary_op(

View file

@ -1,63 +0,0 @@
//! This pass erases all early-bound regions from the types occurring in the MIR.
//! We want to do this once just before codegen, so codegen does not have to take
//! care erasing regions all over the place.
//! N.B., we do _not_ erase regions of statements that are relevant for
//! "types-as-contracts"-validation, namely, `AcquireValid` and `ReleaseValid`.
use crate::transform::{MirPass, MirSource};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::mir::*;
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt};
struct EraseRegionsVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl EraseRegionsVisitor<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
EraseRegionsVisitor { tcx }
}
}
impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
*ty = self.tcx.erase_regions(ty);
}
fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
*region = self.tcx.lifetimes.re_erased;
}
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
*constant = self.tcx.erase_regions(constant);
}
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) {
*substs = self.tcx.erase_regions(substs);
}
fn process_projection_elem(&mut self, elem: &PlaceElem<'tcx>) -> Option<PlaceElem<'tcx>> {
if let PlaceElem::Field(field, ty) = elem {
let new_ty = self.tcx.erase_regions(ty);
if new_ty != *ty {
return Some(PlaceElem::Field(*field, new_ty));
}
}
None
}
}
pub struct EraseRegions;
impl<'tcx> MirPass<'tcx> for EraseRegions {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
EraseRegionsVisitor::new(tcx).visit_body(body);
}
}

View file

@ -357,18 +357,11 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
} }
} }
fn make_generator_state_argument_indirect<'tcx>( fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) {
tcx: TyCtxt<'tcx>,
def_id: DefId,
body: &mut BodyAndCache<'tcx>,
) {
let gen_ty = body.local_decls.raw[1].ty; let gen_ty = body.local_decls.raw[1].ty;
let region = ty::ReFree(ty::FreeRegion { scope: def_id, bound_region: ty::BoundRegion::BrEnv }); let ref_gen_ty =
tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty: gen_ty, mutbl: Mutability::Mut });
let region = tcx.mk_region(region);
let ref_gen_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut });
// Replace the by value generator argument // Replace the by value generator argument
body.local_decls.raw[1].ty = ref_gen_ty; body.local_decls.raw[1].ty = ref_gen_ty;
@ -874,7 +867,6 @@ fn elaborate_generator_drops<'tcx>(
fn create_generator_drop_shim<'tcx>( fn create_generator_drop_shim<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
transform: &TransformVisitor<'tcx>, transform: &TransformVisitor<'tcx>,
def_id: DefId,
source: MirSource<'tcx>, source: MirSource<'tcx>,
gen_ty: Ty<'tcx>, gen_ty: Ty<'tcx>,
body: &mut BodyAndCache<'tcx>, body: &mut BodyAndCache<'tcx>,
@ -912,7 +904,7 @@ fn create_generator_drop_shim<'tcx>(
local_info: LocalInfo::Other, local_info: LocalInfo::Other,
}; };
make_generator_state_argument_indirect(tcx, def_id, &mut body); make_generator_state_argument_indirect(tcx, &mut body);
// Change the generator argument from &mut to *mut // Change the generator argument from &mut to *mut
body.local_decls[SELF_ARG] = LocalDecl { body.local_decls[SELF_ARG] = LocalDecl {
@ -1047,7 +1039,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
fn create_generator_resume_function<'tcx>( fn create_generator_resume_function<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
transform: TransformVisitor<'tcx>, transform: TransformVisitor<'tcx>,
def_id: DefId,
source: MirSource<'tcx>, source: MirSource<'tcx>,
body: &mut BodyAndCache<'tcx>, body: &mut BodyAndCache<'tcx>,
can_return: bool, can_return: bool,
@ -1112,7 +1103,7 @@ fn create_generator_resume_function<'tcx>(
insert_switch(body, cases, &transform, TerminatorKind::Unreachable); insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
make_generator_state_argument_indirect(tcx, def_id, body); make_generator_state_argument_indirect(tcx, body);
make_generator_state_argument_pinned(tcx, body); make_generator_state_argument_pinned(tcx, body);
no_landing_pads(tcx, body); no_landing_pads(tcx, body);
@ -1332,11 +1323,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// Create a copy of our MIR and use it to create the drop shim for the generator // Create a copy of our MIR and use it to create the drop shim for the generator
let drop_shim = let drop_shim =
create_generator_drop_shim(tcx, &transform, def_id, source, gen_ty, body, drop_clean); create_generator_drop_shim(tcx, &transform, source, gen_ty, body, drop_clean);
body.generator_drop = Some(box drop_shim); body.generator_drop = Some(box drop_shim);
// Create the Generator::resume function // Create the Generator::resume function
create_generator_resume_function(tcx, transform, def_id, source, body, can_return); create_generator_resume_function(tcx, transform, source, body, can_return);
} }
} }

View file

@ -22,7 +22,6 @@ pub mod copy_prop;
pub mod deaggregator; pub mod deaggregator;
pub mod dump_mir; pub mod dump_mir;
pub mod elaborate_drops; pub mod elaborate_drops;
pub mod erase_regions;
pub mod generator; pub mod generator;
pub mod inline; pub mod inline;
pub mod instcombine; pub mod instcombine;
@ -296,8 +295,6 @@ fn run_optimization_passes<'tcx>(
&simplify::SimplifyCfg::new("elaborate-drops"), &simplify::SimplifyCfg::new("elaborate-drops"),
// No lifetime analysis based on borrowing can be done from here on out. // No lifetime analysis based on borrowing can be done from here on out.
// From here on out, regions are gone.
&erase_regions::EraseRegions,
// Optimizations begin. // Optimizations begin.
&unreachable_prop::UnreachablePropagation, &unreachable_prop::UnreachablePropagation,
&uninhabited_enum_branching::UninhabitedEnumBranching, &uninhabited_enum_branching::UninhabitedEnumBranching,
@ -341,6 +338,9 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyAndCache<'_> {
let mut body = body.steal(); let mut body = body.steal();
run_optimization_passes(tcx, &mut body, def_id, None); run_optimization_passes(tcx, &mut body, def_id, None);
body.ensure_predecessors(); body.ensure_predecessors();
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
tcx.arena.alloc(body) tcx.arena.alloc(body)
} }
@ -358,5 +358,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec<Promoted, BodyAndCa
body.ensure_predecessors(); body.ensure_predecessors();
} }
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
tcx.intern_promoted(promoted) tcx.intern_promoted(promoted)
} }

View file

@ -913,7 +913,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
ty, ty,
val: ty::ConstKind::Unevaluated( val: ty::ConstKind::Unevaluated(
def_id, def_id,
InternalSubsts::identity_for_item(tcx, def_id), InternalSubsts::for_item(tcx, def_id, |param, _| {
if let ty::GenericParamDefKind::Lifetime = param.kind {
tcx.lifetimes.re_erased.into()
} else {
tcx.mk_param_from_def(param)
}
}),
Some(promoted_id), Some(promoted_id),
), ),
}), }),

View file

@ -6,7 +6,7 @@ use rustc::middle::lang_items;
use rustc::middle::region; use rustc::middle::region;
use rustc::mir::*; use rustc::mir::*;
use rustc::ty::subst::Subst; use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_attr::{self as attr, UnwindAttr}; use rustc_attr::{self as attr, UnwindAttr};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
@ -43,8 +43,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
.. ..
}) })
| Node::TraitItem(hir::TraitItem { | Node::TraitItem(hir::TraitItem {
kind: kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
.. ..
}) => (*body_id, decl.output.span()), }) => (*body_id, decl.output.span()),
Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. }) Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. })
@ -128,12 +127,8 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() { let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() {
let va_list_did = let va_list_did =
tcx.require_lang_item(lang_items::VaListTypeLangItem, Some(arg.span)); tcx.require_lang_item(lang_items::VaListTypeLangItem, Some(arg.span));
let region = tcx.mk_region(ty::ReScope(region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite,
}));
tcx.type_of(va_list_did).subst(tcx, &[region.into()]) tcx.type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()])
} else { } else {
fn_sig.inputs()[index] fn_sig.inputs()[index]
}; };
@ -189,6 +184,20 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let mut body = BodyAndCache::new(body); let mut body = BodyAndCache::new(body);
body.ensure_predecessors(); body.ensure_predecessors();
// The borrow checker will replace all the regions here with its own
// inference variables. There's no point having non-erased regions here.
// The exception is `body.user_type_annotations`, which is used unmodified
// by borrow checking.
debug_assert!(
!(body.local_decls.has_free_regions()
|| body.basic_blocks().has_free_regions()
|| body.var_debug_info.has_free_regions()
|| body.yield_ty.has_free_regions()),
"Unexpected free regions in MIR: {:?}",
body,
);
body body
}) })
} }
@ -209,7 +218,7 @@ fn liberated_closure_env_ty(
}; };
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap(); let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty) tcx.erase_late_bound_regions(&closure_env_ty)
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -368,7 +377,7 @@ impl BlockContext {
} }
} }
return None; None
} }
/// Looks at the topmost frame on the BlockContext and reports /// Looks at the topmost frame on the BlockContext and reports

View file

@ -98,7 +98,7 @@ fn mirror_stmts<'a, 'tcx>(
} }
} }
} }
return result; result
} }
crate fn to_expr_ref<'a, 'tcx>( crate fn to_expr_ref<'a, 'tcx>(

View file

@ -320,7 +320,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
going with stringified version" going with stringified version"
); );
} }
return tokens_for_real; tokens_for_real
} }
fn prepend_attrs( fn prepend_attrs(

View file

@ -996,7 +996,7 @@ impl<'a> Parser<'a> {
let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs); let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs);
self.maybe_recover_from_bad_qpath(expr, true) self.maybe_recover_from_bad_qpath(expr, true)
} }
None => return Err(self.expected_expression_found()), None => Err(self.expected_expression_found()),
} }
} }
@ -1374,6 +1374,7 @@ impl<'a> Parser<'a> {
} }
/// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
/// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> { pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
maybe_whole_expr!(self); maybe_whole_expr!(self);
@ -1713,7 +1714,7 @@ impl<'a> Parser<'a> {
} }
let hi = self.token.span; let hi = self.token.span;
self.bump(); self.bump();
return Ok(self.mk_expr(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs)); Ok(self.mk_expr(lo.to(hi), ExprKind::Match(scrutinee, arms), attrs))
} }
pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> {

View file

@ -314,7 +314,7 @@ impl<'a> Parser<'a> {
" struct ".into(), " struct ".into(),
Applicability::MaybeIncorrect, // speculative Applicability::MaybeIncorrect, // speculative
); );
return Err(err); Err(err)
} else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
let ident = self.parse_ident().unwrap(); let ident = self.parse_ident().unwrap();
self.bump(); // `(` self.bump(); // `(`
@ -362,7 +362,7 @@ impl<'a> Parser<'a> {
); );
} }
} }
return Err(err); Err(err)
} else if self.look_ahead(1, |t| *t == token::Lt) { } else if self.look_ahead(1, |t| *t == token::Lt) {
let ident = self.parse_ident().unwrap(); let ident = self.parse_ident().unwrap();
self.eat_to_tokens(&[&token::Gt]); self.eat_to_tokens(&[&token::Gt]);
@ -384,7 +384,7 @@ impl<'a> Parser<'a> {
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} }
return Err(err); Err(err)
} else { } else {
Ok(()) Ok(())
} }
@ -910,7 +910,7 @@ impl<'a> Parser<'a> {
let span = self.sess.source_map().def_span(span); let span = self.sess.source_map().def_span(span);
let msg = format!("{} is not supported in {}", kind.descr(), ctx); let msg = format!("{} is not supported in {}", kind.descr(), ctx);
self.struct_span_err(span, &msg).emit(); self.struct_span_err(span, &msg).emit();
return None; None
} }
fn error_on_foreign_const(&self, span: Span, ident: Ident) { fn error_on_foreign_const(&self, span: Span, ident: Ident) {
@ -1509,7 +1509,7 @@ impl<'a> Parser<'a> {
}) })
// `extern ABI fn` // `extern ABI fn`
|| self.check_keyword(kw::Extern) || self.check_keyword(kw::Extern)
&& self.look_ahead(1, |t| t.can_begin_literal_or_bool()) && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus())
&& self.look_ahead(2, |t| t.is_keyword(kw::Fn)) && self.look_ahead(2, |t| t.is_keyword(kw::Fn))
} }

View file

@ -696,7 +696,7 @@ impl<'a> Parser<'a> {
self.look_ahead(dist, |t| { self.look_ahead(dist, |t| {
t.is_path_start() // e.g. `MY_CONST`; t.is_path_start() // e.g. `MY_CONST`;
|| t.kind == token::Dot // e.g. `.5` for recovery; || t.kind == token::Dot // e.g. `.5` for recovery;
|| t.can_begin_literal_or_bool() // e.g. `42`. || t.can_begin_literal_maybe_minus() // e.g. `42`.
|| t.is_whole_expr() || t.is_whole_expr()
}) })
} }
@ -918,7 +918,7 @@ impl<'a> Parser<'a> {
} }
err.emit(); err.emit();
} }
return Ok((fields, etc)); Ok((fields, etc))
} }
/// Recover on `...` as if it were `..` to avoid further errors. /// Recover on `...` as if it were `..` to avoid further errors.

View file

@ -278,7 +278,7 @@ impl<'a> Parser<'a> {
_ => {} _ => {}
} }
e.span_label(sp, "expected `{`"); e.span_label(sp, "expected `{`");
return Err(e); Err(e)
} }
/// Parses a block. Inner attributes are allowed. /// Parses a block. Inner attributes are allowed.

View file

@ -864,7 +864,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
first_merge, first_merge,
any_changed any_changed
); );
return any_changed; any_changed
} }
// Indicates that a local variable was *defined*; we know that no // Indicates that a local variable was *defined*; we know that no

View file

@ -222,7 +222,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
return true; return true;
} }
} }
return false; false
} }
fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) { fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
struct_span_err!( struct_span_err!(

View file

@ -30,9 +30,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: Codegen
} }
match item.kind { match item.kind {
hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => { hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true,
return true;
}
hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id)); let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
generics.requires_monomorphization(tcx) generics.requires_monomorphization(tcx)

View file

@ -465,7 +465,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> {
|v| intravisit::walk_crate(v, krate), |v| intravisit::walk_crate(v, krate),
); );
} }
return index; index
} }
/// Cross-references the feature names of unstable APIs with enabled /// Cross-references the feature names of unstable APIs with enabled

View file

@ -1423,7 +1423,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
Some(_) | None => false, Some(_) | None => false,
} }
} else { } else {
return false; false
} }
} }
@ -1837,7 +1837,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> {
&& self.tcx.is_private_dep(item_id.krate); && self.tcx.is_private_dep(item_id.krate);
log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret); log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
return ret; ret
} }
} }

View file

@ -200,7 +200,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
fn visit_pat(&mut self, pat: &'a Pat) { fn visit_pat(&mut self, pat: &'a Pat) {
match pat.kind { match pat.kind {
PatKind::MacCall(..) => return self.visit_macro_invoc(pat.id), PatKind::MacCall(..) => self.visit_macro_invoc(pat.id),
_ => visit::walk_pat(self, pat), _ => visit::walk_pat(self, pat),
} }
} }

View file

@ -1108,7 +1108,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
match binding.kind { match binding.kind {
// Never suggest the name that has binding error // Never suggest the name that has binding error
// i.e., the name that cannot be previously resolved // i.e., the name that cannot be previously resolved
NameBindingKind::Res(Res::Err, _) => return None, NameBindingKind::Res(Res::Err, _) => None,
_ => Some(&i.name), _ => Some(&i.name),
} }
} }

View file

@ -380,7 +380,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
_ => (), _ => (),
} }
}; };
return has_self_arg; has_self_arg
} }
fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) { fn followed_by_brace(&self, span: Span) -> (bool, Option<(Span, String)>) {
@ -430,7 +430,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
break; break;
} }
} }
return (followed_by_brace, closing_brace); (followed_by_brace, closing_brace)
} }
/// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment` /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`

View file

@ -133,7 +133,7 @@ impl RegionExt for Region {
/// that it corresponds to. /// that it corresponds to.
/// ///
/// FIXME. This struct gets converted to a `ResolveLifetimes` for /// FIXME. This struct gets converted to a `ResolveLifetimes` for
/// actual use. It has the same data, but indexed by `DefIndex`. This /// actual use. It has the same data, but indexed by `LocalDefId`. This
/// is silly. /// is silly.
#[derive(Default)] #[derive(Default)]
struct NamedRegionMap { struct NamedRegionMap {

View file

@ -83,7 +83,7 @@ fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKi
// line-breaks and is slow. // line-breaks and is slow.
fn fast_print_path(path: &ast::Path) -> Symbol { fn fast_print_path(path: &ast::Path) -> Symbol {
if path.segments.len() == 1 { if path.segments.len() == 1 {
return path.segments[0].ident.name; path.segments[0].ident.name
} else { } else {
let mut path_str = String::with_capacity(64); let mut path_str = String::with_capacity(64);
for (i, segment) in path.segments.iter().enumerate() { for (i, segment) in path.segments.iter().enumerate() {

View file

@ -534,7 +534,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
let variant = &def.non_enum_variant(); let variant = &def.non_enum_variant();
filter!(self.span_utils, ident.span); filter!(self.span_utils, ident.span);
let span = self.span_from_span(ident.span); let span = self.span_from_span(ident.span);
return Some(Data::RefData(Ref { Some(Data::RefData(Ref {
kind: RefKind::Variable, kind: RefKind::Variable,
span, span,
ref_id: self ref_id: self
@ -542,7 +542,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
.find_field_index(ident, variant) .find_field_index(ident, variant)
.map(|index| id_from_def_id(variant.fields[index].did)) .map(|index| id_from_def_id(variant.fields[index].did))
.unwrap_or_else(|| null_id()), .unwrap_or_else(|| null_id()),
})); }))
} }
ty::Tuple(..) => None, ty::Tuple(..) => None,
_ => { _ => {

View file

@ -1140,7 +1140,7 @@ pub fn parse_error_format(
_ => {} _ => {}
} }
return error_format; error_format
} }
fn parse_crate_edition(matches: &getopts::Matches) -> Edition { fn parse_crate_edition(matches: &getopts::Matches) -> Edition {

View file

@ -99,10 +99,6 @@ impl<'sm> CachingSourceMapView<'sm> {
cache_entry.line_end = line_bounds.1; cache_entry.line_end = line_bounds.1;
cache_entry.time_stamp = self.time_stamp; cache_entry.time_stamp = self.time_stamp;
return Some(( Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line_start))
cache_entry.file.clone(),
cache_entry.line_number,
pos - cache_entry.line_start,
));
} }
} }

Some files were not shown because too many files have changed in this diff Show more