"rustc_hir",
"rustc_incremental",
"rustc_index",
+ "rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc-rayon-core",
"rustc_graphviz",
"rustc_index",
+ "rustc_macros",
"rustc_serialize",
"smallvec 1.4.0",
"stable_deref_trait",
"annotate-snippets 0.8.0",
"atty",
"rustc_data_structures",
+ "rustc_macros",
"rustc_serialize",
"rustc_span",
"termcolor",
"rustc_errors",
"rustc_feature",
"rustc_lexer",
+ "rustc_macros",
"rustc_parse",
"rustc_serialize",
"rustc_session",
"rustc_fs_util",
"rustc_graphviz",
"rustc_hir",
+ "rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
version = "0.0.0"
dependencies = [
"arrayvec 0.5.1",
+ "rustc_macros",
"rustc_serialize",
]
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
+ "rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
"rustc_data_structures",
"rustc_errors",
"rustc_index",
+ "rustc_macros",
"rustc_serialize",
"rustc_span",
"smallvec 1.4.0",
version = "0.0.0"
dependencies = [
"indexmap",
+ "rustc_macros",
"smallvec 1.4.0",
]
"rustc_errors",
"rustc_feature",
"rustc_fs_util",
+ "rustc_macros",
"rustc_serialize",
"rustc_span",
"rustc_target",
# This only applies from stage 1 onwards, and only for Windows targets.
#control-flow-guard = false
+# Enable symbol-mangling-version v0. This can be helpful when profiling rustc,
+# as generics will be preserved in symbols (rather than erased into opaque T).
+#new-symbol-mangling = false
+
# =============================================================================
# Options for specific targets
#
-// ignore-tidy-filelength
-
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::{self, Debug};
fn replace(&mut self, key: K) -> Option<K> {
let root = Self::ensure_is_owned(&mut self.root);
match search::search_tree::<marker::Mut<'_>, K, (), K>(root.node_as_mut(), &key) {
- Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
+ Found(handle) => Some(mem::replace(handle.into_key_mut(), key)),
GoDown(handle) => {
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
.insert(());
{
let root_node = self.root.as_mut()?.node_as_mut();
match search::search_tree(root_node, key) {
- Found(handle) => Some(handle.into_kv_mut().1),
+ Found(handle) => Some(handle.into_val_mut()),
GoDown(_) => None,
}
}
pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> {
let root_node = self.root.as_mut().map(|r| r.node_as_mut());
let front = root_node.map(|rn| rn.first_leaf_edge());
- DrainFilterInner {
- length: &mut self.length,
- cur_leaf_edge: front,
- emptied_internal_root: false,
- }
+ DrainFilterInner { length: &mut self.length, cur_leaf_edge: front }
}
/// Calculates the number of elements if it is incorrect.
pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
length: &'a mut usize,
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
- emptied_internal_root: bool,
}
#[unstable(feature = "btree_drain_filter", issue = "70530")]
}
}
-impl<K, V> Drop for DrainFilterInner<'_, K, V> {
- fn drop(&mut self) {
- if self.emptied_internal_root {
- if let Some(handle) = self.cur_leaf_edge.take() {
- let root = handle.into_node().into_root_mut();
- root.pop_internal_level();
- }
- }
- }
-}
-
impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> {
/// Allow Debug implementations to predict the next element.
pub(super) fn peek(&self) -> Option<(&K, &V)> {
let (k, v) = kv.kv_mut();
if pred(k, v) {
*self.length -= 1;
- let (kv, pos) = kv.remove_kv_tracking(|_| self.emptied_internal_root = true);
+ let (kv, pos) = kv.remove_kv_tracking();
self.cur_leaf_edge = Some(pos);
return Some(kv);
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_mut(self) -> &'a mut V {
- self.handle.into_kv_mut().1
+ self.handle.into_val_mut()
}
/// Sets the value of the entry with the `OccupiedEntry`'s key,
fn remove_kv(self) -> (K, V) {
*self.length -= 1;
- let (old_kv, _) =
- self.handle.remove_kv_tracking(|root| root.into_root_mut().pop_internal_level());
+ let (old_kv, _) = self.handle.remove_kv_tracking();
old_kv
}
}
impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV> {
- /// Removes a key/value-pair from the tree, and returns that pair, as well as
- /// the leaf edge corresponding to that former pair. It's possible this leaves
- /// an empty internal root node, which the caller should subsequently pop from
- /// the map holding the tree. The caller should also decrement the map's length.
- fn remove_kv_tracking<F>(
+ /// Removes a key/value-pair from the map, and returns that pair, as well as
+ /// the leaf edge corresponding to that former pair.
+ fn remove_kv_tracking(
self,
- handle_emptied_internal_root: F,
- ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>)
- where
- F: FnOnce(NodeRef<marker::Mut<'a>, K, V, marker::Internal>),
- {
+ ) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
let (old_kv, mut pos, was_internal) = match self.force() {
Leaf(leaf) => {
let (old_kv, pos) = leaf.remove();
(old_kv, pos, false)
}
Internal(mut internal) => {
- // Replace the location freed in the internal node with the next KV,
- // and remove that next KV from its leaf.
+ // Replace the location freed in the internal node with an
+ // adjacent KV, and remove that adjacent KV from its leaf.
+ // Always choose the adjacent KV on the left side because
+ // it is typically faster to pop an element from the end
+ // of the KV arrays without needing to shift other elements.
let key_loc = internal.kv_mut().0 as *mut K;
let val_loc = internal.kv_mut().1 as *mut V;
- // Deleting from the left side is typically faster since we can
- // just pop an element from the end of the KV array without
- // needing to shift the other values.
let to_remove = internal.left_edge().descend().last_leaf_edge().left_kv().ok();
let to_remove = unsafe { unwrap_unchecked(to_remove) };
if parent.len() == 0 {
// The parent that was just emptied must be the root,
// because nodes on a lower level would not have been
- // left underfull. It has to be popped off the tree soon.
- handle_emptied_internal_root(parent);
+ // left with a single child.
+ parent.into_root_mut().pop_internal_level();
break;
} else {
cur_node = parent.forget_type();
Err(_) => return AtRoot,
};
+ // Prefer the left KV if it exists. Merging with the left side is faster,
+ // since merging happens towards the left and `node` has fewer elements.
+ // Stealing from the left side is faster, since we can pop from the end of
+ // the KV arrays.
let (is_left, mut handle) = match parent.left_kv() {
Ok(left) => (true, left),
Err(parent) => {
- match parent.right_kv() {
- Ok(right) => (false, right),
- Err(_) => {
- // The underfull node has an empty parent, so it is the only child
- // of an empty root. It is destined to become the new root, thus
- // allowed to be underfull. The empty parent should be removed later
- // by `pop_internal_level`.
- return AtRoot;
- }
- }
+ let right = unsafe { unwrap_unchecked(parent.right_kv().ok()) };
+ (false, right)
}
};
}
}
}
+
+#[cfg(test)]
+mod tests;
--- /dev/null
+use crate::boxed::Box;
+use crate::collections::btree_map::Entry::{Occupied, Vacant};
+use crate::collections::BTreeMap;
+use crate::fmt::Debug;
+use crate::rc::Rc;
+use crate::string::String;
+use crate::string::ToString;
+use crate::vec::Vec;
+use std::convert::TryFrom;
+use std::iter::FromIterator;
+use std::mem;
+use std::ops::Bound::{self, Excluded, Included, Unbounded};
+use std::ops::RangeBounds;
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use super::super::DeterministicRng;
+
+// Value of node::CAPACITY, thus capacity of a tree with a single level,
+// i.e. a tree who's root is a leaf node at height 0.
+const NODE_CAPACITY: usize = 11;
+
+// Minimum number of elements to insert in order to guarantee a tree with 2 levels,
+// i.e. a tree who's root is an internal node at height 1, with edges to leaf nodes.
+// It's not the minimum size: removing an element from such a tree does not always reduce height.
+const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
+
+// Minimum number of elements to insert in order to guarantee a tree with 3 levels,
+// i.e. a tree who's root is an internal node at height 2, with edges to more internal nodes.
+// It's not the minimum size: removing an element from such a tree does not always reduce height.
+const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_CAPACITY + 1;
+
+// Gather all references from a mutable iterator and make sure Miri notices if
+// using them is dangerous.
+fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
+ // Gather all those references.
+ let mut refs: Vec<&mut T> = iter.collect();
+ // Use them all. Twice, to be sure we got all interleavings.
+ for r in refs.iter_mut() {
+ mem::swap(dummy, r);
+ }
+ for r in refs {
+ mem::swap(dummy, r);
+ }
+}
+
+#[test]
+fn test_basic_large() {
+ let mut map = BTreeMap::new();
+ // Miri is too slow
+ let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 };
+ assert_eq!(map.len(), 0);
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 10 * i), None);
+ assert_eq!(map.len(), i + 1);
+ }
+
+ assert_eq!(map.first_key_value(), Some((&0, &0)));
+ assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1)))));
+ assert_eq!(map.first_entry().unwrap().key(), &0);
+ assert_eq!(map.last_entry().unwrap().key(), &(size - 1));
+
+ for i in 0..size {
+ assert_eq!(map.get(&i).unwrap(), &(i * 10));
+ }
+
+ for i in size..size * 2 {
+ assert_eq!(map.get(&i), None);
+ }
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 100 * i), Some(10 * i));
+ assert_eq!(map.len(), size);
+ }
+
+ for i in 0..size {
+ assert_eq!(map.get(&i).unwrap(), &(i * 100));
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(i * 2)), Some(i * 200));
+ assert_eq!(map.len(), size - i - 1);
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.get(&(2 * i)), None);
+ assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100));
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(2 * i)), None);
+ assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
+ assert_eq!(map.len(), size / 2 - i - 1);
+ }
+}
+
+#[test]
+fn test_basic_small() {
+ let mut map = BTreeMap::new();
+ // Empty, root is absent (None):
+ assert_eq!(map.remove(&1), None);
+ assert_eq!(map.len(), 0);
+ assert_eq!(map.get(&1), None);
+ assert_eq!(map.get_mut(&1), None);
+ assert_eq!(map.first_key_value(), None);
+ assert_eq!(map.last_key_value(), None);
+ assert_eq!(map.keys().count(), 0);
+ assert_eq!(map.values().count(), 0);
+ assert_eq!(map.range(..).next(), None);
+ assert_eq!(map.range(..1).next(), None);
+ assert_eq!(map.range(1..).next(), None);
+ assert_eq!(map.range(1..=1).next(), None);
+ assert_eq!(map.range(1..2).next(), None);
+ assert_eq!(map.insert(1, 1), None);
+
+ // 1 key-value pair:
+ assert_eq!(map.len(), 1);
+ assert_eq!(map.get(&1), Some(&1));
+ assert_eq!(map.get_mut(&1), Some(&mut 1));
+ assert_eq!(map.first_key_value(), Some((&1, &1)));
+ assert_eq!(map.last_key_value(), Some((&1, &1)));
+ assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
+ assert_eq!(map.values().collect::<Vec<_>>(), vec![&1]);
+ assert_eq!(map.insert(1, 2), Some(1));
+ assert_eq!(map.len(), 1);
+ assert_eq!(map.get(&1), Some(&2));
+ assert_eq!(map.get_mut(&1), Some(&mut 2));
+ assert_eq!(map.first_key_value(), Some((&1, &2)));
+ assert_eq!(map.last_key_value(), Some((&1, &2)));
+ assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
+ assert_eq!(map.values().collect::<Vec<_>>(), vec![&2]);
+ assert_eq!(map.insert(2, 4), None);
+
+ // 2 key-value pairs:
+ assert_eq!(map.len(), 2);
+ assert_eq!(map.get(&2), Some(&4));
+ assert_eq!(map.get_mut(&2), Some(&mut 4));
+ assert_eq!(map.first_key_value(), Some((&1, &2)));
+ assert_eq!(map.last_key_value(), Some((&2, &4)));
+ assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1, &2]);
+ assert_eq!(map.values().collect::<Vec<_>>(), vec![&2, &4]);
+ assert_eq!(map.remove(&1), Some(2));
+
+ // 1 key-value pair:
+ assert_eq!(map.len(), 1);
+ assert_eq!(map.get(&1), None);
+ assert_eq!(map.get_mut(&1), None);
+ assert_eq!(map.get(&2), Some(&4));
+ assert_eq!(map.get_mut(&2), Some(&mut 4));
+ assert_eq!(map.first_key_value(), Some((&2, &4)));
+ assert_eq!(map.last_key_value(), Some((&2, &4)));
+ assert_eq!(map.keys().collect::<Vec<_>>(), vec![&2]);
+ assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
+ assert_eq!(map.remove(&2), Some(4));
+
+ // Empty but root is owned (Some(...)):
+ assert_eq!(map.len(), 0);
+ assert_eq!(map.get(&1), None);
+ assert_eq!(map.get_mut(&1), None);
+ assert_eq!(map.first_key_value(), None);
+ assert_eq!(map.last_key_value(), None);
+ assert_eq!(map.keys().count(), 0);
+ assert_eq!(map.values().count(), 0);
+ assert_eq!(map.range(..).next(), None);
+ assert_eq!(map.range(..1).next(), None);
+ assert_eq!(map.range(1..).next(), None);
+ assert_eq!(map.range(1..=1).next(), None);
+ assert_eq!(map.range(1..2).next(), None);
+ assert_eq!(map.remove(&1), None);
+}
+
+#[test]
+fn test_iter() {
+ // Miri is too slow
+ let size = if cfg!(miri) { 200 } else { 10000 };
+
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test<T>(size: usize, mut iter: T)
+ where
+ T: Iterator<Item = (usize, usize)>,
+ {
+ for i in 0..size {
+ assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
+ assert_eq!(iter.next().unwrap(), (i, i));
+ }
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ }
+ test(size, map.iter().map(|(&k, &v)| (k, v)));
+ test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
+ test(size, map.into_iter());
+}
+
+#[test]
+fn test_iter_rev() {
+ // Miri is too slow
+ let size = if cfg!(miri) { 200 } else { 10000 };
+
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test<T>(size: usize, mut iter: T)
+ where
+ T: Iterator<Item = (usize, usize)>,
+ {
+ for i in 0..size {
+ assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
+ assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1));
+ }
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ }
+ test(size, map.iter().rev().map(|(&k, &v)| (k, v)));
+ test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v)));
+ test(size, map.into_iter().rev());
+}
+
+/// Specifically tests iter_mut's ability to mutate the value of pairs in-line
+fn do_test_iter_mut_mutation<T>(size: usize)
+where
+ T: Copy + Debug + Ord + TryFrom<usize>,
+ <T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug,
+{
+ let zero = T::try_from(0).unwrap();
+ let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect();
+
+ // Forward and backward iteration sees enough pairs (also tested elsewhere)
+ assert_eq!(map.iter_mut().count(), size);
+ assert_eq!(map.iter_mut().rev().count(), size);
+
+ // Iterate forwards, trying to mutate to unique values
+ for (i, (k, v)) in map.iter_mut().enumerate() {
+ assert_eq!(*k, T::try_from(i).unwrap());
+ assert_eq!(*v, zero);
+ *v = T::try_from(i + 1).unwrap();
+ }
+
+ // Iterate backwards, checking that mutations succeeded and trying to mutate again
+ for (i, (k, v)) in map.iter_mut().rev().enumerate() {
+ assert_eq!(*k, T::try_from(size - i - 1).unwrap());
+ assert_eq!(*v, T::try_from(size - i).unwrap());
+ *v = T::try_from(2 * size - i).unwrap();
+ }
+
+ // Check that backward mutations succeeded
+ for (i, (k, v)) in map.iter_mut().enumerate() {
+ assert_eq!(*k, T::try_from(i).unwrap());
+ assert_eq!(*v, T::try_from(size + i + 1).unwrap());
+ }
+}
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
+#[repr(align(32))]
+struct Align32(usize);
+
+impl TryFrom<usize> for Align32 {
+ type Error = ();
+
+ fn try_from(s: usize) -> Result<Align32, ()> {
+ Ok(Align32(s))
+ }
+}
+
+#[test]
+fn test_iter_mut_mutation() {
+ // Check many alignments and trees with roots at various heights.
+ do_test_iter_mut_mutation::<u8>(0);
+ do_test_iter_mut_mutation::<u8>(1);
+ do_test_iter_mut_mutation::<u8>(MIN_INSERTS_HEIGHT_1);
+ do_test_iter_mut_mutation::<u8>(127); // not enough unique values to test MIN_INSERTS_HEIGHT_2
+ do_test_iter_mut_mutation::<u16>(1);
+ do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_1);
+ do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_2);
+ do_test_iter_mut_mutation::<u32>(1);
+ do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_1);
+ do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_2);
+ do_test_iter_mut_mutation::<u64>(1);
+ do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_1);
+ do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_2);
+ do_test_iter_mut_mutation::<u128>(1);
+ do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_1);
+ do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_2);
+ do_test_iter_mut_mutation::<Align32>(1);
+ do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_1);
+ do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_2);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_values_mut() {
+ let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
+ test_all_refs(&mut 13, a.values_mut());
+}
+
+#[test]
+fn test_values_mut_mutation() {
+ let mut a = BTreeMap::new();
+ a.insert(1, String::from("hello"));
+ a.insert(2, String::from("goodbye"));
+
+ for value in a.values_mut() {
+ value.push_str("!");
+ }
+
+ let values: Vec<String> = a.values().cloned().collect();
+ assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_iter_entering_root_twice() {
+ let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect();
+ let mut it = map.iter_mut();
+ let front = it.next().unwrap();
+ let back = it.next_back().unwrap();
+ assert_eq!(front, (&0, &mut 0));
+ assert_eq!(back, (&1, &mut 1));
+ *front.1 = 24;
+ *back.1 = 42;
+ assert_eq!(front, (&0, &mut 24));
+ assert_eq!(back, (&1, &mut 42));
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_iter_descending_to_same_node_twice() {
+ let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect();
+ let mut it = map.iter_mut();
+ // Descend into first child.
+ let front = it.next().unwrap();
+ // Descend into first child again, after running through second child.
+ while it.next_back().is_some() {}
+ // Check immutable access.
+ assert_eq!(front, (&0, &mut 0));
+ // Perform mutable access.
+ *front.1 = 42;
+}
+
+#[test]
+fn test_iter_mixed() {
+ // Miri is too slow
+ let size = if cfg!(miri) { 200 } else { 10000 };
+
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test<T>(size: usize, mut iter: T)
+ where
+ T: Iterator<Item = (usize, usize)> + DoubleEndedIterator,
+ {
+ for i in 0..size / 4 {
+ assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
+ assert_eq!(iter.next().unwrap(), (i, i));
+ assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1));
+ }
+ for i in size / 4..size * 3 / 4 {
+ assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i)));
+ assert_eq!(iter.next().unwrap(), (i, i));
+ }
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ }
+ test(size, map.iter().map(|(&k, &v)| (k, v)));
+ test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
+ test(size, map.into_iter());
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
+fn test_iter_min_max() {
+ let mut a = BTreeMap::new();
+ assert_eq!(a.iter().min(), None);
+ assert_eq!(a.iter().max(), None);
+ assert_eq!(a.iter_mut().min(), None);
+ assert_eq!(a.iter_mut().max(), None);
+ assert_eq!(a.range(..).min(), None);
+ assert_eq!(a.range(..).max(), None);
+ assert_eq!(a.range_mut(..).min(), None);
+ assert_eq!(a.range_mut(..).max(), None);
+ assert_eq!(a.keys().min(), None);
+ assert_eq!(a.keys().max(), None);
+ assert_eq!(a.values().min(), None);
+ assert_eq!(a.values().max(), None);
+ assert_eq!(a.values_mut().min(), None);
+ assert_eq!(a.values_mut().max(), None);
+ a.insert(1, 42);
+ a.insert(2, 24);
+ assert_eq!(a.iter().min(), Some((&1, &42)));
+ assert_eq!(a.iter().max(), Some((&2, &24)));
+ assert_eq!(a.iter_mut().min(), Some((&1, &mut 42)));
+ assert_eq!(a.iter_mut().max(), Some((&2, &mut 24)));
+ assert_eq!(a.range(..).min(), Some((&1, &42)));
+ assert_eq!(a.range(..).max(), Some((&2, &24)));
+ assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42)));
+ assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24)));
+ assert_eq!(a.keys().min(), Some(&1));
+ assert_eq!(a.keys().max(), Some(&2));
+ assert_eq!(a.values().min(), Some(&24));
+ assert_eq!(a.values().max(), Some(&42));
+ assert_eq!(a.values_mut().min(), Some(&mut 24));
+ assert_eq!(a.values_mut().max(), Some(&mut 42));
+}
+
+fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> {
+ map.range(range)
+ .map(|(&k, &v)| {
+ assert_eq!(k, v);
+ k
+ })
+ .collect()
+}
+
+#[test]
+fn test_range_small() {
+ let size = 4;
+
+ let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+ let all: Vec<_> = (1..=size).collect();
+ let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+ assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+ assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+ assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+ assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+ assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+ assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+ assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+ assert_eq!(range_keys(&map, ..), all);
+
+ assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+ assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+ assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+ assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+ assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+ assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+ assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+ assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+ assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+ assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+ assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+ assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+ assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+ assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
+
+ assert_eq!(range_keys(&map, ..3), vec![1, 2]);
+ assert_eq!(range_keys(&map, 3..), vec![3, 4]);
+ assert_eq!(range_keys(&map, 2..=3), vec![2, 3]);
+}
+
+#[test]
+fn test_range_height_1() {
+ // Tests tree with a root and 2 leaves. Depending on details we don't want or need
+ // to rely upon, the single key at the root will be 6 or 7.
+
+ let map: BTreeMap<_, _> = (1..=MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i)).collect();
+ for &root in &[6, 7] {
+ assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]);
+ assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]);
+ assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]);
+
+ assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]);
+ assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]);
+ assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]);
+ assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]);
+ }
+}
+
+#[test]
+fn test_range_large() {
+ let size = 200;
+
+ let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+ let all: Vec<_> = (1..=size).collect();
+ let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+ assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+ assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+ assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+ assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+ assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+ assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+ assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+ assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+ assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+ assert_eq!(range_keys(&map, ..), all);
+
+ assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+ assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+ assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+ assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+ assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+ assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+ assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+ assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+ assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+ assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+ assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+ assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+ assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+ assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+ assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+ assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+ assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+ assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
+
+ fn check<'a, L, R>(lhs: L, rhs: R)
+ where
+ L: IntoIterator<Item = (&'a i32, &'a i32)>,
+ R: IntoIterator<Item = (&'a i32, &'a i32)>,
+ {
+ let lhs: Vec<_> = lhs.into_iter().collect();
+ let rhs: Vec<_> = rhs.into_iter().collect();
+ assert_eq!(lhs, rhs);
+ }
+
+ check(map.range(..=100), map.range(..101));
+ check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
+ check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]);
+}
+
+#[test]
+fn test_range_inclusive_max_value() {
+ let max = usize::MAX;
+ let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
+
+ assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
+}
+
+#[test]
+fn test_range_equal_empty_cases() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ assert_eq!(map.range((Included(2), Excluded(2))).next(), None);
+ assert_eq!(map.range((Excluded(2), Included(2))).next(), None);
+}
+
+#[test]
+#[should_panic]
+fn test_range_equal_excluded() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Excluded(2), Excluded(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_1() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Included(3), Included(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_2() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Included(3), Excluded(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_3() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Excluded(3), Included(2)));
+}
+
+#[test]
+#[should_panic]
+fn test_range_backwards_4() {
+ let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
+ map.range((Excluded(3), Excluded(2)));
+}
+
+#[test]
+fn test_range_1000() {
+ // Miri is too slow
+ let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 };
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
+ let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v));
+ let mut pairs = (0..size).map(|i| (i, i));
+
+ for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+ assert_eq!(kv, pair);
+ }
+ assert_eq!(kvs.next(), None);
+ assert_eq!(pairs.next(), None);
+ }
+ test(&map, size, Included(&0), Excluded(&size));
+ test(&map, size, Unbounded, Excluded(&size));
+ test(&map, size, Included(&0), Included(&(size - 1)));
+ test(&map, size, Unbounded, Included(&(size - 1)));
+ test(&map, size, Included(&0), Unbounded);
+ test(&map, size, Unbounded, Unbounded);
+}
+
+#[test]
+fn test_range_borrowed_key() {
+ let mut map = BTreeMap::new();
+ map.insert("aardvark".to_string(), 1);
+ map.insert("baboon".to_string(), 2);
+ map.insert("coyote".to_string(), 3);
+ map.insert("dingo".to_string(), 4);
+ // NOTE: would like to use simply "b".."d" here...
+ let mut iter = map.range::<str, _>((Included("b"), Excluded("d")));
+ assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
+ assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
+ assert_eq!(iter.next(), None);
+}
+
+#[test]
+fn test_range() {
+ let size = 200;
+ // Miri is too slow
+ let step = if cfg!(miri) { 66 } else { 1 };
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ for i in (0..size).step_by(step) {
+ for j in (i..size).step_by(step) {
+ let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
+ let mut pairs = (i..=j).map(|i| (i, i));
+
+ for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+ assert_eq!(kv, pair);
+ }
+ assert_eq!(kvs.next(), None);
+ assert_eq!(pairs.next(), None);
+ }
+ }
+}
+
+#[test]
+fn test_range_mut() {
+ let size = 200;
+ // Miri is too slow
+ let step = if cfg!(miri) { 66 } else { 1 };
+ let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+
+ for i in (0..size).step_by(step) {
+ for j in (i..size).step_by(step) {
+ let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
+ let mut pairs = (i..=j).map(|i| (i, i));
+
+ for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
+ assert_eq!(kv, pair);
+ }
+ assert_eq!(kvs.next(), None);
+ assert_eq!(pairs.next(), None);
+ }
+ }
+}
+
+mod test_drain_filter {
+ use super::*;
+
+ #[test]
+ fn empty() {
+ let mut map: BTreeMap<i32, i32> = BTreeMap::new();
+ map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
+ assert!(map.is_empty());
+ }
+
+ #[test]
+ fn consuming_nothing() {
+ let pairs = (0..3).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
+ }
+
+ #[test]
+ fn consuming_all() {
+ let pairs = (0..3).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ assert!(map.drain_filter(|_, _| true).eq(pairs));
+ }
+
+ #[test]
+ fn mutating_and_keeping() {
+ let pairs = (0..3).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ assert!(
+ map.drain_filter(|_, v| {
+ *v += 6;
+ false
+ })
+ .eq(std::iter::empty())
+ );
+ assert!(map.keys().copied().eq(0..3));
+ assert!(map.values().copied().eq(6..9));
+ }
+
+ #[test]
+ fn mutating_and_removing() {
+ let pairs = (0..3).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ assert!(
+ map.drain_filter(|_, v| {
+ *v += 6;
+ true
+ })
+ .eq((0..3).map(|i| (i, i + 6)))
+ );
+ assert!(map.is_empty());
+ }
+
+ #[test]
+ fn underfull_keeping_all() {
+ let pairs = (0..3).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ map.drain_filter(|_, _| false);
+ assert!(map.keys().copied().eq(0..3));
+ }
+
+ #[test]
+ fn underfull_removing_one() {
+ let pairs = (0..3).map(|i| (i, i));
+ for doomed in 0..3 {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i == doomed);
+ assert_eq!(map.len(), 2);
+ }
+ }
+
+ #[test]
+ fn underfull_keeping_one() {
+ let pairs = (0..3).map(|i| (i, i));
+ for sacred in 0..3 {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i != sacred);
+ assert!(map.keys().copied().eq(sacred..=sacred));
+ }
+ }
+
+ #[test]
+ fn underfull_removing_all() {
+ let pairs = (0..3).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ map.drain_filter(|_, _| true);
+ assert!(map.is_empty());
+ }
+
+ #[test]
+ fn height_0_keeping_all() {
+ let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ map.drain_filter(|_, _| false);
+ assert!(map.keys().copied().eq(0..NODE_CAPACITY));
+ }
+
+ #[test]
+ fn height_0_removing_one() {
+ let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+ for doomed in 0..NODE_CAPACITY {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i == doomed);
+ assert_eq!(map.len(), NODE_CAPACITY - 1);
+ }
+ }
+
+ #[test]
+ fn height_0_keeping_one() {
+ let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+ for sacred in 0..NODE_CAPACITY {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i != sacred);
+ assert!(map.keys().copied().eq(sacred..=sacred));
+ }
+ }
+
+ #[test]
+ fn height_0_removing_all() {
+ let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ map.drain_filter(|_, _| true);
+ assert!(map.is_empty());
+ }
+
+ #[test]
+ fn height_0_keeping_half() {
+ let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect();
+ assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8);
+ assert_eq!(map.len(), 8);
+ }
+
+ #[test]
+ fn height_1_removing_all() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ map.drain_filter(|_, _| true);
+ assert!(map.is_empty());
+ }
+
+ #[test]
+ fn height_1_removing_one() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
+ for doomed in 0..MIN_INSERTS_HEIGHT_1 {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i == doomed);
+ assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
+ }
+ }
+
+ #[test]
+ fn height_1_keeping_one() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
+ for sacred in 0..MIN_INSERTS_HEIGHT_1 {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i != sacred);
+ assert!(map.keys().copied().eq(sacred..=sacred));
+ }
+ }
+
+ #[cfg(not(miri))] // Miri is too slow
+ #[test]
+ fn height_2_removing_one() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+ for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i == doomed);
+ assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
+ }
+ }
+
+ #[cfg(not(miri))] // Miri is too slow
+ #[test]
+ fn height_2_keeping_one() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+ for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
+ let mut map: BTreeMap<_, _> = pairs.clone().collect();
+ map.drain_filter(|i, _| *i != sacred);
+ assert!(map.keys().copied().eq(sacred..=sacred));
+ }
+ }
+
+ #[test]
+ fn height_2_removing_all() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+ let mut map: BTreeMap<_, _> = pairs.collect();
+ map.drain_filter(|_, _| true);
+ assert!(map.is_empty());
+ }
+
+ #[test]
+ fn drop_panic_leak() {
+ static PREDS: AtomicUsize = AtomicUsize::new(0);
+ static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+ struct D;
+ impl Drop for D {
+ fn drop(&mut self) {
+ if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+ panic!("panic in `drop`");
+ }
+ }
+ }
+
+ // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
+ let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
+
+ catch_unwind(move || {
+ drop(map.drain_filter(|i, _| {
+ PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+ true
+ }))
+ })
+ .unwrap_err();
+
+ assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+ assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+ }
+
+ #[test]
+ fn pred_panic_leak() {
+ static PREDS: AtomicUsize = AtomicUsize::new(0);
+ static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+ struct D;
+ impl Drop for D {
+ fn drop(&mut self) {
+ DROPS.fetch_add(1, Ordering::SeqCst);
+ }
+ }
+
+ // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
+ let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
+
+ catch_unwind(AssertUnwindSafe(|| {
+ drop(map.drain_filter(|i, _| {
+ PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+ match i {
+ 0 => true,
+ _ => panic!(),
+ }
+ }))
+ }))
+ .unwrap_err();
+
+ assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+ assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+ assert_eq!(map.len(), 2);
+ assert_eq!(map.first_entry().unwrap().key(), &4);
+ assert_eq!(map.last_entry().unwrap().key(), &8);
+ }
+
+ // Same as above, but attempt to use the iterator again after the panic in the predicate
+ #[test]
+ fn pred_panic_reuse() {
+ static PREDS: AtomicUsize = AtomicUsize::new(0);
+ static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+ struct D;
+ impl Drop for D {
+ fn drop(&mut self) {
+ DROPS.fetch_add(1, Ordering::SeqCst);
+ }
+ }
+
+ // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
+ let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
+
+ {
+ let mut it = map.drain_filter(|i, _| {
+ PREDS.fetch_add(1usize << i, Ordering::SeqCst);
+ match i {
+ 0 => true,
+ _ => panic!(),
+ }
+ });
+ catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
+ // Iterator behaviour after a panic is explicitly unspecified,
+ // so this is just the current implementation:
+ let result = catch_unwind(AssertUnwindSafe(|| it.next()));
+ assert!(matches!(result, Ok(None)));
+ }
+
+ assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+ assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+ assert_eq!(map.len(), 2);
+ assert_eq!(map.first_entry().unwrap().key(), &4);
+ assert_eq!(map.last_entry().unwrap().key(), &8);
+ }
+}
+
+#[test]
+fn test_borrow() {
+ // make sure these compile -- using the Borrow trait
+ {
+ let mut map = BTreeMap::new();
+ map.insert("0".to_string(), 1);
+ assert_eq!(map["0"], 1);
+ }
+
+ {
+ let mut map = BTreeMap::new();
+ map.insert(Box::new(0), 1);
+ assert_eq!(map[&0], 1);
+ }
+
+ {
+ let mut map = BTreeMap::new();
+ map.insert(Box::new([0, 1]) as Box<[i32]>, 1);
+ assert_eq!(map[&[0, 1][..]], 1);
+ }
+
+ {
+ let mut map = BTreeMap::new();
+ map.insert(Rc::new(0), 1);
+ assert_eq!(map[&0], 1);
+ }
+}
+
+#[test]
+fn test_entry() {
+ let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
+
+ let mut map: BTreeMap<_, _> = xs.iter().cloned().collect();
+
+ // Existing key (insert)
+ match map.entry(1) {
+ Vacant(_) => unreachable!(),
+ Occupied(mut view) => {
+ assert_eq!(view.get(), &10);
+ assert_eq!(view.insert(100), 10);
+ }
+ }
+ assert_eq!(map.get(&1).unwrap(), &100);
+ assert_eq!(map.len(), 6);
+
+ // Existing key (update)
+ match map.entry(2) {
+ Vacant(_) => unreachable!(),
+ Occupied(mut view) => {
+ let v = view.get_mut();
+ *v *= 10;
+ }
+ }
+ assert_eq!(map.get(&2).unwrap(), &200);
+ assert_eq!(map.len(), 6);
+
+ // Existing key (take)
+ match map.entry(3) {
+ Vacant(_) => unreachable!(),
+ Occupied(view) => {
+ assert_eq!(view.remove(), 30);
+ }
+ }
+ assert_eq!(map.get(&3), None);
+ assert_eq!(map.len(), 5);
+
+ // Inexistent key (insert)
+ match map.entry(10) {
+ Occupied(_) => unreachable!(),
+ Vacant(view) => {
+ assert_eq!(*view.insert(1000), 1000);
+ }
+ }
+ assert_eq!(map.get(&10).unwrap(), &1000);
+ assert_eq!(map.len(), 6);
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = BTreeMap::new();
+ a.insert(1, "one");
+ let mut b = BTreeMap::new();
+ b.insert(2, "two");
+ b.insert(3, "three");
+
+ a.extend(&b);
+
+ assert_eq!(a.len(), 3);
+ assert_eq!(a[&1], "one");
+ assert_eq!(a[&2], "two");
+ assert_eq!(a[&3], "three");
+}
+
+#[test]
+fn test_zst() {
+ let mut m = BTreeMap::new();
+ assert_eq!(m.len(), 0);
+
+ assert_eq!(m.insert((), ()), None);
+ assert_eq!(m.len(), 1);
+
+ assert_eq!(m.insert((), ()), Some(()));
+ assert_eq!(m.len(), 1);
+ assert_eq!(m.iter().count(), 1);
+
+ m.clear();
+ assert_eq!(m.len(), 0);
+
+ for _ in 0..100 {
+ m.insert((), ());
+ }
+
+ assert_eq!(m.len(), 1);
+ assert_eq!(m.iter().count(), 1);
+}
+
+// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
+// do not cause segfaults when used with zero-sized values. All other map behavior is
+// undefined.
+#[test]
+fn test_bad_zst() {
+ use std::cmp::Ordering;
+
+ struct Bad;
+
+ impl PartialEq for Bad {
+ fn eq(&self, _: &Self) -> bool {
+ false
+ }
+ }
+
+ impl Eq for Bad {}
+
+ impl PartialOrd for Bad {
+ fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
+ Some(Ordering::Less)
+ }
+ }
+
+ impl Ord for Bad {
+ fn cmp(&self, _: &Self) -> Ordering {
+ Ordering::Less
+ }
+ }
+
+ let mut m = BTreeMap::new();
+
+ for _ in 0..100 {
+ m.insert(Bad, Bad);
+ }
+}
+
+#[test]
+fn test_clone() {
+ let mut map = BTreeMap::new();
+ let size = MIN_INSERTS_HEIGHT_1;
+ assert_eq!(map.len(), 0);
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 10 * i), None);
+ assert_eq!(map.len(), i + 1);
+ assert_eq!(map, map.clone());
+ }
+
+ for i in 0..size {
+ assert_eq!(map.insert(i, 100 * i), Some(10 * i));
+ assert_eq!(map.len(), size);
+ assert_eq!(map, map.clone());
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(i * 2)), Some(i * 200));
+ assert_eq!(map.len(), size - i - 1);
+ assert_eq!(map, map.clone());
+ }
+
+ for i in 0..size / 2 {
+ assert_eq!(map.remove(&(2 * i)), None);
+ assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
+ assert_eq!(map.len(), size / 2 - i - 1);
+ assert_eq!(map, map.clone());
+ }
+
+ // Test a tree with 2 chock-full levels and a tree with 3 levels.
+ map = (1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
+ assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
+ assert_eq!(map, map.clone());
+ map.insert(0, 0);
+ assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2);
+ assert_eq!(map, map.clone());
+}
+
+#[test]
+fn test_clone_from() {
+ let mut map1 = BTreeMap::new();
+ let max_size = MIN_INSERTS_HEIGHT_1;
+
+ // Range to max_size inclusive, because i is the size of map1 being tested.
+ for i in 0..=max_size {
+ let mut map2 = BTreeMap::new();
+ for j in 0..i {
+ let mut map1_copy = map2.clone();
+ map1_copy.clone_from(&map1); // small cloned from large
+ assert_eq!(map1_copy, map1);
+ let mut map2_copy = map1.clone();
+ map2_copy.clone_from(&map2); // large cloned from small
+ assert_eq!(map2_copy, map2);
+ map2.insert(100 * j + 1, 2 * j + 1);
+ }
+ map2.clone_from(&map1); // same length
+ assert_eq!(map2, map1);
+ map1.insert(i, 10 * i);
+ }
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_variance() {
+ use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values};
+
+ fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
+ v
+ }
+ fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
+ v
+ }
+ fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
+ v
+ }
+ fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
+ v
+ }
+ fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
+ v
+ }
+ fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
+ v
+ }
+ fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
+ v
+ }
+ fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
+ v
+ }
+ fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> {
+ v
+ }
+ fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> {
+ v
+ }
+}
+
+#[test]
+fn test_occupied_entry_key() {
+ let mut a = BTreeMap::new();
+ let key = "hello there";
+ let value = "value goes here";
+ assert!(a.is_empty());
+ a.insert(key.clone(), value.clone());
+ assert_eq!(a.len(), 1);
+ assert_eq!(a[key], value);
+
+ match a.entry(key.clone()) {
+ Vacant(_) => panic!(),
+ Occupied(e) => assert_eq!(key, *e.key()),
+ }
+ assert_eq!(a.len(), 1);
+ assert_eq!(a[key], value);
+}
+
+#[test]
+fn test_vacant_entry_key() {
+ let mut a = BTreeMap::new();
+ let key = "hello there";
+ let value = "value goes here";
+
+ assert!(a.is_empty());
+ match a.entry(key.clone()) {
+ Occupied(_) => panic!(),
+ Vacant(e) => {
+ assert_eq!(key, *e.key());
+ e.insert(value.clone());
+ }
+ }
+ assert_eq!(a.len(), 1);
+ assert_eq!(a[key], value);
+}
+
+#[test]
+fn test_first_last_entry() {
+ let mut a = BTreeMap::new();
+ assert!(a.first_entry().is_none());
+ assert!(a.last_entry().is_none());
+ a.insert(1, 42);
+ assert_eq!(a.first_entry().unwrap().key(), &1);
+ assert_eq!(a.last_entry().unwrap().key(), &1);
+ a.insert(2, 24);
+ assert_eq!(a.first_entry().unwrap().key(), &1);
+ assert_eq!(a.last_entry().unwrap().key(), &2);
+ a.insert(0, 6);
+ assert_eq!(a.first_entry().unwrap().key(), &0);
+ assert_eq!(a.last_entry().unwrap().key(), &2);
+ let (k1, v1) = a.first_entry().unwrap().remove_entry();
+ assert_eq!(k1, 0);
+ assert_eq!(v1, 6);
+ let (k2, v2) = a.last_entry().unwrap().remove_entry();
+ assert_eq!(k2, 2);
+ assert_eq!(v2, 24);
+ assert_eq!(a.first_entry().unwrap().key(), &1);
+ assert_eq!(a.last_entry().unwrap().key(), &1);
+}
+
+macro_rules! create_append_test {
+ ($name:ident, $len:expr) => {
+ #[test]
+ fn $name() {
+ let mut a = BTreeMap::new();
+ for i in 0..8 {
+ a.insert(i, i);
+ }
+
+ let mut b = BTreeMap::new();
+ for i in 5..$len {
+ b.insert(i, 2 * i);
+ }
+
+ a.append(&mut b);
+
+ assert_eq!(a.len(), $len);
+ assert_eq!(b.len(), 0);
+
+ for i in 0..$len {
+ if i < 5 {
+ assert_eq!(a[&i], i);
+ } else {
+ assert_eq!(a[&i], 2 * i);
+ }
+ }
+
+ assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1)));
+ assert_eq!(a.insert($len - 1, 20), None);
+ }
+ };
+}
+
+// These are mostly for testing the algorithm that "fixes" the right edge after insertion.
+// Single node.
+create_append_test!(test_append_9, 9);
+// Two leafs that don't need fixing.
+create_append_test!(test_append_17, 17);
+// Two leafs where the second one ends up underfull and needs stealing at the end.
+create_append_test!(test_append_14, 14);
+// Two leafs where the second one ends up empty because the insertion finished at the root.
+create_append_test!(test_append_12, 12);
+// Three levels; insertion finished at the root.
+create_append_test!(test_append_144, 144);
+// Three levels; insertion finished at leaf while there is an empty node on the second level.
+create_append_test!(test_append_145, 145);
+// Tests for several randomly chosen sizes.
+create_append_test!(test_append_170, 170);
+create_append_test!(test_append_181, 181);
+#[cfg(not(miri))] // Miri is too slow
+create_append_test!(test_append_239, 239);
+#[cfg(not(miri))] // Miri is too slow
+create_append_test!(test_append_1700, 1700);
+
+fn rand_data(len: usize) -> Vec<(u32, u32)> {
+ let mut rng = DeterministicRng::new();
+ Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
+}
+
+#[test]
+fn test_split_off_empty_right() {
+ let mut data = rand_data(173);
+
+ let mut map = BTreeMap::from_iter(data.clone());
+ let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
+
+ data.sort();
+ assert!(map.into_iter().eq(data));
+ assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+ let mut data = rand_data(314);
+
+ let mut map = BTreeMap::from_iter(data.clone());
+ let right = map.split_off(&data.iter().min().unwrap().0);
+
+ data.sort();
+ assert!(map.into_iter().eq(None));
+ assert!(right.into_iter().eq(data));
+}
+
+// In a tree with 3 levels, if all but a part of the first leaf node is split off,
+// make sure fix_top eliminates both top levels.
+#[test]
+fn test_split_off_tiny_left_height_2() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+ let mut left: BTreeMap<_, _> = pairs.clone().collect();
+ let right = left.split_off(&1);
+ assert_eq!(left.len(), 1);
+ assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1);
+ assert_eq!(*left.first_key_value().unwrap().0, 0);
+ assert_eq!(*right.first_key_value().unwrap().0, 1);
+}
+
+// In a tree with 3 levels, if only part of the last leaf node is split off,
+// make sure fix_top eliminates both top levels.
+#[test]
+fn test_split_off_tiny_right_height_2() {
+ let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
+ let last = MIN_INSERTS_HEIGHT_2 - 1;
+ let mut left: BTreeMap<_, _> = pairs.clone().collect();
+ assert_eq!(*left.last_key_value().unwrap().0, last);
+ let right = left.split_off(&last);
+ assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1);
+ assert_eq!(right.len(), 1);
+ assert_eq!(*left.last_key_value().unwrap().0, last - 1);
+ assert_eq!(*right.last_key_value().unwrap().0, last);
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+ // Miri is too slow
+ let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
+ // special case with maximum height.
+ data.sort();
+
+ let mut map = BTreeMap::from_iter(data.clone());
+ let key = data[data.len() / 2].0;
+ let right = map.split_off(&key);
+
+ assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
+ assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
+}
+
+#[test]
+fn test_into_iter_drop_leak_height_0() {
+ static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+ struct D;
+
+ impl Drop for D {
+ fn drop(&mut self) {
+ if DROPS.fetch_add(1, Ordering::SeqCst) == 3 {
+ panic!("panic in `drop`");
+ }
+ }
+ }
+
+ let mut map = BTreeMap::new();
+ map.insert("a", D);
+ map.insert("b", D);
+ map.insert("c", D);
+ map.insert("d", D);
+ map.insert("e", D);
+
+ catch_unwind(move || drop(map.into_iter())).unwrap_err();
+
+ assert_eq!(DROPS.load(Ordering::SeqCst), 5);
+}
+
+#[test]
+fn test_into_iter_drop_leak_height_1() {
+ let size = MIN_INSERTS_HEIGHT_1;
+ static DROPS: AtomicUsize = AtomicUsize::new(0);
+ static PANIC_POINT: AtomicUsize = AtomicUsize::new(0);
+
+ struct D;
+ impl Drop for D {
+ fn drop(&mut self) {
+ if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
+ panic!("panic in `drop`");
+ }
+ }
+ }
+
+ for panic_point in vec![0, 1, size - 2, size - 1] {
+ DROPS.store(0, Ordering::SeqCst);
+ PANIC_POINT.store(panic_point, Ordering::SeqCst);
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
+ catch_unwind(move || drop(map.into_iter())).unwrap_err();
+ assert_eq!(DROPS.load(Ordering::SeqCst), size);
+ }
+}
+
+#[test]
+fn test_into_keys() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: BTreeMap<_, _> = vec.into_iter().collect();
+ let keys: Vec<_> = map.into_keys().collect();
+
+ assert_eq!(keys.len(), 3);
+ assert!(keys.contains(&1));
+ assert!(keys.contains(&2));
+ assert!(keys.contains(&3));
+}
+
+#[test]
+fn test_into_values() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: BTreeMap<_, _> = vec.into_iter().collect();
+ let values: Vec<_> = map.into_values().collect();
+
+ assert_eq!(values.len(), 3);
+ assert!(values.contains(&'a'));
+ assert!(values.contains(&'b'));
+ assert!(values.contains(&'c'));
+}
}
})
}
+
+#[cfg(test)]
+/// XorShiftRng
+struct DeterministicRng {
+ x: u32,
+ y: u32,
+ z: u32,
+ w: u32,
+}
+
+#[cfg(test)]
+impl DeterministicRng {
+ fn new() -> Self {
+ DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
+ }
+
+ fn next(&mut self) -> u32 {
+ let x = self.x;
+ let t = x ^ (x << 11);
+ self.x = self.y;
+ self.y = self.z;
+ self.z = self.w;
+ let w_ = self.w;
+ self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
+ self.w
+ }
+}
const B: usize = 6;
pub const MIN_LEN: usize = B - 1;
pub const CAPACITY: usize = 2 * B - 1;
+const KV_IDX_CENTER: usize = B - 1;
+const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1;
+const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
/// The underlying representation of leaf nodes.
#[repr(C)]
impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
/// Unsafely asserts to the compiler some static information about whether this
/// node is a `Leaf` or an `Internal`.
- unsafe fn cast_unchecked<NewType>(&mut self) -> NodeRef<marker::Mut<'_>, K, V, NewType> {
+ unsafe fn cast_unchecked<NewType>(self) -> NodeRef<marker::Mut<'a>, K, V, NewType> {
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
}
}
impl<Node, Type> Handle<Node, Type> {
- /// Retrieves the node that contains the edge of key/value pair this handle points to.
+ /// Retrieves the node that contains the edge or key/value pair this handle points to.
pub fn into_node(self) -> Node {
self.node
}
}
}
+enum InsertionPlace {
+ Left(usize),
+ Right(usize),
+}
+
+/// Given an edge index where we want to insert into a node filled to capacity,
+/// computes a sensible KV index of a split point and where to perform the insertion.
+/// The goal of the split point is for its key and value to end up in a parent node;
+/// the keys, values and edges to the left of the split point become the left child;
+/// the keys, values and edges to the right of the split point become the right child.
+fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) {
+ debug_assert!(edge_idx <= CAPACITY);
+ // Rust issue #74834 tries to explain these symmetric rules.
+ match edge_idx {
+ 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)),
+ EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)),
+ EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)),
+ _ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))),
+ }
+}
+
impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::Edge> {
/// Helps implementations of `insert_fit` for a particular `NodeType`,
/// by taking care of leaf data.
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
(InsertResult::Fit(kv), ptr)
} else {
- let middle = unsafe { Handle::new_kv(self.node, B) };
+ let (middle_kv_idx, insertion) = splitpoint(self.idx);
+ let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
let (mut left, k, v, mut right) = middle.split();
- let ptr = if self.idx <= B {
- unsafe { Handle::new_edge(left.reborrow_mut(), self.idx).insert_fit(key, val) }
- } else {
- unsafe {
+ let ptr = match insertion {
+ InsertionPlace::Left(insert_idx) => unsafe {
+ Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val)
+ },
+ InsertionPlace::Right(insert_idx) => unsafe {
Handle::new_edge(
right.node_as_mut().cast_unchecked::<marker::Leaf>(),
- self.idx - (B + 1),
+ insert_idx,
)
.insert_fit(key, val)
- }
+ },
};
(InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right }), ptr)
}
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
InsertResult::Fit(kv)
} else {
- let middle = unsafe { Handle::new_kv(self.node, B) };
+ let (middle_kv_idx, insertion) = splitpoint(self.idx);
+ let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
let (mut left, k, v, mut right) = middle.split();
- if self.idx <= B {
- unsafe {
- Handle::new_edge(left.reborrow_mut(), self.idx).insert_fit(key, val, edge);
- }
- } else {
- unsafe {
+ match insertion {
+ InsertionPlace::Left(insert_idx) => unsafe {
+ Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val, edge);
+ },
+ InsertionPlace::Right(insert_idx) => unsafe {
Handle::new_edge(
right.node_as_mut().cast_unchecked::<marker::Internal>(),
- self.idx - (B + 1),
+ insert_idx,
)
.insert_fit(key, val, edge);
- }
+ },
}
InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right })
}
}
impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
+ pub fn into_key_mut(self) -> &'a mut K {
+ let keys = self.node.into_key_slice_mut();
+ unsafe { keys.get_unchecked_mut(self.idx) }
+ }
+
+ pub fn into_val_mut(self) -> &'a mut V {
+ let vals = self.node.into_val_slice_mut();
+ unsafe { vals.get_unchecked_mut(self.idx) }
+ }
+
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
unsafe {
let (keys, vals) = self.node.into_slices_mut();
}
/// Removes the key/value pair pointed to by this handle and returns it, along with the edge
- /// between the now adjacent key/value pairs (if any) to the left and right of this handle.
+ /// that the key/value pair collapsed into.
pub fn remove(
mut self,
) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
/// to by this handle, and the node immediately to the right of this handle into one new
/// child of the underlying node, returning an edge referencing that new child.
///
- /// Assumes that this edge `.can_merge()`.
+ /// Panics unless this edge `.can_merge()`.
pub fn merge(
mut self,
) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> {
let self2 = unsafe { ptr::read(&self) };
let mut left_node = self1.left_edge().descend();
let left_len = left_node.len();
- let mut right_node = self2.right_edge().descend();
+ let right_node = self2.right_edge().descend();
let right_len = right_node.len();
- // necessary for correctness, but in a private module
assert!(left_len + right_len < CAPACITY);
unsafe {
(*left_node.as_leaf_mut()).len += right_len as u16 + 1;
- let layout = if self.node.height > 1 {
+ if self.node.height > 1 {
+ // SAFETY: the height of the nodes being merged is one below the height
+ // of the node of this edge, thus above zero, so they are internal.
+ let mut left_node = left_node.cast_unchecked();
+ let right_node = right_node.cast_unchecked();
ptr::copy_nonoverlapping(
- right_node.cast_unchecked().as_internal().edges.as_ptr(),
- left_node
- .cast_unchecked()
- .as_internal_mut()
- .edges
- .as_mut_ptr()
- .add(left_len + 1),
+ right_node.reborrow().as_internal().edges.as_ptr(),
+ left_node.reborrow_mut().as_internal_mut().edges.as_mut_ptr().add(left_len + 1),
right_len + 1,
);
for i in left_len + 1..left_len + right_len + 2 {
- Handle::new_edge(left_node.cast_unchecked().reborrow_mut(), i)
- .correct_parent_link();
+ Handle::new_edge(left_node.reborrow_mut(), i).correct_parent_link();
}
- Layout::new::<InternalNode<K, V>>()
+ Global.dealloc(right_node.node.cast(), Layout::new::<InternalNode<K, V>>());
} else {
- Layout::new::<LeafNode<K, V>>()
- };
- Global.dealloc(right_node.node.cast(), layout);
+ Global.dealloc(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
+ }
Handle::new_edge(self.node, self.idx)
}
unsafe {
let (k, v, edge) = self.reborrow_mut().left_edge().descend().pop();
- let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k);
- let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v);
+ let k = mem::replace(self.kv_mut().0, k);
+ let v = mem::replace(self.kv_mut().1, v);
match self.reborrow_mut().right_edge().descend().force() {
ForceResult::Leaf(mut leaf) => leaf.push_front(k, v),
unsafe {
let (k, v, edge) = self.reborrow_mut().right_edge().descend().pop_front();
- let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k);
- let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v);
+ let k = mem::replace(self.kv_mut().0, k);
+ let v = mem::replace(self.kv_mut().1, v);
match self.reborrow_mut().left_edge().descend().force() {
ForceResult::Leaf(mut leaf) => leaf.push(k, v),
let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
let parent_kv = {
- let kv = self.reborrow_mut().into_kv_mut();
+ let kv = self.kv_mut();
(kv.0 as *mut K, kv.1 as *mut V)
};
let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
let parent_kv = {
- let kv = self.reborrow_mut().into_kv_mut();
+ let kv = self.kv_mut();
(kv.0 as *mut K, kv.1 as *mut V)
};
ret
}
}
+
+#[cfg(test)]
+mod tests;
--- /dev/null
+use super::*;
+
+#[test]
+fn test_splitpoint() {
+ for idx in 0..=CAPACITY {
+ let (middle_kv_idx, insertion) = splitpoint(idx);
+
+ // Simulate performing the split:
+ let mut left_len = middle_kv_idx;
+ let mut right_len = CAPACITY - middle_kv_idx - 1;
+ match insertion {
+ InsertionPlace::Left(edge_idx) => {
+ assert!(edge_idx <= left_len);
+ left_len += 1;
+ }
+ InsertionPlace::Right(edge_idx) => {
+ assert!(edge_idx <= right_len);
+ right_len += 1;
+ }
+ }
+ assert!(left_len >= MIN_LEN);
+ assert!(right_len >= MIN_LEN);
+ assert!(left_len + right_len == CAPACITY);
+ }
+}
#[stable(feature = "fused", since = "1.26.0")]
impl<T: Ord> FusedIterator for Union<'_, T> {}
+
+#[cfg(test)]
+mod tests;
--- /dev/null
+use crate::collections::BTreeSet;
+use crate::vec::Vec;
+use std::iter::FromIterator;
+use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::sync::atomic::{AtomicU32, Ordering};
+
+use super::super::DeterministicRng;
+
+#[test]
+fn test_clone_eq() {
+ let mut m = BTreeSet::new();
+
+ m.insert(1);
+ m.insert(2);
+
+ assert_eq!(m.clone(), m);
+}
+
+#[test]
+fn test_iter_min_max() {
+ let mut a = BTreeSet::new();
+ assert_eq!(a.iter().min(), None);
+ assert_eq!(a.iter().max(), None);
+ assert_eq!(a.range(..).min(), None);
+ assert_eq!(a.range(..).max(), None);
+ assert_eq!(a.difference(&BTreeSet::new()).min(), None);
+ assert_eq!(a.difference(&BTreeSet::new()).max(), None);
+ assert_eq!(a.intersection(&a).min(), None);
+ assert_eq!(a.intersection(&a).max(), None);
+ assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None);
+ assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None);
+ assert_eq!(a.union(&a).min(), None);
+ assert_eq!(a.union(&a).max(), None);
+ a.insert(1);
+ a.insert(2);
+ assert_eq!(a.iter().min(), Some(&1));
+ assert_eq!(a.iter().max(), Some(&2));
+ assert_eq!(a.range(..).min(), Some(&1));
+ assert_eq!(a.range(..).max(), Some(&2));
+ assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1));
+ assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2));
+ assert_eq!(a.intersection(&a).min(), Some(&1));
+ assert_eq!(a.intersection(&a).max(), Some(&2));
+ assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1));
+ assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2));
+ assert_eq!(a.union(&a).min(), Some(&1));
+ assert_eq!(a.union(&a).max(), Some(&2));
+}
+
+fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
+where
+ F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool,
+{
+ let mut set_a = BTreeSet::new();
+ let mut set_b = BTreeSet::new();
+
+ for x in a {
+ assert!(set_a.insert(*x))
+ }
+ for y in b {
+ assert!(set_b.insert(*y))
+ }
+
+ let mut i = 0;
+ f(&set_a, &set_b, &mut |&x| {
+ if i < expected.len() {
+ assert_eq!(x, expected[i]);
+ }
+ i += 1;
+ true
+ });
+ assert_eq!(i, expected.len());
+}
+
+#[test]
+fn test_intersection() {
+ fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.intersection(y).all(f))
+ }
+
+ check_intersection(&[], &[], &[]);
+ check_intersection(&[1, 2, 3], &[], &[]);
+ check_intersection(&[], &[1, 2, 3], &[]);
+ check_intersection(&[2], &[1, 2, 3], &[2]);
+ check_intersection(&[1, 2, 3], &[2], &[2]);
+ check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]);
+
+ if cfg!(miri) {
+ // Miri is too slow
+ return;
+ }
+
+ let large = (0..100).collect::<Vec<_>>();
+ check_intersection(&[], &large, &[]);
+ check_intersection(&large, &[], &[]);
+ check_intersection(&[-1], &large, &[]);
+ check_intersection(&large, &[-1], &[]);
+ check_intersection(&[0], &large, &[0]);
+ check_intersection(&large, &[0], &[0]);
+ check_intersection(&[99], &large, &[99]);
+ check_intersection(&large, &[99], &[99]);
+ check_intersection(&[100], &large, &[]);
+ check_intersection(&large, &[100], &[]);
+ check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]);
+}
+
+#[test]
+fn test_intersection_size_hint() {
+ let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
+ let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+ let mut iter = x.intersection(&y);
+ assert_eq!(iter.size_hint(), (1, Some(1)));
+ assert_eq!(iter.next(), Some(&3));
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+
+ iter = y.intersection(&y);
+ assert_eq!(iter.size_hint(), (0, Some(3)));
+ assert_eq!(iter.next(), Some(&1));
+ assert_eq!(iter.size_hint(), (0, Some(2)));
+}
+
+#[test]
+fn test_difference() {
+ fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.difference(y).all(f))
+ }
+
+ check_difference(&[], &[], &[]);
+ check_difference(&[1, 12], &[], &[1, 12]);
+ check_difference(&[], &[1, 2, 3, 9], &[]);
+ check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
+ check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]);
+ check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]);
+ check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]);
+ check_difference(
+ &[-5, 11, 22, 33, 40, 42],
+ &[-12, -5, 14, 23, 34, 38, 39, 50],
+ &[11, 22, 33, 40, 42],
+ );
+
+ if cfg!(miri) {
+ // Miri is too slow
+ return;
+ }
+
+ let large = (0..100).collect::<Vec<_>>();
+ check_difference(&[], &large, &[]);
+ check_difference(&[-1], &large, &[-1]);
+ check_difference(&[0], &large, &[]);
+ check_difference(&[99], &large, &[]);
+ check_difference(&[100], &large, &[100]);
+ check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]);
+ check_difference(&large, &[], &large);
+ check_difference(&large, &[-1], &large);
+ check_difference(&large, &[100], &large);
+}
+
+#[test]
+fn test_difference_size_hint() {
+ let s246: BTreeSet<i32> = [2, 4, 6].iter().copied().collect();
+ let s23456: BTreeSet<i32> = (2..=6).collect();
+ let mut iter = s246.difference(&s23456);
+ assert_eq!(iter.size_hint(), (0, Some(3)));
+ assert_eq!(iter.next(), None);
+
+ let s12345: BTreeSet<i32> = (1..=5).collect();
+ iter = s246.difference(&s12345);
+ assert_eq!(iter.size_hint(), (0, Some(3)));
+ assert_eq!(iter.next(), Some(&6));
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+
+ let s34567: BTreeSet<i32> = (3..=7).collect();
+ iter = s246.difference(&s34567);
+ assert_eq!(iter.size_hint(), (0, Some(3)));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.size_hint(), (0, Some(2)));
+ assert_eq!(iter.next(), None);
+
+ let s1: BTreeSet<i32> = (-9..=1).collect();
+ iter = s246.difference(&s1);
+ assert_eq!(iter.size_hint(), (3, Some(3)));
+
+ let s2: BTreeSet<i32> = (-9..=2).collect();
+ iter = s246.difference(&s2);
+ assert_eq!(iter.size_hint(), (2, Some(2)));
+ assert_eq!(iter.next(), Some(&4));
+ assert_eq!(iter.size_hint(), (1, Some(1)));
+
+ let s23: BTreeSet<i32> = (2..=3).collect();
+ iter = s246.difference(&s23);
+ assert_eq!(iter.size_hint(), (1, Some(3)));
+ assert_eq!(iter.next(), Some(&4));
+ assert_eq!(iter.size_hint(), (1, Some(1)));
+
+ let s4: BTreeSet<i32> = (4..=4).collect();
+ iter = s246.difference(&s4);
+ assert_eq!(iter.size_hint(), (2, Some(3)));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.size_hint(), (1, Some(2)));
+ assert_eq!(iter.next(), Some(&6));
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+
+ let s56: BTreeSet<i32> = (5..=6).collect();
+ iter = s246.difference(&s56);
+ assert_eq!(iter.size_hint(), (1, Some(3)));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.size_hint(), (0, Some(2)));
+
+ let s6: BTreeSet<i32> = (6..=19).collect();
+ iter = s246.difference(&s6);
+ assert_eq!(iter.size_hint(), (2, Some(2)));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.size_hint(), (1, Some(1)));
+
+ let s7: BTreeSet<i32> = (7..=19).collect();
+ iter = s246.difference(&s7);
+ assert_eq!(iter.size_hint(), (3, Some(3)));
+}
+
+#[test]
+fn test_symmetric_difference() {
+ fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
+ }
+
+ check_symmetric_difference(&[], &[], &[]);
+ check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
+ check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
+ check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]);
+}
+
+#[test]
+fn test_symmetric_difference_size_hint() {
+ let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
+ let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+ let mut iter = x.symmetric_difference(&y);
+ assert_eq!(iter.size_hint(), (0, Some(5)));
+ assert_eq!(iter.next(), Some(&1));
+ assert_eq!(iter.size_hint(), (0, Some(4)));
+ assert_eq!(iter.next(), Some(&3));
+ assert_eq!(iter.size_hint(), (0, Some(1)));
+}
+
+#[test]
+fn test_union() {
+ fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
+ check(a, b, expected, |x, y, f| x.union(y).all(f))
+ }
+
+ check_union(&[], &[], &[]);
+ check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
+ check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
+ check_union(
+ &[1, 3, 5, 9, 11, 16, 19, 24],
+ &[-2, 1, 5, 9, 13, 19],
+ &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24],
+ );
+}
+
+#[test]
+fn test_union_size_hint() {
+ let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
+ let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
+ let mut iter = x.union(&y);
+ assert_eq!(iter.size_hint(), (3, Some(5)));
+ assert_eq!(iter.next(), Some(&1));
+ assert_eq!(iter.size_hint(), (2, Some(4)));
+ assert_eq!(iter.next(), Some(&2));
+ assert_eq!(iter.size_hint(), (1, Some(2)));
+}
+
+#[test]
+// Only tests the simple function definition with respect to intersection
+fn test_is_disjoint() {
+ let one = [1].iter().collect::<BTreeSet<_>>();
+ let two = [2].iter().collect::<BTreeSet<_>>();
+ assert!(one.is_disjoint(&two));
+}
+
+#[test]
+// Also implicitly tests the trivial function definition of is_superset
+fn test_is_subset() {
+ fn is_subset(a: &[i32], b: &[i32]) -> bool {
+ let set_a = a.iter().collect::<BTreeSet<_>>();
+ let set_b = b.iter().collect::<BTreeSet<_>>();
+ set_a.is_subset(&set_b)
+ }
+
+ assert_eq!(is_subset(&[], &[]), true);
+ assert_eq!(is_subset(&[], &[1, 2]), true);
+ assert_eq!(is_subset(&[0], &[1, 2]), false);
+ assert_eq!(is_subset(&[1], &[1, 2]), true);
+ assert_eq!(is_subset(&[2], &[1, 2]), true);
+ assert_eq!(is_subset(&[3], &[1, 2]), false);
+ assert_eq!(is_subset(&[1, 2], &[1]), false);
+ assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
+ assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
+ assert_eq!(
+ is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]),
+ true
+ );
+ assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false);
+
+ if cfg!(miri) {
+ // Miri is too slow
+ return;
+ }
+
+ let large = (0..100).collect::<Vec<_>>();
+ assert_eq!(is_subset(&[], &large), true);
+ assert_eq!(is_subset(&large, &[]), false);
+ assert_eq!(is_subset(&[-1], &large), false);
+ assert_eq!(is_subset(&[0], &large), true);
+ assert_eq!(is_subset(&[1, 2], &large), true);
+ assert_eq!(is_subset(&[99, 100], &large), false);
+}
+
+#[test]
+fn test_drain_filter() {
+ let mut x: BTreeSet<_> = [1].iter().copied().collect();
+ let mut y: BTreeSet<_> = [1].iter().copied().collect();
+
+ x.drain_filter(|_| true);
+ y.drain_filter(|_| false);
+ assert_eq!(x.len(), 0);
+ assert_eq!(y.len(), 1);
+}
+
+#[test]
+fn test_drain_filter_drop_panic_leak() {
+ static PREDS: AtomicU32 = AtomicU32::new(0);
+ static DROPS: AtomicU32 = AtomicU32::new(0);
+
+ #[derive(PartialEq, Eq, PartialOrd, Ord)]
+ struct D(i32);
+ impl Drop for D {
+ fn drop(&mut self) {
+ if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
+ panic!("panic in `drop`");
+ }
+ }
+ }
+
+ let mut set = BTreeSet::new();
+ set.insert(D(0));
+ set.insert(D(4));
+ set.insert(D(8));
+
+ catch_unwind(move || {
+ drop(set.drain_filter(|d| {
+ PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
+ true
+ }))
+ })
+ .ok();
+
+ assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+ assert_eq!(DROPS.load(Ordering::SeqCst), 3);
+}
+
+#[test]
+fn test_drain_filter_pred_panic_leak() {
+ static PREDS: AtomicU32 = AtomicU32::new(0);
+ static DROPS: AtomicU32 = AtomicU32::new(0);
+
+ #[derive(PartialEq, Eq, PartialOrd, Ord)]
+ struct D(i32);
+ impl Drop for D {
+ fn drop(&mut self) {
+ DROPS.fetch_add(1, Ordering::SeqCst);
+ }
+ }
+
+ let mut set = BTreeSet::new();
+ set.insert(D(0));
+ set.insert(D(4));
+ set.insert(D(8));
+
+ catch_unwind(AssertUnwindSafe(|| {
+ drop(set.drain_filter(|d| {
+ PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
+ match d.0 {
+ 0 => true,
+ _ => panic!(),
+ }
+ }))
+ }))
+ .ok();
+
+ assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
+ assert_eq!(DROPS.load(Ordering::SeqCst), 1);
+ assert_eq!(set.len(), 2);
+ assert_eq!(set.first().unwrap().0, 4);
+ assert_eq!(set.last().unwrap().0, 8);
+}
+
+#[test]
+fn test_clear() {
+ let mut x = BTreeSet::new();
+ x.insert(1);
+
+ x.clear();
+ assert!(x.is_empty());
+}
+
+#[test]
+fn test_zip() {
+ let mut x = BTreeSet::new();
+ x.insert(5);
+ x.insert(12);
+ x.insert(11);
+
+ let mut y = BTreeSet::new();
+ y.insert("foo");
+ y.insert("bar");
+
+ let x = x;
+ let y = y;
+ let mut z = x.iter().zip(&y);
+
+ assert_eq!(z.next().unwrap(), (&5, &("bar")));
+ assert_eq!(z.next().unwrap(), (&11, &("foo")));
+ assert!(z.next().is_none());
+}
+
+#[test]
+fn test_from_iter() {
+ let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+ let set: BTreeSet<_> = xs.iter().cloned().collect();
+
+ for x in &xs {
+ assert!(set.contains(x));
+ }
+}
+
+#[test]
+fn test_show() {
+ let mut set = BTreeSet::new();
+ let empty = BTreeSet::<i32>::new();
+
+ set.insert(1);
+ set.insert(2);
+
+ let set_str = format!("{:?}", set);
+
+ assert_eq!(set_str, "{1, 2}");
+ assert_eq!(format!("{:?}", empty), "{}");
+}
+
+#[test]
+fn test_extend_ref() {
+ let mut a = BTreeSet::new();
+ a.insert(1);
+
+ a.extend(&[2, 3, 4]);
+
+ assert_eq!(a.len(), 4);
+ assert!(a.contains(&1));
+ assert!(a.contains(&2));
+ assert!(a.contains(&3));
+ assert!(a.contains(&4));
+
+ let mut b = BTreeSet::new();
+ b.insert(5);
+ b.insert(6);
+
+ a.extend(&b);
+
+ assert_eq!(a.len(), 6);
+ assert!(a.contains(&1));
+ assert!(a.contains(&2));
+ assert!(a.contains(&3));
+ assert!(a.contains(&4));
+ assert!(a.contains(&5));
+ assert!(a.contains(&6));
+}
+
+#[test]
+fn test_recovery() {
+ use std::cmp::Ordering;
+
+ #[derive(Debug)]
+ struct Foo(&'static str, i32);
+
+ impl PartialEq for Foo {
+ fn eq(&self, other: &Self) -> bool {
+ self.0 == other.0
+ }
+ }
+
+ impl Eq for Foo {}
+
+ impl PartialOrd for Foo {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.0.partial_cmp(&other.0)
+ }
+ }
+
+ impl Ord for Foo {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.0.cmp(&other.0)
+ }
+ }
+
+ let mut s = BTreeSet::new();
+ assert_eq!(s.replace(Foo("a", 1)), None);
+ assert_eq!(s.len(), 1);
+ assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
+ assert_eq!(s.len(), 1);
+
+ {
+ let mut it = s.iter();
+ assert_eq!(it.next(), Some(&Foo("a", 2)));
+ assert_eq!(it.next(), None);
+ }
+
+ assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2)));
+ assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2)));
+ assert_eq!(s.len(), 0);
+
+ assert_eq!(s.get(&Foo("a", 1)), None);
+ assert_eq!(s.take(&Foo("a", 1)), None);
+
+ assert_eq!(s.iter().next(), None);
+}
+
+#[test]
+#[allow(dead_code)]
+fn test_variance() {
+ use std::collections::btree_set::{IntoIter, Iter, Range};
+
+ fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
+ v
+ }
+ fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
+ v
+ }
+ fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
+ v
+ }
+ fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
+ v
+ }
+}
+
+#[test]
+fn test_append() {
+ let mut a = BTreeSet::new();
+ a.insert(1);
+ a.insert(2);
+ a.insert(3);
+
+ let mut b = BTreeSet::new();
+ b.insert(3);
+ b.insert(4);
+ b.insert(5);
+
+ a.append(&mut b);
+
+ assert_eq!(a.len(), 5);
+ assert_eq!(b.len(), 0);
+
+ assert_eq!(a.contains(&1), true);
+ assert_eq!(a.contains(&2), true);
+ assert_eq!(a.contains(&3), true);
+ assert_eq!(a.contains(&4), true);
+ assert_eq!(a.contains(&5), true);
+}
+
+#[test]
+fn test_first_last() {
+ let mut a = BTreeSet::new();
+ assert_eq!(a.first(), None);
+ assert_eq!(a.last(), None);
+ a.insert(1);
+ assert_eq!(a.first(), Some(&1));
+ assert_eq!(a.last(), Some(&1));
+ a.insert(2);
+ assert_eq!(a.first(), Some(&1));
+ assert_eq!(a.last(), Some(&2));
+ for i in 3..=12 {
+ a.insert(i);
+ }
+ assert_eq!(a.first(), Some(&1));
+ assert_eq!(a.last(), Some(&12));
+ assert_eq!(a.pop_first(), Some(1));
+ assert_eq!(a.pop_last(), Some(12));
+ assert_eq!(a.pop_first(), Some(2));
+ assert_eq!(a.pop_last(), Some(11));
+ assert_eq!(a.pop_first(), Some(3));
+ assert_eq!(a.pop_last(), Some(10));
+ assert_eq!(a.pop_first(), Some(4));
+ assert_eq!(a.pop_first(), Some(5));
+ assert_eq!(a.pop_first(), Some(6));
+ assert_eq!(a.pop_first(), Some(7));
+ assert_eq!(a.pop_first(), Some(8));
+ assert_eq!(a.clone().pop_last(), Some(9));
+ assert_eq!(a.pop_first(), Some(9));
+ assert_eq!(a.pop_first(), None);
+ assert_eq!(a.pop_last(), None);
+}
+
+fn rand_data(len: usize) -> Vec<u32> {
+ let mut rng = DeterministicRng::new();
+ Vec::from_iter((0..len).map(|_| rng.next()))
+}
+
+#[test]
+fn test_split_off_empty_right() {
+ let mut data = rand_data(173);
+
+ let mut set = BTreeSet::from_iter(data.clone());
+ let right = set.split_off(&(data.iter().max().unwrap() + 1));
+
+ data.sort();
+ assert!(set.into_iter().eq(data));
+ assert!(right.into_iter().eq(None));
+}
+
+#[test]
+fn test_split_off_empty_left() {
+ let mut data = rand_data(314);
+
+ let mut set = BTreeSet::from_iter(data.clone());
+ let right = set.split_off(data.iter().min().unwrap());
+
+ data.sort();
+ assert!(set.into_iter().eq(None));
+ assert!(right.into_iter().eq(data));
+}
+
+#[test]
+fn test_split_off_large_random_sorted() {
+ // Miri is too slow
+ let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
+ // special case with maximum height.
+ data.sort();
+
+ let mut set = BTreeSet::from_iter(data.clone());
+ let key = data[data.len() / 2];
+ let right = set.split_off(&key);
+
+ assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
+ assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
+}
#![feature(arbitrary_self_types)]
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(btree_drain_filter)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
#![feature(container_error_extra)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
+#![feature(exclusive_range_pattern)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(lang_items)]
#![feature(layout_for_ptr)]
#![feature(libc)]
+#![feature(map_first_last)]
+#![feature(map_into_keys_values)]
#![feature(negative_impls)]
#![feature(new_uninit)]
#![feature(nll)]
///
/// This `struct` is created by the `into_iter` method on [`Vec`] (provided
/// by the [`IntoIterator`] trait).
-///
-/// [`Vec`]: struct.Vec.html
-/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
buf: NonNull<T>,
/// A draining iterator for `Vec<T>`.
///
-/// This `struct` is created by the [`drain`] method on [`Vec`].
-///
-/// [`drain`]: struct.Vec.html#method.drain
-/// [`Vec`]: struct.Vec.html
+/// This `struct` is created by [`Vec::drain`].
#[stable(feature = "drain", since = "1.6.0")]
pub struct Drain<'a, T: 'a> {
/// Index of tail to preserve
/// A splicing iterator for `Vec`.
///
-/// This struct is created by the [`splice()`] method on [`Vec`]. See its
-/// documentation for more.
-///
-/// [`splice()`]: struct.Vec.html#method.splice
-/// [`Vec`]: struct.Vec.html
+/// This struct is created by [`Vec::splice()`].
+/// See its documentation for more.
#[derive(Debug)]
#[stable(feature = "vec_splice", since = "1.21.0")]
pub struct Splice<'a, I: Iterator + 'a> {
+++ /dev/null
-use std::collections::btree_map::Entry::{Occupied, Vacant};
-use std::collections::BTreeMap;
-use std::convert::TryFrom;
-use std::fmt::Debug;
-use std::iter::FromIterator;
-use std::mem;
-use std::ops::Bound::{self, Excluded, Included, Unbounded};
-use std::ops::RangeBounds;
-use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::rc::Rc;
-use std::sync::atomic::{AtomicUsize, Ordering};
-
-use super::DeterministicRng;
-
-// Value of node::CAPACITY, thus capacity of a tree with a single level,
-// i.e. a tree who's root is a leaf node at height 0.
-const NODE_CAPACITY: usize = 11;
-
-// Minimum number of elements to insert in order to guarantee a tree with 2 levels,
-// i.e. a tree who's root is an internal node at height 1, with edges to leaf nodes.
-// It's not the minimum size: removing an element from such a tree does not always reduce height.
-const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
-
-// Minimum number of elements to insert in order to guarantee a tree with 3 levels,
-// i.e. a tree who's root is an internal node at height 2, with edges to more internal nodes.
-// It's not the minimum size: removing an element from such a tree does not always reduce height.
-const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_CAPACITY + 1;
-
-// Gather all references from a mutable iterator and make sure Miri notices if
-// using them is dangerous.
-fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
- // Gather all those references.
- let mut refs: Vec<&mut T> = iter.collect();
- // Use them all. Twice, to be sure we got all interleavings.
- for r in refs.iter_mut() {
- mem::swap(dummy, r);
- }
- for r in refs {
- mem::swap(dummy, r);
- }
-}
-
-#[test]
-fn test_basic_large() {
- let mut map = BTreeMap::new();
- // Miri is too slow
- let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 } else { 10000 };
- assert_eq!(map.len(), 0);
-
- for i in 0..size {
- assert_eq!(map.insert(i, 10 * i), None);
- assert_eq!(map.len(), i + 1);
- }
-
- assert_eq!(map.first_key_value(), Some((&0, &0)));
- assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1)))));
- assert_eq!(map.first_entry().unwrap().key(), &0);
- assert_eq!(map.last_entry().unwrap().key(), &(size - 1));
-
- for i in 0..size {
- assert_eq!(map.get(&i).unwrap(), &(i * 10));
- }
-
- for i in size..size * 2 {
- assert_eq!(map.get(&i), None);
- }
-
- for i in 0..size {
- assert_eq!(map.insert(i, 100 * i), Some(10 * i));
- assert_eq!(map.len(), size);
- }
-
- for i in 0..size {
- assert_eq!(map.get(&i).unwrap(), &(i * 100));
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(i * 2)), Some(i * 200));
- assert_eq!(map.len(), size - i - 1);
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.get(&(2 * i)), None);
- assert_eq!(map.get(&(2 * i + 1)).unwrap(), &(i * 200 + 100));
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(2 * i)), None);
- assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
- assert_eq!(map.len(), size / 2 - i - 1);
- }
-}
-
-#[test]
-fn test_basic_small() {
- let mut map = BTreeMap::new();
- // Empty, root is absent (None):
- assert_eq!(map.remove(&1), None);
- assert_eq!(map.len(), 0);
- assert_eq!(map.get(&1), None);
- assert_eq!(map.get_mut(&1), None);
- assert_eq!(map.first_key_value(), None);
- assert_eq!(map.last_key_value(), None);
- assert_eq!(map.keys().count(), 0);
- assert_eq!(map.values().count(), 0);
- assert_eq!(map.range(..).next(), None);
- assert_eq!(map.range(..1).next(), None);
- assert_eq!(map.range(1..).next(), None);
- assert_eq!(map.range(1..=1).next(), None);
- assert_eq!(map.range(1..2).next(), None);
- assert_eq!(map.insert(1, 1), None);
-
- // 1 key-value pair:
- assert_eq!(map.len(), 1);
- assert_eq!(map.get(&1), Some(&1));
- assert_eq!(map.get_mut(&1), Some(&mut 1));
- assert_eq!(map.first_key_value(), Some((&1, &1)));
- assert_eq!(map.last_key_value(), Some((&1, &1)));
- assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
- assert_eq!(map.values().collect::<Vec<_>>(), vec![&1]);
- assert_eq!(map.insert(1, 2), Some(1));
- assert_eq!(map.len(), 1);
- assert_eq!(map.get(&1), Some(&2));
- assert_eq!(map.get_mut(&1), Some(&mut 2));
- assert_eq!(map.first_key_value(), Some((&1, &2)));
- assert_eq!(map.last_key_value(), Some((&1, &2)));
- assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1]);
- assert_eq!(map.values().collect::<Vec<_>>(), vec![&2]);
- assert_eq!(map.insert(2, 4), None);
-
- // 2 key-value pairs:
- assert_eq!(map.len(), 2);
- assert_eq!(map.get(&2), Some(&4));
- assert_eq!(map.get_mut(&2), Some(&mut 4));
- assert_eq!(map.first_key_value(), Some((&1, &2)));
- assert_eq!(map.last_key_value(), Some((&2, &4)));
- assert_eq!(map.keys().collect::<Vec<_>>(), vec![&1, &2]);
- assert_eq!(map.values().collect::<Vec<_>>(), vec![&2, &4]);
- assert_eq!(map.remove(&1), Some(2));
-
- // 1 key-value pair:
- assert_eq!(map.len(), 1);
- assert_eq!(map.get(&1), None);
- assert_eq!(map.get_mut(&1), None);
- assert_eq!(map.get(&2), Some(&4));
- assert_eq!(map.get_mut(&2), Some(&mut 4));
- assert_eq!(map.first_key_value(), Some((&2, &4)));
- assert_eq!(map.last_key_value(), Some((&2, &4)));
- assert_eq!(map.keys().collect::<Vec<_>>(), vec![&2]);
- assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
- assert_eq!(map.remove(&2), Some(4));
-
- // Empty but root is owned (Some(...)):
- assert_eq!(map.len(), 0);
- assert_eq!(map.get(&1), None);
- assert_eq!(map.get_mut(&1), None);
- assert_eq!(map.first_key_value(), None);
- assert_eq!(map.last_key_value(), None);
- assert_eq!(map.keys().count(), 0);
- assert_eq!(map.values().count(), 0);
- assert_eq!(map.range(..).next(), None);
- assert_eq!(map.range(..1).next(), None);
- assert_eq!(map.range(1..).next(), None);
- assert_eq!(map.range(1..=1).next(), None);
- assert_eq!(map.range(1..2).next(), None);
- assert_eq!(map.remove(&1), None);
-}
-
-#[test]
-fn test_iter() {
- // Miri is too slow
- let size = if cfg!(miri) { 200 } else { 10000 };
-
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test<T>(size: usize, mut iter: T)
- where
- T: Iterator<Item = (usize, usize)>,
- {
- for i in 0..size {
- assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
- assert_eq!(iter.next().unwrap(), (i, i));
- }
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- }
- test(size, map.iter().map(|(&k, &v)| (k, v)));
- test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
- test(size, map.into_iter());
-}
-
-#[test]
-fn test_iter_rev() {
- // Miri is too slow
- let size = if cfg!(miri) { 200 } else { 10000 };
-
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test<T>(size: usize, mut iter: T)
- where
- T: Iterator<Item = (usize, usize)>,
- {
- for i in 0..size {
- assert_eq!(iter.size_hint(), (size - i, Some(size - i)));
- assert_eq!(iter.next().unwrap(), (size - i - 1, size - i - 1));
- }
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- }
- test(size, map.iter().rev().map(|(&k, &v)| (k, v)));
- test(size, map.iter_mut().rev().map(|(&k, &mut v)| (k, v)));
- test(size, map.into_iter().rev());
-}
-
-/// Specifically tests iter_mut's ability to mutate the value of pairs in-line
-fn do_test_iter_mut_mutation<T>(size: usize)
-where
- T: Copy + Debug + Ord + TryFrom<usize>,
- <T as std::convert::TryFrom<usize>>::Error: std::fmt::Debug,
-{
- let zero = T::try_from(0).unwrap();
- let mut map: BTreeMap<T, T> = (0..size).map(|i| (T::try_from(i).unwrap(), zero)).collect();
-
- // Forward and backward iteration sees enough pairs (also tested elsewhere)
- assert_eq!(map.iter_mut().count(), size);
- assert_eq!(map.iter_mut().rev().count(), size);
-
- // Iterate forwards, trying to mutate to unique values
- for (i, (k, v)) in map.iter_mut().enumerate() {
- assert_eq!(*k, T::try_from(i).unwrap());
- assert_eq!(*v, zero);
- *v = T::try_from(i + 1).unwrap();
- }
-
- // Iterate backwards, checking that mutations succeeded and trying to mutate again
- for (i, (k, v)) in map.iter_mut().rev().enumerate() {
- assert_eq!(*k, T::try_from(size - i - 1).unwrap());
- assert_eq!(*v, T::try_from(size - i).unwrap());
- *v = T::try_from(2 * size - i).unwrap();
- }
-
- // Check that backward mutations succeeded
- for (i, (k, v)) in map.iter_mut().enumerate() {
- assert_eq!(*k, T::try_from(i).unwrap());
- assert_eq!(*v, T::try_from(size + i + 1).unwrap());
- }
-}
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
-#[repr(align(32))]
-struct Align32(usize);
-
-impl TryFrom<usize> for Align32 {
- type Error = ();
-
- fn try_from(s: usize) -> Result<Align32, ()> {
- Ok(Align32(s))
- }
-}
-
-#[test]
-fn test_iter_mut_mutation() {
- // Check many alignments and trees with roots at various heights.
- do_test_iter_mut_mutation::<u8>(0);
- do_test_iter_mut_mutation::<u8>(1);
- do_test_iter_mut_mutation::<u8>(MIN_INSERTS_HEIGHT_1);
- do_test_iter_mut_mutation::<u8>(127); // not enough unique values to test MIN_INSERTS_HEIGHT_2
- do_test_iter_mut_mutation::<u16>(1);
- do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_1);
- do_test_iter_mut_mutation::<u16>(MIN_INSERTS_HEIGHT_2);
- do_test_iter_mut_mutation::<u32>(1);
- do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_1);
- do_test_iter_mut_mutation::<u32>(MIN_INSERTS_HEIGHT_2);
- do_test_iter_mut_mutation::<u64>(1);
- do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_1);
- do_test_iter_mut_mutation::<u64>(MIN_INSERTS_HEIGHT_2);
- do_test_iter_mut_mutation::<u128>(1);
- do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_1);
- do_test_iter_mut_mutation::<u128>(MIN_INSERTS_HEIGHT_2);
- do_test_iter_mut_mutation::<Align32>(1);
- do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_1);
- do_test_iter_mut_mutation::<Align32>(MIN_INSERTS_HEIGHT_2);
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_values_mut() {
- let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
- test_all_refs(&mut 13, a.values_mut());
-}
-
-#[test]
-fn test_values_mut_mutation() {
- let mut a = BTreeMap::new();
- a.insert(1, String::from("hello"));
- a.insert(2, String::from("goodbye"));
-
- for value in a.values_mut() {
- value.push_str("!");
- }
-
- let values: Vec<String> = a.values().cloned().collect();
- assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_iter_entering_root_twice() {
- let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect();
- let mut it = map.iter_mut();
- let front = it.next().unwrap();
- let back = it.next_back().unwrap();
- assert_eq!(front, (&0, &mut 0));
- assert_eq!(back, (&1, &mut 1));
- *front.1 = 24;
- *back.1 = 42;
- assert_eq!(front, (&0, &mut 24));
- assert_eq!(back, (&1, &mut 42));
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_iter_descending_to_same_node_twice() {
- let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect();
- let mut it = map.iter_mut();
- // Descend into first child.
- let front = it.next().unwrap();
- // Descend into first child again, after running through second child.
- while it.next_back().is_some() {}
- // Check immutable access.
- assert_eq!(front, (&0, &mut 0));
- // Perform mutable access.
- *front.1 = 42;
-}
-
-#[test]
-fn test_iter_mixed() {
- // Miri is too slow
- let size = if cfg!(miri) { 200 } else { 10000 };
-
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test<T>(size: usize, mut iter: T)
- where
- T: Iterator<Item = (usize, usize)> + DoubleEndedIterator,
- {
- for i in 0..size / 4 {
- assert_eq!(iter.size_hint(), (size - i * 2, Some(size - i * 2)));
- assert_eq!(iter.next().unwrap(), (i, i));
- assert_eq!(iter.next_back().unwrap(), (size - i - 1, size - i - 1));
- }
- for i in size / 4..size * 3 / 4 {
- assert_eq!(iter.size_hint(), (size * 3 / 4 - i, Some(size * 3 / 4 - i)));
- assert_eq!(iter.next().unwrap(), (i, i));
- }
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- }
- test(size, map.iter().map(|(&k, &v)| (k, v)));
- test(size, map.iter_mut().map(|(&k, &mut v)| (k, v)));
- test(size, map.into_iter());
-}
-
-#[test]
-#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
-fn test_iter_min_max() {
- let mut a = BTreeMap::new();
- assert_eq!(a.iter().min(), None);
- assert_eq!(a.iter().max(), None);
- assert_eq!(a.iter_mut().min(), None);
- assert_eq!(a.iter_mut().max(), None);
- assert_eq!(a.range(..).min(), None);
- assert_eq!(a.range(..).max(), None);
- assert_eq!(a.range_mut(..).min(), None);
- assert_eq!(a.range_mut(..).max(), None);
- assert_eq!(a.keys().min(), None);
- assert_eq!(a.keys().max(), None);
- assert_eq!(a.values().min(), None);
- assert_eq!(a.values().max(), None);
- assert_eq!(a.values_mut().min(), None);
- assert_eq!(a.values_mut().max(), None);
- a.insert(1, 42);
- a.insert(2, 24);
- assert_eq!(a.iter().min(), Some((&1, &42)));
- assert_eq!(a.iter().max(), Some((&2, &24)));
- assert_eq!(a.iter_mut().min(), Some((&1, &mut 42)));
- assert_eq!(a.iter_mut().max(), Some((&2, &mut 24)));
- assert_eq!(a.range(..).min(), Some((&1, &42)));
- assert_eq!(a.range(..).max(), Some((&2, &24)));
- assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42)));
- assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24)));
- assert_eq!(a.keys().min(), Some(&1));
- assert_eq!(a.keys().max(), Some(&2));
- assert_eq!(a.values().min(), Some(&24));
- assert_eq!(a.values().max(), Some(&42));
- assert_eq!(a.values_mut().min(), Some(&mut 24));
- assert_eq!(a.values_mut().max(), Some(&mut 42));
-}
-
-fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> {
- map.range(range)
- .map(|(&k, &v)| {
- assert_eq!(k, v);
- k
- })
- .collect()
-}
-
-#[test]
-fn test_range_small() {
- let size = 4;
-
- let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
- let all: Vec<_> = (1..=size).collect();
- let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
-
- assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
- assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
- assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
- assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
- assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
- assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
- assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
- assert_eq!(range_keys(&map, ..), all);
-
- assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
- assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
- assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
- assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
- assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
- assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
- assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
- assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
- assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
- assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
- assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
- assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
- assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
- assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
- assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
- assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
- assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
- assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
- assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
- assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
-
- assert_eq!(range_keys(&map, ..3), vec![1, 2]);
- assert_eq!(range_keys(&map, 3..), vec![3, 4]);
- assert_eq!(range_keys(&map, 2..=3), vec![2, 3]);
-}
-
-#[test]
-fn test_range_height_1() {
- // Tests tree with a root and 2 leaves. Depending on details we don't want or need
- // to rely upon, the single key at the root will be 6 or 7.
-
- let map: BTreeMap<_, _> = (1..=MIN_INSERTS_HEIGHT_1 as i32).map(|i| (i, i)).collect();
- for &root in &[6, 7] {
- assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]);
- assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]);
- assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]);
-
- assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]);
- assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]);
- assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]);
- assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]);
- }
-}
-
-#[test]
-fn test_range_large() {
- let size = 200;
-
- let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
- let all: Vec<_> = (1..=size).collect();
- let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
-
- assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
- assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
- assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
- assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
- assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
- assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
- assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
- assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
- assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
- assert_eq!(range_keys(&map, ..), all);
-
- assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
- assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
- assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
- assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
- assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
- assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
- assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
- assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
- assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
- assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
- assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
- assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
- assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
- assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
- assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
- assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
- assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
- assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
- assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
- assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
- assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
- assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
-
- fn check<'a, L, R>(lhs: L, rhs: R)
- where
- L: IntoIterator<Item = (&'a i32, &'a i32)>,
- R: IntoIterator<Item = (&'a i32, &'a i32)>,
- {
- let lhs: Vec<_> = lhs.into_iter().collect();
- let rhs: Vec<_> = rhs.into_iter().collect();
- assert_eq!(lhs, rhs);
- }
-
- check(map.range(..=100), map.range(..101));
- check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
- check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]);
-}
-
-#[test]
-fn test_range_inclusive_max_value() {
- let max = usize::MAX;
- let map: BTreeMap<_, _> = vec![(max, 0)].into_iter().collect();
-
- assert_eq!(map.range(max..=max).collect::<Vec<_>>(), &[(&max, &0)]);
-}
-
-#[test]
-fn test_range_equal_empty_cases() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- assert_eq!(map.range((Included(2), Excluded(2))).next(), None);
- assert_eq!(map.range((Excluded(2), Included(2))).next(), None);
-}
-
-#[test]
-#[should_panic]
-fn test_range_equal_excluded() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Excluded(2), Excluded(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_1() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Included(3), Included(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_2() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Included(3), Excluded(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_3() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Excluded(3), Included(2)));
-}
-
-#[test]
-#[should_panic]
-fn test_range_backwards_4() {
- let map: BTreeMap<_, _> = (0..5).map(|i| (i, i)).collect();
- map.range((Excluded(3), Excluded(2)));
-}
-
-#[test]
-fn test_range_1000() {
- // Miri is too slow
- let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 as u32 } else { 1000 };
- let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- fn test(map: &BTreeMap<u32, u32>, size: u32, min: Bound<&u32>, max: Bound<&u32>) {
- let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v));
- let mut pairs = (0..size).map(|i| (i, i));
-
- for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
- assert_eq!(kv, pair);
- }
- assert_eq!(kvs.next(), None);
- assert_eq!(pairs.next(), None);
- }
- test(&map, size, Included(&0), Excluded(&size));
- test(&map, size, Unbounded, Excluded(&size));
- test(&map, size, Included(&0), Included(&(size - 1)));
- test(&map, size, Unbounded, Included(&(size - 1)));
- test(&map, size, Included(&0), Unbounded);
- test(&map, size, Unbounded, Unbounded);
-}
-
-#[test]
-fn test_range_borrowed_key() {
- let mut map = BTreeMap::new();
- map.insert("aardvark".to_string(), 1);
- map.insert("baboon".to_string(), 2);
- map.insert("coyote".to_string(), 3);
- map.insert("dingo".to_string(), 4);
- // NOTE: would like to use simply "b".."d" here...
- let mut iter = map.range::<str, _>((Included("b"), Excluded("d")));
- assert_eq!(iter.next(), Some((&"baboon".to_string(), &2)));
- assert_eq!(iter.next(), Some((&"coyote".to_string(), &3)));
- assert_eq!(iter.next(), None);
-}
-
-#[test]
-fn test_range() {
- let size = 200;
- // Miri is too slow
- let step = if cfg!(miri) { 66 } else { 1 };
- let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- for i in (0..size).step_by(step) {
- for j in (i..size).step_by(step) {
- let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v));
- let mut pairs = (i..=j).map(|i| (i, i));
-
- for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
- assert_eq!(kv, pair);
- }
- assert_eq!(kvs.next(), None);
- assert_eq!(pairs.next(), None);
- }
- }
-}
-
-#[test]
-fn test_range_mut() {
- let size = 200;
- // Miri is too slow
- let step = if cfg!(miri) { 66 } else { 1 };
- let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
- for i in (0..size).step_by(step) {
- for j in (i..size).step_by(step) {
- let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v));
- let mut pairs = (i..=j).map(|i| (i, i));
-
- for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) {
- assert_eq!(kv, pair);
- }
- assert_eq!(kvs.next(), None);
- assert_eq!(pairs.next(), None);
- }
- }
-}
-
-mod test_drain_filter {
- use super::*;
-
- #[test]
- fn empty() {
- let mut map: BTreeMap<i32, i32> = BTreeMap::new();
- map.drain_filter(|_, _| unreachable!("there's nothing to decide on"));
- assert!(map.is_empty());
- }
-
- #[test]
- fn consuming_nothing() {
- let pairs = (0..3).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- assert!(map.drain_filter(|_, _| false).eq(std::iter::empty()));
- }
-
- #[test]
- fn consuming_all() {
- let pairs = (0..3).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- assert!(map.drain_filter(|_, _| true).eq(pairs));
- }
-
- #[test]
- fn mutating_and_keeping() {
- let pairs = (0..3).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- assert!(
- map.drain_filter(|_, v| {
- *v += 6;
- false
- })
- .eq(std::iter::empty())
- );
- assert!(map.keys().copied().eq(0..3));
- assert!(map.values().copied().eq(6..9));
- }
-
- #[test]
- fn mutating_and_removing() {
- let pairs = (0..3).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- assert!(
- map.drain_filter(|_, v| {
- *v += 6;
- true
- })
- .eq((0..3).map(|i| (i, i + 6)))
- );
- assert!(map.is_empty());
- }
-
- #[test]
- fn underfull_keeping_all() {
- let pairs = (0..3).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- map.drain_filter(|_, _| false);
- assert!(map.keys().copied().eq(0..3));
- }
-
- #[test]
- fn underfull_removing_one() {
- let pairs = (0..3).map(|i| (i, i));
- for doomed in 0..3 {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i == doomed);
- assert_eq!(map.len(), 2);
- }
- }
-
- #[test]
- fn underfull_keeping_one() {
- let pairs = (0..3).map(|i| (i, i));
- for sacred in 0..3 {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i != sacred);
- assert!(map.keys().copied().eq(sacred..=sacred));
- }
- }
-
- #[test]
- fn underfull_removing_all() {
- let pairs = (0..3).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- map.drain_filter(|_, _| true);
- assert!(map.is_empty());
- }
-
- #[test]
- fn height_0_keeping_all() {
- let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- map.drain_filter(|_, _| false);
- assert!(map.keys().copied().eq(0..NODE_CAPACITY));
- }
-
- #[test]
- fn height_0_removing_one() {
- let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
- for doomed in 0..NODE_CAPACITY {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i == doomed);
- assert_eq!(map.len(), NODE_CAPACITY - 1);
- }
- }
-
- #[test]
- fn height_0_keeping_one() {
- let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
- for sacred in 0..NODE_CAPACITY {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i != sacred);
- assert!(map.keys().copied().eq(sacred..=sacred));
- }
- }
-
- #[test]
- fn height_0_removing_all() {
- let pairs = (0..NODE_CAPACITY).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- map.drain_filter(|_, _| true);
- assert!(map.is_empty());
- }
-
- #[test]
- fn height_0_keeping_half() {
- let mut map: BTreeMap<_, _> = (0..16).map(|i| (i, i)).collect();
- assert_eq!(map.drain_filter(|i, _| *i % 2 == 0).count(), 8);
- assert_eq!(map.len(), 8);
- }
-
- #[test]
- fn height_1_removing_all() {
- let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- map.drain_filter(|_, _| true);
- assert!(map.is_empty());
- }
-
- #[test]
- fn height_1_removing_one() {
- let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
- for doomed in 0..MIN_INSERTS_HEIGHT_1 {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i == doomed);
- assert_eq!(map.len(), MIN_INSERTS_HEIGHT_1 - 1);
- }
- }
-
- #[test]
- fn height_1_keeping_one() {
- let pairs = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i));
- for sacred in 0..MIN_INSERTS_HEIGHT_1 {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i != sacred);
- assert!(map.keys().copied().eq(sacred..=sacred));
- }
- }
-
- #[cfg(not(miri))] // Miri is too slow
- #[test]
- fn height_2_removing_one() {
- let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
- for doomed in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i == doomed);
- assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
- }
- }
-
- #[cfg(not(miri))] // Miri is too slow
- #[test]
- fn height_2_keeping_one() {
- let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
- for sacred in (0..MIN_INSERTS_HEIGHT_2).step_by(12) {
- let mut map: BTreeMap<_, _> = pairs.clone().collect();
- map.drain_filter(|i, _| *i != sacred);
- assert!(map.keys().copied().eq(sacred..=sacred));
- }
- }
-
- #[test]
- fn height_2_removing_all() {
- let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
- let mut map: BTreeMap<_, _> = pairs.collect();
- map.drain_filter(|_, _| true);
- assert!(map.is_empty());
- }
-
- #[test]
- fn drop_panic_leak() {
- static PREDS: AtomicUsize = AtomicUsize::new(0);
- static DROPS: AtomicUsize = AtomicUsize::new(0);
-
- struct D;
- impl Drop for D {
- fn drop(&mut self) {
- if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
- panic!("panic in `drop`");
- }
- }
- }
-
- // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
- let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
-
- catch_unwind(move || {
- drop(map.drain_filter(|i, _| {
- PREDS.fetch_add(1usize << i, Ordering::SeqCst);
- true
- }))
- })
- .unwrap_err();
-
- assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
- assert_eq!(DROPS.load(Ordering::SeqCst), 3);
- }
-
- #[test]
- fn pred_panic_leak() {
- static PREDS: AtomicUsize = AtomicUsize::new(0);
- static DROPS: AtomicUsize = AtomicUsize::new(0);
-
- struct D;
- impl Drop for D {
- fn drop(&mut self) {
- DROPS.fetch_add(1, Ordering::SeqCst);
- }
- }
-
- // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
- let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
-
- catch_unwind(AssertUnwindSafe(|| {
- drop(map.drain_filter(|i, _| {
- PREDS.fetch_add(1usize << i, Ordering::SeqCst);
- match i {
- 0 => true,
- _ => panic!(),
- }
- }))
- }))
- .unwrap_err();
-
- assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
- assert_eq!(DROPS.load(Ordering::SeqCst), 1);
- assert_eq!(map.len(), 2);
- assert_eq!(map.first_entry().unwrap().key(), &4);
- assert_eq!(map.last_entry().unwrap().key(), &8);
- }
-
- // Same as above, but attempt to use the iterator again after the panic in the predicate
- #[test]
- fn pred_panic_reuse() {
- static PREDS: AtomicUsize = AtomicUsize::new(0);
- static DROPS: AtomicUsize = AtomicUsize::new(0);
-
- struct D;
- impl Drop for D {
- fn drop(&mut self) {
- DROPS.fetch_add(1, Ordering::SeqCst);
- }
- }
-
- // Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
- let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
-
- {
- let mut it = map.drain_filter(|i, _| {
- PREDS.fetch_add(1usize << i, Ordering::SeqCst);
- match i {
- 0 => true,
- _ => panic!(),
- }
- });
- catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
- // Iterator behaviour after a panic is explicitly unspecified,
- // so this is just the current implementation:
- let result = catch_unwind(AssertUnwindSafe(|| it.next()));
- assert!(matches!(result, Ok(None)));
- }
-
- assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
- assert_eq!(DROPS.load(Ordering::SeqCst), 1);
- assert_eq!(map.len(), 2);
- assert_eq!(map.first_entry().unwrap().key(), &4);
- assert_eq!(map.last_entry().unwrap().key(), &8);
- }
-}
-
-#[test]
-fn test_borrow() {
- // make sure these compile -- using the Borrow trait
- {
- let mut map = BTreeMap::new();
- map.insert("0".to_string(), 1);
- assert_eq!(map["0"], 1);
- }
-
- {
- let mut map = BTreeMap::new();
- map.insert(Box::new(0), 1);
- assert_eq!(map[&0], 1);
- }
-
- {
- let mut map = BTreeMap::new();
- map.insert(Box::new([0, 1]) as Box<[i32]>, 1);
- assert_eq!(map[&[0, 1][..]], 1);
- }
-
- {
- let mut map = BTreeMap::new();
- map.insert(Rc::new(0), 1);
- assert_eq!(map[&0], 1);
- }
-}
-
-#[test]
-fn test_entry() {
- let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
- let mut map: BTreeMap<_, _> = xs.iter().cloned().collect();
-
- // Existing key (insert)
- match map.entry(1) {
- Vacant(_) => unreachable!(),
- Occupied(mut view) => {
- assert_eq!(view.get(), &10);
- assert_eq!(view.insert(100), 10);
- }
- }
- assert_eq!(map.get(&1).unwrap(), &100);
- assert_eq!(map.len(), 6);
-
- // Existing key (update)
- match map.entry(2) {
- Vacant(_) => unreachable!(),
- Occupied(mut view) => {
- let v = view.get_mut();
- *v *= 10;
- }
- }
- assert_eq!(map.get(&2).unwrap(), &200);
- assert_eq!(map.len(), 6);
-
- // Existing key (take)
- match map.entry(3) {
- Vacant(_) => unreachable!(),
- Occupied(view) => {
- assert_eq!(view.remove(), 30);
- }
- }
- assert_eq!(map.get(&3), None);
- assert_eq!(map.len(), 5);
-
- // Inexistent key (insert)
- match map.entry(10) {
- Occupied(_) => unreachable!(),
- Vacant(view) => {
- assert_eq!(*view.insert(1000), 1000);
- }
- }
- assert_eq!(map.get(&10).unwrap(), &1000);
- assert_eq!(map.len(), 6);
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = BTreeMap::new();
- a.insert(1, "one");
- let mut b = BTreeMap::new();
- b.insert(2, "two");
- b.insert(3, "three");
-
- a.extend(&b);
-
- assert_eq!(a.len(), 3);
- assert_eq!(a[&1], "one");
- assert_eq!(a[&2], "two");
- assert_eq!(a[&3], "three");
-}
-
-#[test]
-fn test_zst() {
- let mut m = BTreeMap::new();
- assert_eq!(m.len(), 0);
-
- assert_eq!(m.insert((), ()), None);
- assert_eq!(m.len(), 1);
-
- assert_eq!(m.insert((), ()), Some(()));
- assert_eq!(m.len(), 1);
- assert_eq!(m.iter().count(), 1);
-
- m.clear();
- assert_eq!(m.len(), 0);
-
- for _ in 0..100 {
- m.insert((), ());
- }
-
- assert_eq!(m.len(), 1);
- assert_eq!(m.iter().count(), 1);
-}
-
-// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
-// do not cause segfaults when used with zero-sized values. All other map behavior is
-// undefined.
-#[test]
-fn test_bad_zst() {
- use std::cmp::Ordering;
-
- struct Bad;
-
- impl PartialEq for Bad {
- fn eq(&self, _: &Self) -> bool {
- false
- }
- }
-
- impl Eq for Bad {}
-
- impl PartialOrd for Bad {
- fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
- Some(Ordering::Less)
- }
- }
-
- impl Ord for Bad {
- fn cmp(&self, _: &Self) -> Ordering {
- Ordering::Less
- }
- }
-
- let mut m = BTreeMap::new();
-
- for _ in 0..100 {
- m.insert(Bad, Bad);
- }
-}
-
-#[test]
-fn test_clone() {
- let mut map = BTreeMap::new();
- let size = MIN_INSERTS_HEIGHT_1;
- assert_eq!(map.len(), 0);
-
- for i in 0..size {
- assert_eq!(map.insert(i, 10 * i), None);
- assert_eq!(map.len(), i + 1);
- assert_eq!(map, map.clone());
- }
-
- for i in 0..size {
- assert_eq!(map.insert(i, 100 * i), Some(10 * i));
- assert_eq!(map.len(), size);
- assert_eq!(map, map.clone());
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(i * 2)), Some(i * 200));
- assert_eq!(map.len(), size - i - 1);
- assert_eq!(map, map.clone());
- }
-
- for i in 0..size / 2 {
- assert_eq!(map.remove(&(2 * i)), None);
- assert_eq!(map.remove(&(2 * i + 1)), Some(i * 200 + 100));
- assert_eq!(map.len(), size / 2 - i - 1);
- assert_eq!(map, map.clone());
- }
-
- // Test a tree with 2 chock-full levels and a tree with 3 levels.
- map = (1..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
- assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2 - 1);
- assert_eq!(map, map.clone());
- map.insert(0, 0);
- assert_eq!(map.len(), MIN_INSERTS_HEIGHT_2);
- assert_eq!(map, map.clone());
-}
-
-#[test]
-fn test_clone_from() {
- let mut map1 = BTreeMap::new();
- let max_size = MIN_INSERTS_HEIGHT_1;
-
- // Range to max_size inclusive, because i is the size of map1 being tested.
- for i in 0..=max_size {
- let mut map2 = BTreeMap::new();
- for j in 0..i {
- let mut map1_copy = map2.clone();
- map1_copy.clone_from(&map1); // small cloned from large
- assert_eq!(map1_copy, map1);
- let mut map2_copy = map1.clone();
- map2_copy.clone_from(&map2); // large cloned from small
- assert_eq!(map2_copy, map2);
- map2.insert(100 * j + 1, 2 * j + 1);
- }
- map2.clone_from(&map1); // same length
- assert_eq!(map2, map1);
- map1.insert(i, 10 * i);
- }
-}
-
-#[test]
-#[allow(dead_code)]
-fn test_variance() {
- use std::collections::btree_map::{IntoIter, Iter, Keys, Range, Values};
-
- fn map_key<'new>(v: BTreeMap<&'static str, ()>) -> BTreeMap<&'new str, ()> {
- v
- }
- fn map_val<'new>(v: BTreeMap<(), &'static str>) -> BTreeMap<(), &'new str> {
- v
- }
- fn iter_key<'a, 'new>(v: Iter<'a, &'static str, ()>) -> Iter<'a, &'new str, ()> {
- v
- }
- fn iter_val<'a, 'new>(v: Iter<'a, (), &'static str>) -> Iter<'a, (), &'new str> {
- v
- }
- fn into_iter_key<'new>(v: IntoIter<&'static str, ()>) -> IntoIter<&'new str, ()> {
- v
- }
- fn into_iter_val<'new>(v: IntoIter<(), &'static str>) -> IntoIter<(), &'new str> {
- v
- }
- fn range_key<'a, 'new>(v: Range<'a, &'static str, ()>) -> Range<'a, &'new str, ()> {
- v
- }
- fn range_val<'a, 'new>(v: Range<'a, (), &'static str>) -> Range<'a, (), &'new str> {
- v
- }
- fn keys<'a, 'new>(v: Keys<'a, &'static str, ()>) -> Keys<'a, &'new str, ()> {
- v
- }
- fn vals<'a, 'new>(v: Values<'a, (), &'static str>) -> Values<'a, (), &'new str> {
- v
- }
-}
-
-#[test]
-fn test_occupied_entry_key() {
- let mut a = BTreeMap::new();
- let key = "hello there";
- let value = "value goes here";
- assert!(a.is_empty());
- a.insert(key.clone(), value.clone());
- assert_eq!(a.len(), 1);
- assert_eq!(a[key], value);
-
- match a.entry(key.clone()) {
- Vacant(_) => panic!(),
- Occupied(e) => assert_eq!(key, *e.key()),
- }
- assert_eq!(a.len(), 1);
- assert_eq!(a[key], value);
-}
-
-#[test]
-fn test_vacant_entry_key() {
- let mut a = BTreeMap::new();
- let key = "hello there";
- let value = "value goes here";
-
- assert!(a.is_empty());
- match a.entry(key.clone()) {
- Occupied(_) => panic!(),
- Vacant(e) => {
- assert_eq!(key, *e.key());
- e.insert(value.clone());
- }
- }
- assert_eq!(a.len(), 1);
- assert_eq!(a[key], value);
-}
-
-#[test]
-fn test_first_last_entry() {
- let mut a = BTreeMap::new();
- assert!(a.first_entry().is_none());
- assert!(a.last_entry().is_none());
- a.insert(1, 42);
- assert_eq!(a.first_entry().unwrap().key(), &1);
- assert_eq!(a.last_entry().unwrap().key(), &1);
- a.insert(2, 24);
- assert_eq!(a.first_entry().unwrap().key(), &1);
- assert_eq!(a.last_entry().unwrap().key(), &2);
- a.insert(0, 6);
- assert_eq!(a.first_entry().unwrap().key(), &0);
- assert_eq!(a.last_entry().unwrap().key(), &2);
- let (k1, v1) = a.first_entry().unwrap().remove_entry();
- assert_eq!(k1, 0);
- assert_eq!(v1, 6);
- let (k2, v2) = a.last_entry().unwrap().remove_entry();
- assert_eq!(k2, 2);
- assert_eq!(v2, 24);
- assert_eq!(a.first_entry().unwrap().key(), &1);
- assert_eq!(a.last_entry().unwrap().key(), &1);
-}
-
-macro_rules! create_append_test {
- ($name:ident, $len:expr) => {
- #[test]
- fn $name() {
- let mut a = BTreeMap::new();
- for i in 0..8 {
- a.insert(i, i);
- }
-
- let mut b = BTreeMap::new();
- for i in 5..$len {
- b.insert(i, 2 * i);
- }
-
- a.append(&mut b);
-
- assert_eq!(a.len(), $len);
- assert_eq!(b.len(), 0);
-
- for i in 0..$len {
- if i < 5 {
- assert_eq!(a[&i], i);
- } else {
- assert_eq!(a[&i], 2 * i);
- }
- }
-
- assert_eq!(a.remove(&($len - 1)), Some(2 * ($len - 1)));
- assert_eq!(a.insert($len - 1, 20), None);
- }
- };
-}
-
-// These are mostly for testing the algorithm that "fixes" the right edge after insertion.
-// Single node.
-create_append_test!(test_append_9, 9);
-// Two leafs that don't need fixing.
-create_append_test!(test_append_17, 17);
-// Two leafs where the second one ends up underfull and needs stealing at the end.
-create_append_test!(test_append_14, 14);
-// Two leafs where the second one ends up empty because the insertion finished at the root.
-create_append_test!(test_append_12, 12);
-// Three levels; insertion finished at the root.
-create_append_test!(test_append_144, 144);
-// Three levels; insertion finished at leaf while there is an empty node on the second level.
-create_append_test!(test_append_145, 145);
-// Tests for several randomly chosen sizes.
-create_append_test!(test_append_170, 170);
-create_append_test!(test_append_181, 181);
-#[cfg(not(miri))] // Miri is too slow
-create_append_test!(test_append_239, 239);
-#[cfg(not(miri))] // Miri is too slow
-create_append_test!(test_append_1700, 1700);
-
-fn rand_data(len: usize) -> Vec<(u32, u32)> {
- let mut rng = DeterministicRng::new();
- Vec::from_iter((0..len).map(|_| (rng.next(), rng.next())))
-}
-
-#[test]
-fn test_split_off_empty_right() {
- let mut data = rand_data(173);
-
- let mut map = BTreeMap::from_iter(data.clone());
- let right = map.split_off(&(data.iter().max().unwrap().0 + 1));
-
- data.sort();
- assert!(map.into_iter().eq(data));
- assert!(right.into_iter().eq(None));
-}
-
-#[test]
-fn test_split_off_empty_left() {
- let mut data = rand_data(314);
-
- let mut map = BTreeMap::from_iter(data.clone());
- let right = map.split_off(&data.iter().min().unwrap().0);
-
- data.sort();
- assert!(map.into_iter().eq(None));
- assert!(right.into_iter().eq(data));
-}
-
-// In a tree with 3 levels, if all but a part of the first leaf node is split off,
-// make sure fix_top eliminates both top levels.
-#[test]
-fn test_split_off_tiny_left_height_2() {
- let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
- let mut left: BTreeMap<_, _> = pairs.clone().collect();
- let right = left.split_off(&1);
- assert_eq!(left.len(), 1);
- assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1);
- assert_eq!(*left.first_key_value().unwrap().0, 0);
- assert_eq!(*right.first_key_value().unwrap().0, 1);
-}
-
-// In a tree with 3 levels, if only part of the last leaf node is split off,
-// make sure fix_top eliminates both top levels.
-#[test]
-fn test_split_off_tiny_right_height_2() {
- let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
- let last = MIN_INSERTS_HEIGHT_2 - 1;
- let mut left: BTreeMap<_, _> = pairs.clone().collect();
- assert_eq!(*left.last_key_value().unwrap().0, last);
- let right = left.split_off(&last);
- assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1);
- assert_eq!(right.len(), 1);
- assert_eq!(*left.last_key_value().unwrap().0, last - 1);
- assert_eq!(*right.last_key_value().unwrap().0, last);
-}
-
-#[test]
-fn test_split_off_large_random_sorted() {
- // Miri is too slow
- let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
- // special case with maximum height.
- data.sort();
-
- let mut map = BTreeMap::from_iter(data.clone());
- let key = data[data.len() / 2].0;
- let right = map.split_off(&key);
-
- assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key)));
- assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key)));
-}
-
-#[test]
-fn test_into_iter_drop_leak_height_0() {
- static DROPS: AtomicUsize = AtomicUsize::new(0);
-
- struct D;
-
- impl Drop for D {
- fn drop(&mut self) {
- if DROPS.fetch_add(1, Ordering::SeqCst) == 3 {
- panic!("panic in `drop`");
- }
- }
- }
-
- let mut map = BTreeMap::new();
- map.insert("a", D);
- map.insert("b", D);
- map.insert("c", D);
- map.insert("d", D);
- map.insert("e", D);
-
- catch_unwind(move || drop(map.into_iter())).unwrap_err();
-
- assert_eq!(DROPS.load(Ordering::SeqCst), 5);
-}
-
-#[test]
-fn test_into_iter_drop_leak_height_1() {
- let size = MIN_INSERTS_HEIGHT_1;
- static DROPS: AtomicUsize = AtomicUsize::new(0);
- static PANIC_POINT: AtomicUsize = AtomicUsize::new(0);
-
- struct D;
- impl Drop for D {
- fn drop(&mut self) {
- if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) {
- panic!("panic in `drop`");
- }
- }
- }
-
- for panic_point in vec![0, 1, size - 2, size - 1] {
- DROPS.store(0, Ordering::SeqCst);
- PANIC_POINT.store(panic_point, Ordering::SeqCst);
- let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
- catch_unwind(move || drop(map.into_iter())).unwrap_err();
- assert_eq!(DROPS.load(Ordering::SeqCst), size);
- }
-}
-
-#[test]
-fn test_into_keys() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map: BTreeMap<_, _> = vec.into_iter().collect();
- let keys: Vec<_> = map.into_keys().collect();
-
- assert_eq!(keys.len(), 3);
- assert!(keys.contains(&1));
- assert!(keys.contains(&2));
- assert!(keys.contains(&3));
-}
-
-#[test]
-fn test_into_values() {
- let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
- let map: BTreeMap<_, _> = vec.into_iter().collect();
- let values: Vec<_> = map.into_values().collect();
-
- assert_eq!(values.len(), 3);
- assert!(values.contains(&'a'));
- assert!(values.contains(&'b'));
- assert!(values.contains(&'c'));
-}
+++ /dev/null
-mod map;
-mod set;
-
-/// XorShiftRng
-struct DeterministicRng {
- x: u32,
- y: u32,
- z: u32,
- w: u32,
-}
-
-impl DeterministicRng {
- fn new() -> Self {
- DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
- }
-
- fn next(&mut self) -> u32 {
- let x = self.x;
- let t = x ^ (x << 11);
- self.x = self.y;
- self.y = self.z;
- self.z = self.w;
- let w_ = self.w;
- self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
- self.w
- }
-}
+++ /dev/null
-use std::collections::BTreeSet;
-use std::iter::FromIterator;
-use std::panic::{catch_unwind, AssertUnwindSafe};
-use std::sync::atomic::{AtomicU32, Ordering};
-
-use super::DeterministicRng;
-
-#[test]
-fn test_clone_eq() {
- let mut m = BTreeSet::new();
-
- m.insert(1);
- m.insert(2);
-
- assert_eq!(m.clone(), m);
-}
-
-#[test]
-fn test_hash() {
- use crate::hash;
-
- let mut x = BTreeSet::new();
- let mut y = BTreeSet::new();
-
- x.insert(1);
- x.insert(2);
- x.insert(3);
-
- y.insert(3);
- y.insert(2);
- y.insert(1);
-
- assert_eq!(hash(&x), hash(&y));
-}
-
-#[test]
-fn test_iter_min_max() {
- let mut a = BTreeSet::new();
- assert_eq!(a.iter().min(), None);
- assert_eq!(a.iter().max(), None);
- assert_eq!(a.range(..).min(), None);
- assert_eq!(a.range(..).max(), None);
- assert_eq!(a.difference(&BTreeSet::new()).min(), None);
- assert_eq!(a.difference(&BTreeSet::new()).max(), None);
- assert_eq!(a.intersection(&a).min(), None);
- assert_eq!(a.intersection(&a).max(), None);
- assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None);
- assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None);
- assert_eq!(a.union(&a).min(), None);
- assert_eq!(a.union(&a).max(), None);
- a.insert(1);
- a.insert(2);
- assert_eq!(a.iter().min(), Some(&1));
- assert_eq!(a.iter().max(), Some(&2));
- assert_eq!(a.range(..).min(), Some(&1));
- assert_eq!(a.range(..).max(), Some(&2));
- assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1));
- assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2));
- assert_eq!(a.intersection(&a).min(), Some(&1));
- assert_eq!(a.intersection(&a).max(), Some(&2));
- assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1));
- assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2));
- assert_eq!(a.union(&a).min(), Some(&1));
- assert_eq!(a.union(&a).max(), Some(&2));
-}
-
-fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F)
-where
- F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, &mut dyn FnMut(&i32) -> bool) -> bool,
-{
- let mut set_a = BTreeSet::new();
- let mut set_b = BTreeSet::new();
-
- for x in a {
- assert!(set_a.insert(*x))
- }
- for y in b {
- assert!(set_b.insert(*y))
- }
-
- let mut i = 0;
- f(&set_a, &set_b, &mut |&x| {
- if i < expected.len() {
- assert_eq!(x, expected[i]);
- }
- i += 1;
- true
- });
- assert_eq!(i, expected.len());
-}
-
-#[test]
-fn test_intersection() {
- fn check_intersection(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.intersection(y).all(f))
- }
-
- check_intersection(&[], &[], &[]);
- check_intersection(&[1, 2, 3], &[], &[]);
- check_intersection(&[], &[1, 2, 3], &[]);
- check_intersection(&[2], &[1, 2, 3], &[2]);
- check_intersection(&[1, 2, 3], &[2], &[2]);
- check_intersection(&[11, 1, 3, 77, 103, 5, -5], &[2, 11, 77, -9, -42, 5, 3], &[3, 5, 11, 77]);
-
- if cfg!(miri) {
- // Miri is too slow
- return;
- }
-
- let large = (0..100).collect::<Vec<_>>();
- check_intersection(&[], &large, &[]);
- check_intersection(&large, &[], &[]);
- check_intersection(&[-1], &large, &[]);
- check_intersection(&large, &[-1], &[]);
- check_intersection(&[0], &large, &[0]);
- check_intersection(&large, &[0], &[0]);
- check_intersection(&[99], &large, &[99]);
- check_intersection(&large, &[99], &[99]);
- check_intersection(&[100], &large, &[]);
- check_intersection(&large, &[100], &[]);
- check_intersection(&[11, 5000, 1, 3, 77, 8924], &large, &[1, 3, 11, 77]);
-}
-
-#[test]
-fn test_intersection_size_hint() {
- let x: BTreeSet<i32> = [3, 4].iter().copied().collect();
- let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
- let mut iter = x.intersection(&y);
- assert_eq!(iter.size_hint(), (1, Some(1)));
- assert_eq!(iter.next(), Some(&3));
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
-
- iter = y.intersection(&y);
- assert_eq!(iter.size_hint(), (0, Some(3)));
- assert_eq!(iter.next(), Some(&1));
- assert_eq!(iter.size_hint(), (0, Some(2)));
-}
-
-#[test]
-fn test_difference() {
- fn check_difference(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.difference(y).all(f))
- }
-
- check_difference(&[], &[], &[]);
- check_difference(&[1, 12], &[], &[1, 12]);
- check_difference(&[], &[1, 2, 3, 9], &[]);
- check_difference(&[1, 3, 5, 9, 11], &[3, 9], &[1, 5, 11]);
- check_difference(&[1, 3, 5, 9, 11], &[3, 6, 9], &[1, 5, 11]);
- check_difference(&[1, 3, 5, 9, 11], &[0, 1], &[3, 5, 9, 11]);
- check_difference(&[1, 3, 5, 9, 11], &[11, 12], &[1, 3, 5, 9]);
- check_difference(
- &[-5, 11, 22, 33, 40, 42],
- &[-12, -5, 14, 23, 34, 38, 39, 50],
- &[11, 22, 33, 40, 42],
- );
-
- if cfg!(miri) {
- // Miri is too slow
- return;
- }
-
- let large = (0..100).collect::<Vec<_>>();
- check_difference(&[], &large, &[]);
- check_difference(&[-1], &large, &[-1]);
- check_difference(&[0], &large, &[]);
- check_difference(&[99], &large, &[]);
- check_difference(&[100], &large, &[100]);
- check_difference(&[11, 5000, 1, 3, 77, 8924], &large, &[5000, 8924]);
- check_difference(&large, &[], &large);
- check_difference(&large, &[-1], &large);
- check_difference(&large, &[100], &large);
-}
-
-#[test]
-fn test_difference_size_hint() {
- let s246: BTreeSet<i32> = [2, 4, 6].iter().copied().collect();
- let s23456: BTreeSet<i32> = (2..=6).collect();
- let mut iter = s246.difference(&s23456);
- assert_eq!(iter.size_hint(), (0, Some(3)));
- assert_eq!(iter.next(), None);
-
- let s12345: BTreeSet<i32> = (1..=5).collect();
- iter = s246.difference(&s12345);
- assert_eq!(iter.size_hint(), (0, Some(3)));
- assert_eq!(iter.next(), Some(&6));
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
-
- let s34567: BTreeSet<i32> = (3..=7).collect();
- iter = s246.difference(&s34567);
- assert_eq!(iter.size_hint(), (0, Some(3)));
- assert_eq!(iter.next(), Some(&2));
- assert_eq!(iter.size_hint(), (0, Some(2)));
- assert_eq!(iter.next(), None);
-
- let s1: BTreeSet<i32> = (-9..=1).collect();
- iter = s246.difference(&s1);
- assert_eq!(iter.size_hint(), (3, Some(3)));
-
- let s2: BTreeSet<i32> = (-9..=2).collect();
- iter = s246.difference(&s2);
- assert_eq!(iter.size_hint(), (2, Some(2)));
- assert_eq!(iter.next(), Some(&4));
- assert_eq!(iter.size_hint(), (1, Some(1)));
-
- let s23: BTreeSet<i32> = (2..=3).collect();
- iter = s246.difference(&s23);
- assert_eq!(iter.size_hint(), (1, Some(3)));
- assert_eq!(iter.next(), Some(&4));
- assert_eq!(iter.size_hint(), (1, Some(1)));
-
- let s4: BTreeSet<i32> = (4..=4).collect();
- iter = s246.difference(&s4);
- assert_eq!(iter.size_hint(), (2, Some(3)));
- assert_eq!(iter.next(), Some(&2));
- assert_eq!(iter.size_hint(), (1, Some(2)));
- assert_eq!(iter.next(), Some(&6));
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
-
- let s56: BTreeSet<i32> = (5..=6).collect();
- iter = s246.difference(&s56);
- assert_eq!(iter.size_hint(), (1, Some(3)));
- assert_eq!(iter.next(), Some(&2));
- assert_eq!(iter.size_hint(), (0, Some(2)));
-
- let s6: BTreeSet<i32> = (6..=19).collect();
- iter = s246.difference(&s6);
- assert_eq!(iter.size_hint(), (2, Some(2)));
- assert_eq!(iter.next(), Some(&2));
- assert_eq!(iter.size_hint(), (1, Some(1)));
-
- let s7: BTreeSet<i32> = (7..=19).collect();
- iter = s246.difference(&s7);
- assert_eq!(iter.size_hint(), (3, Some(3)));
-}
-
-#[test]
-fn test_symmetric_difference() {
- fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f))
- }
-
- check_symmetric_difference(&[], &[], &[]);
- check_symmetric_difference(&[1, 2, 3], &[2], &[1, 3]);
- check_symmetric_difference(&[2], &[1, 2, 3], &[1, 3]);
- check_symmetric_difference(&[1, 3, 5, 9, 11], &[-2, 3, 9, 14, 22], &[-2, 1, 5, 11, 14, 22]);
-}
-
-#[test]
-fn test_symmetric_difference_size_hint() {
- let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
- let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
- let mut iter = x.symmetric_difference(&y);
- assert_eq!(iter.size_hint(), (0, Some(5)));
- assert_eq!(iter.next(), Some(&1));
- assert_eq!(iter.size_hint(), (0, Some(4)));
- assert_eq!(iter.next(), Some(&3));
- assert_eq!(iter.size_hint(), (0, Some(1)));
-}
-
-#[test]
-fn test_union() {
- fn check_union(a: &[i32], b: &[i32], expected: &[i32]) {
- check(a, b, expected, |x, y, f| x.union(y).all(f))
- }
-
- check_union(&[], &[], &[]);
- check_union(&[1, 2, 3], &[2], &[1, 2, 3]);
- check_union(&[2], &[1, 2, 3], &[1, 2, 3]);
- check_union(
- &[1, 3, 5, 9, 11, 16, 19, 24],
- &[-2, 1, 5, 9, 13, 19],
- &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24],
- );
-}
-
-#[test]
-fn test_union_size_hint() {
- let x: BTreeSet<i32> = [2, 4].iter().copied().collect();
- let y: BTreeSet<i32> = [1, 2, 3].iter().copied().collect();
- let mut iter = x.union(&y);
- assert_eq!(iter.size_hint(), (3, Some(5)));
- assert_eq!(iter.next(), Some(&1));
- assert_eq!(iter.size_hint(), (2, Some(4)));
- assert_eq!(iter.next(), Some(&2));
- assert_eq!(iter.size_hint(), (1, Some(2)));
-}
-
-#[test]
-// Only tests the simple function definition with respect to intersection
-fn test_is_disjoint() {
- let one = [1].iter().collect::<BTreeSet<_>>();
- let two = [2].iter().collect::<BTreeSet<_>>();
- assert!(one.is_disjoint(&two));
-}
-
-#[test]
-// Also implicitly tests the trivial function definition of is_superset
-fn test_is_subset() {
- fn is_subset(a: &[i32], b: &[i32]) -> bool {
- let set_a = a.iter().collect::<BTreeSet<_>>();
- let set_b = b.iter().collect::<BTreeSet<_>>();
- set_a.is_subset(&set_b)
- }
-
- assert_eq!(is_subset(&[], &[]), true);
- assert_eq!(is_subset(&[], &[1, 2]), true);
- assert_eq!(is_subset(&[0], &[1, 2]), false);
- assert_eq!(is_subset(&[1], &[1, 2]), true);
- assert_eq!(is_subset(&[2], &[1, 2]), true);
- assert_eq!(is_subset(&[3], &[1, 2]), false);
- assert_eq!(is_subset(&[1, 2], &[1]), false);
- assert_eq!(is_subset(&[1, 2], &[1, 2]), true);
- assert_eq!(is_subset(&[1, 2], &[2, 3]), false);
- assert_eq!(
- is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42]),
- true
- );
- assert_eq!(is_subset(&[-5, 11, 22, 33, 40, 42], &[-12, -5, 11, 14, 22, 23, 34, 38]), false);
-
- if cfg!(miri) {
- // Miri is too slow
- return;
- }
-
- let large = (0..100).collect::<Vec<_>>();
- assert_eq!(is_subset(&[], &large), true);
- assert_eq!(is_subset(&large, &[]), false);
- assert_eq!(is_subset(&[-1], &large), false);
- assert_eq!(is_subset(&[0], &large), true);
- assert_eq!(is_subset(&[1, 2], &large), true);
- assert_eq!(is_subset(&[99, 100], &large), false);
-}
-
-#[test]
-fn test_drain_filter() {
- let mut x: BTreeSet<_> = [1].iter().copied().collect();
- let mut y: BTreeSet<_> = [1].iter().copied().collect();
-
- x.drain_filter(|_| true);
- y.drain_filter(|_| false);
- assert_eq!(x.len(), 0);
- assert_eq!(y.len(), 1);
-}
-
-#[test]
-fn test_drain_filter_drop_panic_leak() {
- static PREDS: AtomicU32 = AtomicU32::new(0);
- static DROPS: AtomicU32 = AtomicU32::new(0);
-
- #[derive(PartialEq, Eq, PartialOrd, Ord)]
- struct D(i32);
- impl Drop for D {
- fn drop(&mut self) {
- if DROPS.fetch_add(1, Ordering::SeqCst) == 1 {
- panic!("panic in `drop`");
- }
- }
- }
-
- let mut set = BTreeSet::new();
- set.insert(D(0));
- set.insert(D(4));
- set.insert(D(8));
-
- catch_unwind(move || {
- drop(set.drain_filter(|d| {
- PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
- true
- }))
- })
- .ok();
-
- assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
- assert_eq!(DROPS.load(Ordering::SeqCst), 3);
-}
-
-#[test]
-fn test_drain_filter_pred_panic_leak() {
- static PREDS: AtomicU32 = AtomicU32::new(0);
- static DROPS: AtomicU32 = AtomicU32::new(0);
-
- #[derive(PartialEq, Eq, PartialOrd, Ord)]
- struct D(i32);
- impl Drop for D {
- fn drop(&mut self) {
- DROPS.fetch_add(1, Ordering::SeqCst);
- }
- }
-
- let mut set = BTreeSet::new();
- set.insert(D(0));
- set.insert(D(4));
- set.insert(D(8));
-
- catch_unwind(AssertUnwindSafe(|| {
- drop(set.drain_filter(|d| {
- PREDS.fetch_add(1u32 << d.0, Ordering::SeqCst);
- match d.0 {
- 0 => true,
- _ => panic!(),
- }
- }))
- }))
- .ok();
-
- assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
- assert_eq!(DROPS.load(Ordering::SeqCst), 1);
- assert_eq!(set.len(), 2);
- assert_eq!(set.first().unwrap().0, 4);
- assert_eq!(set.last().unwrap().0, 8);
-}
-
-#[test]
-fn test_clear() {
- let mut x = BTreeSet::new();
- x.insert(1);
-
- x.clear();
- assert!(x.is_empty());
-}
-
-#[test]
-fn test_zip() {
- let mut x = BTreeSet::new();
- x.insert(5);
- x.insert(12);
- x.insert(11);
-
- let mut y = BTreeSet::new();
- y.insert("foo");
- y.insert("bar");
-
- let x = x;
- let y = y;
- let mut z = x.iter().zip(&y);
-
- assert_eq!(z.next().unwrap(), (&5, &("bar")));
- assert_eq!(z.next().unwrap(), (&11, &("foo")));
- assert!(z.next().is_none());
-}
-
-#[test]
-fn test_from_iter() {
- let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
- let set: BTreeSet<_> = xs.iter().cloned().collect();
-
- for x in &xs {
- assert!(set.contains(x));
- }
-}
-
-#[test]
-fn test_show() {
- let mut set = BTreeSet::new();
- let empty = BTreeSet::<i32>::new();
-
- set.insert(1);
- set.insert(2);
-
- let set_str = format!("{:?}", set);
-
- assert_eq!(set_str, "{1, 2}");
- assert_eq!(format!("{:?}", empty), "{}");
-}
-
-#[test]
-fn test_extend_ref() {
- let mut a = BTreeSet::new();
- a.insert(1);
-
- a.extend(&[2, 3, 4]);
-
- assert_eq!(a.len(), 4);
- assert!(a.contains(&1));
- assert!(a.contains(&2));
- assert!(a.contains(&3));
- assert!(a.contains(&4));
-
- let mut b = BTreeSet::new();
- b.insert(5);
- b.insert(6);
-
- a.extend(&b);
-
- assert_eq!(a.len(), 6);
- assert!(a.contains(&1));
- assert!(a.contains(&2));
- assert!(a.contains(&3));
- assert!(a.contains(&4));
- assert!(a.contains(&5));
- assert!(a.contains(&6));
-}
-
-#[test]
-fn test_recovery() {
- use std::cmp::Ordering;
-
- #[derive(Debug)]
- struct Foo(&'static str, i32);
-
- impl PartialEq for Foo {
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
- }
-
- impl Eq for Foo {}
-
- impl PartialOrd for Foo {
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- self.0.partial_cmp(&other.0)
- }
- }
-
- impl Ord for Foo {
- fn cmp(&self, other: &Self) -> Ordering {
- self.0.cmp(&other.0)
- }
- }
-
- let mut s = BTreeSet::new();
- assert_eq!(s.replace(Foo("a", 1)), None);
- assert_eq!(s.len(), 1);
- assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
- assert_eq!(s.len(), 1);
-
- {
- let mut it = s.iter();
- assert_eq!(it.next(), Some(&Foo("a", 2)));
- assert_eq!(it.next(), None);
- }
-
- assert_eq!(s.get(&Foo("a", 1)), Some(&Foo("a", 2)));
- assert_eq!(s.take(&Foo("a", 1)), Some(Foo("a", 2)));
- assert_eq!(s.len(), 0);
-
- assert_eq!(s.get(&Foo("a", 1)), None);
- assert_eq!(s.take(&Foo("a", 1)), None);
-
- assert_eq!(s.iter().next(), None);
-}
-
-#[test]
-#[allow(dead_code)]
-fn test_variance() {
- use std::collections::btree_set::{IntoIter, Iter, Range};
-
- fn set<'new>(v: BTreeSet<&'static str>) -> BTreeSet<&'new str> {
- v
- }
- fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
- v
- }
- fn into_iter<'new>(v: IntoIter<&'static str>) -> IntoIter<&'new str> {
- v
- }
- fn range<'a, 'new>(v: Range<'a, &'static str>) -> Range<'a, &'new str> {
- v
- }
-}
-
-#[test]
-fn test_append() {
- let mut a = BTreeSet::new();
- a.insert(1);
- a.insert(2);
- a.insert(3);
-
- let mut b = BTreeSet::new();
- b.insert(3);
- b.insert(4);
- b.insert(5);
-
- a.append(&mut b);
-
- assert_eq!(a.len(), 5);
- assert_eq!(b.len(), 0);
-
- assert_eq!(a.contains(&1), true);
- assert_eq!(a.contains(&2), true);
- assert_eq!(a.contains(&3), true);
- assert_eq!(a.contains(&4), true);
- assert_eq!(a.contains(&5), true);
-}
-
-#[test]
-fn test_first_last() {
- let mut a = BTreeSet::new();
- assert_eq!(a.first(), None);
- assert_eq!(a.last(), None);
- a.insert(1);
- assert_eq!(a.first(), Some(&1));
- assert_eq!(a.last(), Some(&1));
- a.insert(2);
- assert_eq!(a.first(), Some(&1));
- assert_eq!(a.last(), Some(&2));
- for i in 3..=12 {
- a.insert(i);
- }
- assert_eq!(a.first(), Some(&1));
- assert_eq!(a.last(), Some(&12));
- assert_eq!(a.pop_first(), Some(1));
- assert_eq!(a.pop_last(), Some(12));
- assert_eq!(a.pop_first(), Some(2));
- assert_eq!(a.pop_last(), Some(11));
- assert_eq!(a.pop_first(), Some(3));
- assert_eq!(a.pop_last(), Some(10));
- assert_eq!(a.pop_first(), Some(4));
- assert_eq!(a.pop_first(), Some(5));
- assert_eq!(a.pop_first(), Some(6));
- assert_eq!(a.pop_first(), Some(7));
- assert_eq!(a.pop_first(), Some(8));
- assert_eq!(a.clone().pop_last(), Some(9));
- assert_eq!(a.pop_first(), Some(9));
- assert_eq!(a.pop_first(), None);
- assert_eq!(a.pop_last(), None);
-}
-
-fn rand_data(len: usize) -> Vec<u32> {
- let mut rng = DeterministicRng::new();
- Vec::from_iter((0..len).map(|_| rng.next()))
-}
-
-#[test]
-fn test_split_off_empty_right() {
- let mut data = rand_data(173);
-
- let mut set = BTreeSet::from_iter(data.clone());
- let right = set.split_off(&(data.iter().max().unwrap() + 1));
-
- data.sort();
- assert!(set.into_iter().eq(data));
- assert!(right.into_iter().eq(None));
-}
-
-#[test]
-fn test_split_off_empty_left() {
- let mut data = rand_data(314);
-
- let mut set = BTreeSet::from_iter(data.clone());
- let right = set.split_off(data.iter().min().unwrap());
-
- data.sort();
- assert!(set.into_iter().eq(None));
- assert!(right.into_iter().eq(data));
-}
-
-#[test]
-fn test_split_off_large_random_sorted() {
- // Miri is too slow
- let mut data = if cfg!(miri) { rand_data(529) } else { rand_data(1529) };
- // special case with maximum height.
- data.sort();
-
- let mut set = BTreeSet::from_iter(data.clone());
- let key = data[data.len() / 2];
- let right = set.split_off(&key);
-
- assert!(set.into_iter().eq(data.clone().into_iter().filter(|x| *x < key)));
- assert!(right.into_iter().eq(data.into_iter().filter(|x| *x >= key)));
-}
--- /dev/null
+use std::collections::BTreeSet;
+
+#[test]
+fn test_hash() {
+ use crate::hash;
+
+ let mut x = BTreeSet::new();
+ let mut y = BTreeSet::new();
+
+ x.insert(1);
+ x.insert(2);
+ x.insert(3);
+
+ y.insert(3);
+ y.insert(2);
+ y.insert(1);
+
+ assert_eq!(hash(&x), hash(&y));
+}
#![feature(allocator_api)]
#![feature(box_syntax)]
-#![feature(btree_drain_filter)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
-#![feature(map_first_last)]
-#![feature(map_into_keys_values)]
#![feature(new_uninit)]
#![feature(pattern)]
#![feature(str_split_once)]
mod binary_heap;
mod borrow;
mod boxed;
-mod btree;
+mod btree_set_hash;
mod cow_str;
mod fmt;
mod heap;
}
array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
+
+#[cfg(not(bootstrap))]
+#[lang = "array"]
+impl<T, const N: usize> [T; N] {
+ /// Returns an array of the same size as `self`, with function `f` applied to each element
+ /// in order.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(array_map)]
+ /// let x = [1, 2, 3];
+ /// let y = x.map(|v| v + 1);
+ /// assert_eq!(y, [2, 3, 4]);
+ ///
+ /// let x = [1, 2, 3];
+ /// let mut temp = 0;
+ /// let y = x.map(|v| { temp += 1; v * temp });
+ /// assert_eq!(y, [1, 4, 9]);
+ ///
+ /// let x = ["Ferris", "Bueller's", "Day", "Off"];
+ /// let y = x.map(|v| v.len());
+ /// assert_eq!(y, [6, 9, 3, 3]);
+ /// ```
+ #[unstable(feature = "array_map", issue = "75243")]
+ pub fn map<F, U>(self, mut f: F) -> [U; N]
+ where
+ F: FnMut(T) -> U,
+ {
+ use crate::mem::MaybeUninit;
+ struct Guard<T, const N: usize> {
+ dst: *mut T,
+ initialized: usize,
+ }
+
+ impl<T, const N: usize> Drop for Guard<T, N> {
+ fn drop(&mut self) {
+ debug_assert!(self.initialized <= N);
+
+ let initialized_part =
+ crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
+ // SAFETY: this raw slice will contain only initialized objects
+ // that's why, it is allowed to drop it.
+ unsafe {
+ crate::ptr::drop_in_place(initialized_part);
+ }
+ }
+ }
+ let mut dst = MaybeUninit::uninit_array::<N>();
+ let mut guard: Guard<U, N> =
+ Guard { dst: MaybeUninit::first_ptr_mut(&mut dst), initialized: 0 };
+ for (src, dst) in IntoIter::new(self).zip(&mut dst) {
+ dst.write(f(src));
+ guard.initialized += 1;
+ }
+ // FIXME: Convert to crate::mem::transmute once it works with generics.
+ // unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) }
+ crate::mem::forget(guard);
+ // SAFETY: At this point we've properly initialized the whole array
+ // and we just need to cast it to the correct type.
+ unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) }
+ }
+}
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
/// for a [`char`].
///
-/// [`char`]: ../../std/primitive.char.html
-/// [`u32`]: ../../std/primitive.u32.html
-///
/// For an unsafe version of this function which ignores these checks, see
/// [`from_u32_unchecked`].
///
-/// [`from_u32_unchecked`]: fn.from_u32_unchecked.html
-///
/// # Examples
///
/// Basic usage:
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
/// [`char`], possibly creating an invalid one.
///
-/// [`char`]: ../../std/primitive.char.html
-/// [`u32`]: ../../std/primitive.u32.html
-///
/// # Safety
///
/// This function is unsafe, as it may construct invalid `char` values.
///
/// For a safe version of this function, see the [`from_u32`] function.
///
-/// [`from_u32`]: fn.from_u32.html
-///
/// # Examples
///
/// Basic usage:
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
/// optimizations but will panic when executed.
///
-/// [`unreachable!`]: ../macro.unreachable.html
///
/// # Example
///
/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
/// do anything at all.
///
-/// [`core::sync::atomic::spin_loop_hint`]: ../sync/atomic/fn.spin_loop_hint.html
+/// [`core::sync::atomic::spin_loop_hint`]: crate::sync::atomic::spin_loop_hint
#[inline]
#[unstable(feature = "renamed_spin_loop", issue = "55002")]
pub fn spin_loop() {
/// collection into another. You take a collection, call [`iter`] on it,
/// do a bunch of transformations, and then `collect()` at the end.
///
- /// One of the keys to `collect()`'s power is that many things you might
- /// not think of as 'collections' actually are. For example, a [`String`]
- /// is a collection of [`char`]s. And a collection of
- /// [`Result<T, E>`][`Result`] can be thought of as single
- /// [`Result`]`<Collection<T>, E>`. See the examples below for more.
+ /// `collect()` can also create instances of types that are not typical
+ /// collections. For example, a [`String`] can be built from [`char`]s,
+ /// and an iterator of [`Result<T, E>`][`Result`] items can be collected
+ /// into `Result<Collection<T>, E>`. See the examples below for more.
///
/// Because `collect()` is so general, it can cause problems with type
/// inference. As such, `collect()` is one of the few times you'll see
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)]
+#![feature(maybe_uninit_extra)]
#![feature(external_doc)]
#![feature(associated_type_bounds)]
#![feature(const_caller_location)]
/// working with [pinned] data, where reusing the memory without calling the destructor could lead
/// to Undefined Behaviour.
///
-/// [`mem::zeroed`]: fn.zeroed.html
-/// [`MaybeUninit<T>`]: union.MaybeUninit.html
-/// [pinned]: ../pin/index.html
+/// [`mem::zeroed`]: crate::mem::zeroed
+/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
+/// [pinned]: crate::pin
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// leaving the state of this container unchanged.
/// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
///
- /// [`ManuallyDrop::drop`]: #method.drop
- /// [`ManuallyDrop::into_inner`]: #method.into_inner
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
#[stable(feature = "manually_drop_take", since = "1.42.0")]
#[inline]
/// This is normally prevented by the type system, but users of `ManuallyDrop` must
/// uphold those guarantees without assistance from the compiler.
///
- /// [`ManuallyDrop::into_inner`]: #method.into_inner
- /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html
- /// [pinned]: ../pin/index.html
+ /// [pinned]: crate::pin
#[stable(feature = "manually_drop", since = "1.20.0")]
#[inline]
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
///
- /// [`assume_init`]: #method.assume_init
+ /// [`assume_init`]: MaybeUninit::assume_init
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
#[inline(always)]
/// to ensure that that data may indeed be duplicated.
///
/// [inv]: #initialization-invariant
- /// [`assume_init`]: #method.assume_init
+ /// [`assume_init`]: MaybeUninit::assume_init
///
/// # Examples
///
//! }
//! ```
//!
-//! [`Option`]: enum.Option.html
-//! [`Some`]: enum.Option.html#variant.Some
-//! [`None`]: enum.Option.html#variant.None
//! [`Box<T>`]: ../../std/boxed/struct.Box.html
-//! [`i32`]: ../../std/primitive.i32.html
#![stable(feature = "rust1", since = "1.0.0")]
ops::{self, Deref, DerefMut},
};
-/// The `Option` type. See [the module level documentation](index.html) for more.
+/// The `Option` type. See [the module level documentation](self) for more.
#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[rustc_diagnostic_item = "option_type"]
#[stable(feature = "rust1", since = "1.0.0")]
/// let x: Option<u32> = None;
/// assert_eq!(x.is_some(), false);
/// ```
- ///
- /// [`Some`]: #variant.Some
#[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
#[inline]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
/// let x: Option<u32> = None;
/// assert_eq!(x.is_none(), true);
/// ```
- ///
- /// [`None`]: #variant.None
#[must_use = "if you intended to assert that this doesn't have a value, consider \
`.and_then(|| panic!(\"`Option` had a value when expected `None`\"))` instead"]
#[inline]
/// so this technique uses `as_ref` to first take an `Option` to a reference
/// to the value inside the original.
///
- /// [`map`]: enum.Option.html#method.map
+ /// [`map`]: Option::map
/// [`String`]: ../../std/string/struct.String.html
- /// [`usize`]: ../../std/primitive.usize.html
///
/// ```
/// let text: Option<String> = Some("Hello, world!".to_string());
}
/// Converts from [`Pin`]`<&Option<T>>` to `Option<`[`Pin`]`<&T>>`.
- ///
- /// [`Pin`]: ../pin/struct.Pin.html
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
}
/// Converts from [`Pin`]`<&mut Option<T>>` to `Option<`[`Pin`]`<&mut T>>`.
- ///
- /// [`Pin`]: ../pin/struct.Pin.html
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
/// Panics if the value is a [`None`] with a custom panic message provided by
/// `msg`.
///
- /// [`Some`]: #variant.Some
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// case explicitly, or call [`unwrap_or`], [`unwrap_or_else`], or
/// [`unwrap_or_default`].
///
- /// [`unwrap_or`]: #method.unwrap_or
- /// [`unwrap_or_else`]: #method.unwrap_or_else
- /// [`unwrap_or_default`]: #method.unwrap_or_default
+ /// [`unwrap_or`]: Option::unwrap_or
+ /// [`unwrap_or_else`]: Option::unwrap_or_else
+ /// [`unwrap_or_default`]: Option::unwrap_or_default
///
/// # Panics
///
/// Panics if the self value equals [`None`].
///
- /// [`Some`]: #variant.Some
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// the result of a function call, it is recommended to use [`unwrap_or_else`],
/// which is lazily evaluated.
///
- /// [`Some`]: #variant.Some
- /// [`unwrap_or_else`]: #method.unwrap_or_else
+ /// [`unwrap_or_else`]: Option::unwrap_or_else
///
/// # Examples
///
/// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, consuming the original:
///
/// [`String`]: ../../std/string/struct.String.html
- /// [`usize`]: ../../std/primitive.usize.html
- ///
/// ```
/// let maybe_some_string = Some(String::from("Hello, World!"));
/// // `Option::map` takes self *by value*, consuming `maybe_some_string`
/// the result of a function call, it is recommended to use [`map_or_else`],
/// which is lazily evaluated.
///
- /// [`map_or_else`]: #method.map_or_else
+ /// [`map_or_else`]: Option::map_or_else
///
/// # Examples
///
/// result of a function call, it is recommended to use [`ok_or_else`], which is
/// lazily evaluated.
///
- /// [`Result<T, E>`]: ../../std/result/enum.Result.html
- /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
- /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
- /// [`None`]: #variant.None
- /// [`Some(v)`]: #variant.Some
- /// [`ok_or_else`]: #method.ok_or_else
+ /// [`Result<T, E>`]: Result
+ /// [`Ok(v)`]: Ok
+ /// [`Err(err)`]: Err
+ /// [`Some(v)`]: Some
+ /// [`ok_or_else`]: Option::ok_or_else
///
/// # Examples
///
/// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
/// [`Ok(v)`] and [`None`] to [`Err(err())`].
///
- /// [`Result<T, E>`]: ../../std/result/enum.Result.html
- /// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
- /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
- /// [`None`]: #variant.None
- /// [`Some(v)`]: #variant.Some
+ /// [`Result<T, E>`]: Result
+ /// [`Ok(v)`]: Ok
+ /// [`Err(err())`]: Err
+ /// [`Some(v)`]: Some
///
/// # Examples
///
/// Returns [`None`] if the option is [`None`], otherwise returns `optb`.
///
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
///
/// Some languages call this operation flatmap.
///
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// assert_eq!(Some(4).filter(is_even), Some(4));
/// ```
///
- /// [`None`]: #variant.None
- /// [`Some(t)`]: #variant.Some
- /// [`Iterator::filter()`]: ../../std/iter/trait.Iterator.html#method.filter
#[inline]
#[stable(feature = "option_filter", since = "1.27.0")]
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
/// result of a function call, it is recommended to use [`or_else`], which is
/// lazily evaluated.
///
- /// [`or_else`]: #method.or_else
+ /// [`or_else`]: Option::or_else
///
/// # Examples
///
/// Returns [`Some`] if exactly one of `self`, `optb` is [`Some`], otherwise returns [`None`].
///
- /// [`Some`]: #variant.Some
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// Inserts `v` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// Inserts a value computed from `f` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// Takes the value out of the option, leaving a [`None`] in its place.
///
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// returning the old value if present,
/// leaving a [`Some`] in its place without deinitializing either one.
///
- /// [`Some`]: #variant.Some
- ///
/// # Examples
///
/// ```
/// Panics if the value is a [`Some`], with a panic message including the
/// passed message, and the content of the [`Some`].
///
- /// [`Some`]: #variant.Some
- /// [`None`]: #variant.None
- ///
/// # Examples
///
/// ```
/// Panics if the value is a [`Some`], with a custom panic message provided
/// by the [`Some`]'s value.
///
- /// [`Some(v)`]: #variant.Some
- /// [`None`]: #variant.None
+ /// [`Some(v)`]: Some
///
/// # Examples
///
/// assert_eq!(0, bad_year);
/// ```
///
- /// [`Some`]: #variant.Some
- /// [`None`]: #variant.None
- /// [default value]: ../default/trait.Default.html#tymethod.default
- /// [`parse`]: ../../std/primitive.str.html#method.parse
- /// [`FromStr`]: ../../std/str/trait.FromStr.html
+ /// [default value]: Default::default
+ /// [`parse`]: str::parse
+ /// [`FromStr`]: crate::str::FromStr
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_or_default(self) -> T {
/// Leaves the original Option in-place, creating a new one with a reference
/// to the original one, additionally coercing the contents via [`Deref`].
///
- /// [`Deref`]: ../../std/ops/trait.Deref.html
- ///
/// # Examples
///
/// ```
/// [`Some`]`(`[`Ok`]`(_))` and [`Some`]`(`[`Err`]`(_))` will be mapped to
/// [`Ok`]`(`[`Some`]`(_))` and [`Err`]`(_)`.
///
- /// [`None`]: #variant.None
- /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
- /// [`Some`]: #variant.Some
- /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
- ///
/// # Examples
///
/// ```
/// so this technique uses `as_ref` to first take an `Option` to a reference
/// to the value inside the original.
///
- /// [`map`]: ../../std/option/enum.Option.html#method.map
+ /// [`map`]: Option::map
/// [`String`]: ../../std/string/struct.String.html
- /// [`usize`]: ../../std/primitive.usize.html
///
/// ```
/// let s: Option<String> = Some(String::from("Hello, Rustaceans!"));
/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
///
/// This `struct` is created by the [`Option::iter`] function.
-///
-/// [`Option`]: enum.Option.html
-/// [`Some`]: enum.Option.html#variant.Some
-/// [`Option::iter`]: enum.Option.html#method.iter
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Iter<'a, A: 'a> {
/// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none.
///
/// This `struct` is created by the [`Option::iter_mut`] function.
-///
-/// [`Option`]: enum.Option.html
-/// [`Some`]: enum.Option.html#variant.Some
-/// [`Option::iter_mut`]: enum.Option.html#method.iter_mut
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IterMut<'a, A: 'a> {
///
/// This `struct` is created by the [`Option::into_iter`] function.
///
-/// [`Option`]: enum.Option.html
-/// [`Some`]: enum.Option.html#variant.Some
/// [`Option::into_iter`]: enum.Option.html#method.into_iter
#[derive(Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
///
/// Since the third element caused an underflow, no further elements were taken,
/// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
- ///
- /// [`Iterator`]: ../iter/trait.Iterator.html
#[inline]
fn from_iter<I: IntoIterator<Item = Option<A>>>(iter: I) -> Option<V> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
- // SAFETY: the caller must guarantee that the bytes `v`
- // are valid UTF-8, thus the cast to `*const str` is safe.
- // Also, the pointer dereference is safe because that pointer
- // comes from a reference which is guaranteed to be valid for reads.
- unsafe { &*(v as *const [u8] as *const str) }
+#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
+#[allow(unused_attributes)]
+#[allow_internal_unstable(const_fn_transmute)]
+pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
+ // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
+ // Also relies on `&str` and `&[u8]` having the same layout.
+ unsafe { mem::transmute(v) }
}
/// Converts a slice of bytes to a string slice without checking
#[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
#[inline(always)]
#[allow(unused_attributes)]
- #[allow_internal_unstable(const_fn_union)]
+ #[allow_internal_unstable(const_fn_transmute)]
pub const fn as_bytes(&self) -> &[u8] {
- #[repr(C)]
- union Slices<'a> {
- str: &'a str,
- slice: &'a [u8],
- }
// SAFETY: const sound because we transmute two types with the same layout
- unsafe { Slices { str: self }.slice }
+ unsafe { mem::transmute(self) }
}
/// Converts a mutable string slice to a mutable byte slice.
let _arr = <[DoesNotImplDefault; 0]>::default();
}
+
+#[test]
+fn array_map() {
+ let a = [1, 2, 3];
+ let b = a.map(|v| v + 1);
+ assert_eq!(b, [2, 3, 4]);
+
+ let a = [1u8, 2, 3];
+ let b = a.map(|v| v as u64);
+ assert_eq!(b, [1, 2, 3]);
+}
+
+// See note on above test for why `should_panic` is used.
+#[test]
+#[should_panic(expected = "test succeeded")]
+fn array_map_drop_safety() {
+ use core::sync::atomic::AtomicUsize;
+ use core::sync::atomic::Ordering;
+ static DROPPED: AtomicUsize = AtomicUsize::new(0);
+ struct DropCounter;
+ impl Drop for DropCounter {
+ fn drop(&mut self) {
+ DROPPED.fetch_add(1, Ordering::SeqCst);
+ }
+ }
+
+ let num_to_create = 5;
+ let success = std::panic::catch_unwind(|| {
+ let items = [0; 10];
+ let mut nth = 0;
+ items.map(|_| {
+ assert!(nth < num_to_create);
+ nth += 1;
+ DropCounter
+ });
+ });
+ assert!(success.is_err());
+ assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
+ panic!("test succeeded")
+}
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
+#![feature(array_map)]
#![feature(bool_to_option)]
#![feature(bound_cloned)]
#![feature(box_syntax)]
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
-libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.74", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.32" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
} else if target.contains("freebsd") {
println!("cargo:rustc-link-lib=execinfo");
println!("cargo:rustc-link-lib=pthread");
+ if env::var("RUST_STD_FREEBSD_12_ABI").is_ok() {
+ println!("cargo:rustc-cfg=freebsd12");
+ }
} else if target.contains("netbsd") {
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=rt");
+#![deny(unsafe_op_in_unsafe_fn)]
use crate::ascii;
use crate::borrow::{Borrow, Cow};
use crate::cmp::Ordering;
/// example, you can build a `CString` straight out of a [`String`] or
/// a [`&str`], since both implement that trait).
///
-/// The [`new`] method will actually check that the provided `&[u8]`
+/// The [`CString::new`] method will actually check that the provided `&[u8]`
/// does not have 0 bytes in the middle, and return an error if it
/// finds one.
///
/// # Extracting a raw pointer to the whole C string
///
-/// `CString` implements a [`as_ptr`] method through the [`Deref`]
+/// `CString` implements a [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
/// trait. This method will give you a `*const c_char` which you can
/// feed directly to extern functions that expect a nul-terminated
-/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a
+/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a
/// read-only pointer; if the C code writes to it, that causes
/// undefined behavior.
///
/// # Extracting a slice of the whole C string
///
/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
-/// `CString` with the [`as_bytes`] method. Slices produced in this
+/// `CString` with the [`CString::as_bytes`] method. Slices produced in this
/// way do *not* contain the trailing nul terminator. This is useful
/// when you will be calling an extern function that takes a `*const
/// u8` argument which is not necessarily nul-terminated, plus another
/// [`len`][slice.len] method.
///
/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
-/// can use [`as_bytes_with_nul`] instead.
+/// can use [`CString::as_bytes_with_nul`] instead.
///
/// Once you have the kind of slice you need (with or without a nul
/// terminator), you can call the slice's own
/// extern functions. See the documentation for that function for a
/// discussion on ensuring the lifetime of the raw pointer.
///
-/// [`Into`]: ../convert/trait.Into.html
-/// [`Vec`]: ../vec/struct.Vec.html
-/// [`String`]: ../string/struct.String.html
-/// [`&str`]: ../primitive.str.html
-/// [`u8`]: ../primitive.u8.html
-/// [`new`]: #method.new
-/// [`as_bytes`]: #method.as_bytes
-/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
-/// [`as_ptr`]: #method.as_ptr
+/// [`&str`]: str
/// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
/// [slice.len]: ../primitive.slice.html#method.len
-/// [`Deref`]: ../ops/trait.Deref.html
-/// [`CStr`]: struct.CStr.html
-/// [`&CStr`]: struct.CStr.html
+/// [`Deref`]: ops::Deref
+/// [`&CStr`]: CStr
///
/// # Examples
///
/// documentation of `CString` before use, as improper ownership management
/// of `CString` instances can lead to invalid memory accesses, memory leaks,
/// and other memory errors.
-
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
-/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
-/// interface to other consumers.
+/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide
+/// a safe interface to other consumers.
///
/// # Examples
///
/// println!("string: {}", my_string_safe());
/// ```
///
-/// [`u8`]: ../primitive.u8.html
-/// [`&str`]: ../primitive.str.html
-/// [`String`]: ../string/struct.String.html
-/// [`CString`]: struct.CString.html
-/// [`from_ptr`]: #method.from_ptr
+/// [`&str`]: str
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
/// This error is created by the [`new`][`CString::new`] method on
/// [`CString`]. See its documentation for more.
///
-/// [`CString`]: struct.CString.html
-/// [`CString::new`]: struct.CString.html#method.new
-///
/// # Examples
///
/// ```
/// The slice used to create a [`CStr`] must have one and only one nul byte,
/// positioned at the end.
///
-/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`].
+/// This error is created by the [`CStr::from_bytes_with_nul`] method.
/// See its documentation for more.
///
-/// [`CStr`]: struct.CStr.html
-/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
-///
/// # Examples
///
/// ```
/// The vector used to create a [`CString`] must have one and only one nul byte,
/// positioned at the end.
///
-/// This error is created by the [`from_vec_with_nul`] method on [`CString`].
+/// This error is created by the [`CString::from_vec_with_nul`] method.
/// See its documentation for more.
///
-/// [`CString`]: struct.CString.html
-/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
-///
/// # Examples
///
/// ```
///
/// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
/// ```
- ///
- /// [`CString`]: struct.CString.html
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..]
}
///
/// assert_eq!(bytes, value.unwrap_err().into_bytes());
/// ```
- ///
- /// [`CString`]: struct.CString.html
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
///
-/// `CString` is just a wrapper over a buffer of bytes with a nul
-/// terminator; [`into_string`][`CString::into_string`] performs UTF-8
-/// validation on those bytes and may return this error.
+/// `CString` is just a wrapper over a buffer of bytes with a nul terminator;
+/// [`CString::into_string`] performs UTF-8 validation on those bytes and may
+/// return this error.
///
-/// This `struct` is created by the
-/// [`into_string`][`CString::into_string`] method on [`CString`]. See
+/// This `struct` is created by [`CString::into_string()`]. See
/// its documentation for more.
-///
-/// [`String`]: ../string/struct.String.html
-/// [`CString`]: struct.CString.html
-/// [`CString::into_string`]: struct.CString.html#method.into_string
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstring_into", since = "1.7.0")]
pub struct IntoStringError {
/// This function will return an error if the supplied bytes contain an
/// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
/// the position of the nul byte.
- ///
- /// [`NulError`]: struct.NulError.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
trait SpecIntoVec {
/// Creates a C-compatible string by consuming a byte vector,
/// without checking for interior 0 bytes.
///
- /// This method is equivalent to [`new`] except that no runtime assertion
- /// is made that `v` contains no 0 bytes, and it requires an actual
- /// byte vector, not anything that can be converted to one with Into.
- ///
- /// [`new`]: #method.new
+ /// This method is equivalent to [`CString::new`] except that no runtime
+ /// assertion is made that `v` contains no 0 bytes, and it requires an
+ /// actual byte vector, not anything that can be converted to one with Into.
///
/// # Examples
///
CString { inner: v.into_boxed_slice() }
}
- /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`].
+ /// Retakes ownership of a `CString` that was transferred to C via
+ /// [`CString::into_raw`].
///
/// Additionally, the length of the string will be recalculated from the pointer.
///
/// # Safety
///
/// This should only ever be called with a pointer that was earlier
- /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g., trying to take
+ /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take
/// ownership of a string that was allocated by foreign code) is likely to lead
/// to undefined behavior or allocator corruption.
///
/// It should be noted that the length isn't just "recomputed," but that
/// the recomputed length must match the original length from the
- /// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods
- /// should not be used when passing the string to C functions that can
+ /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw`
+ /// methods should not be used when passing the string to C functions that can
/// modify the string's length.
///
/// > **Note:** If you need to borrow a string that was allocated by
/// > make your own provisions for freeing it appropriately, likely
/// > with the foreign code's API to do that.
///
- /// [`into_raw`]: #method.into_raw
- /// [`CStr`]: struct.CStr.html
- ///
/// # Examples
///
/// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
/// ```
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
- let len = sys::strlen(ptr) + 1; // Including the NUL byte
- let slice = slice::from_raw_parts_mut(ptr, len as usize);
- CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
+ // SAFETY: This is called with a pointer that was obtained from a call
+ // to `CString::into_raw` and the length has not been modified. As such,
+ // we know there is a NUL byte (and only one) at the end and that the
+ // information about the size of the allocation is correct on Rust's
+ // side.
+ unsafe {
+ let len = sys::strlen(ptr) + 1; // Including the NUL byte
+ let slice = slice::from_raw_parts_mut(ptr, len as usize);
+ CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
+ }
}
/// Consumes the `CString` and transfers ownership of the string to a C caller.
///
/// The pointer which this function returns must be returned to Rust and reconstituted using
- /// [`from_raw`] to be properly deallocated. Specifically, one
+ /// [`CString::from_raw`] to be properly deallocated. Specifically, one
/// should *not* use the standard C `free()` function to deallocate
/// this string.
///
- /// Failure to call [`from_raw`] will lead to a memory leak.
+ /// Failure to call [`CString::from_raw`] will lead to a memory leak.
///
/// The C side must **not** modify the length of the string (by writing a
/// `NULL` somewhere inside the string or removing the final one) before
- /// it makes it back into Rust using [`from_raw`]. See the safety section
- /// in [`from_raw`].
- ///
- /// [`from_raw`]: #method.from_raw
+ /// it makes it back into Rust using [`CString::from_raw`]. See the safety section
+ /// in [`CString::from_raw`].
///
/// # Examples
///
///
/// On failure, ownership of the original `CString` is returned.
///
- /// [`String`]: ../string/struct.String.html
- ///
/// # Examples
///
/// ```
vec
}
- /// Equivalent to the [`into_bytes`] function except that the returned vector
- /// includes the trailing nul terminator.
- ///
- /// [`into_bytes`]: #method.into_bytes
+ /// Equivalent to [`CString::into_bytes()`] except that the
+ /// returned vector includes the trailing nul terminator.
///
/// # Examples
///
/// The returned slice does **not** contain the trailing nul
/// terminator, and it is guaranteed to not have any interior nul
/// bytes. If you need the nul terminator, use
- /// [`as_bytes_with_nul`] instead.
- ///
- /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
+ /// [`CString::as_bytes_with_nul`] instead.
///
/// # Examples
///
&self.inner[..self.inner.len() - 1]
}
- /// Equivalent to the [`as_bytes`] function except that the returned slice
- /// includes the trailing nul terminator.
- ///
- /// [`as_bytes`]: #method.as_bytes
+ /// Equivalent to [`CString::as_bytes()`] except that the
+ /// returned slice includes the trailing nul terminator.
///
/// # Examples
///
/// Extracts a [`CStr`] slice containing the entire string.
///
- /// [`CStr`]: struct.CStr.html
- ///
/// # Examples
///
/// ```
/// Converts this `CString` into a boxed [`CStr`].
///
- /// [`CStr`]: struct.CStr.html
- ///
/// # Examples
///
/// ```
}
/// Bypass "move out of struct which implements [`Drop`] trait" restriction.
- ///
- /// [`Drop`]: ../ops/trait.Drop.html
fn into_inner(self) -> Box<[u8]> {
// Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
// so we use `ManuallyDrop` to ensure `self` is not dropped.
unsafe { ptr::read(&this.inner) }
}
- /// Converts a `Vec` of `u8` to a `CString` without checking the invariants
- /// on the given `Vec`.
+ /// Converts a [`Vec`]`<u8>` to a [`CString`] without checking the
+ /// invariants on the given [`Vec`].
///
/// # Safety
///
- /// The given `Vec` **must** have one nul byte as its last element.
+ /// The given [`Vec`] **must** have one nul byte as its last element.
/// This means it cannot be empty nor have any other nul byte anywhere else.
///
/// # Example
Self { inner: v.into_boxed_slice() }
}
- /// Attempts to converts a `Vec` of `u8` to a `CString`.
+ /// Attempts to converts a [`Vec`]`<u8>` to a [`CString`].
///
/// Runtime checks are present to ensure there is only one nul byte in the
- /// `Vec`, its last element.
+ /// [`Vec`], its last element.
///
/// # Errors
///
///
/// # Examples
///
- /// A successful conversion will produce the same result as [`new`] when
- /// called without the ending nul byte.
+ /// A successful conversion will produce the same result as [`CString::new`]
+ /// when called without the ending nul byte.
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// );
/// ```
///
- /// A incorrectly formatted vector will produce an error.
+ /// A incorrectly formatted [`Vec`] will produce an error.
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
/// // No nul byte
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
/// ```
- ///
- /// [`new`]: #method.new
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
let nul_pos = memchr::memchr(0, &v);
/// Converts a [`CString`] into a [`Vec`]`<u8>`.
///
/// The conversion consumes the [`CString`], and removes the terminating NUL byte.
- ///
- /// [`Vec`]: ../vec/struct.Vec.html
- /// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: CString) -> Vec<u8> {
s.into_bytes()
#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
- ///
- /// [`Box`]: ../boxed/struct.Box.html
- /// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
impl From<Vec<NonZeroU8>> for CString {
/// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
/// copying nor checking for inner null bytes.
- ///
- /// [`CString`]: ../ffi/struct.CString.html
- /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
- /// [`Vec`]: ../vec/struct.Vec.html
#[inline]
fn from(v: Vec<NonZeroU8>) -> CString {
unsafe {
#[stable(feature = "box_from_c_string", since = "1.20.0")]
impl From<CString> for Box<CStr> {
/// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
- ///
- /// [`CString`]: ../ffi/struct.CString.html
- /// [`Box`]: ../boxed/struct.Box.html
#[inline]
fn from(s: CString) -> Box<CStr> {
s.into_boxed_c_str()
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
/// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
- ///
- /// [`CString`]: ../ffi/struct.CString.html
- /// [`Arc`]: ../sync/struct.Arc.html
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
/// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
- ///
- /// [`CString`]: ../ffi/struct.CString.html
- /// [`Rc`]: ../rc/struct.Rc.html
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
/// Returns the position of the nul byte in the slice that caused
/// [`CString::new`] to fail.
///
- /// [`CString::new`]: struct.CString.html#method.new
- ///
/// # Examples
///
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
/// Converts a [`NulError`] into a [`io::Error`].
- ///
- /// [`NulError`]: ../ffi/struct.NulError.html
- /// [`io::Error`]: ../io/struct.Error.html
fn from(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
}
impl IntoStringError {
/// Consumes this error, returning original [`CString`] which generated the
/// error.
- ///
- /// [`CString`]: struct.CString.html
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_cstring(self) -> CString {
self.inner
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
- let len = sys::strlen(ptr);
- let ptr = ptr as *const u8;
- CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+ // SAFETY: The caller has provided a pointer that points to a valid C
+ // string with a NUL terminator of size less than `isize::MAX`, whose
+ // content remain valid and doesn't change for the lifetime of the
+ // returned `CStr`.
+ //
+ // Thus computing the length is fine (a NUL byte exists), the call to
+ // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
+ // the call to `from_bytes_with_nul_unchecked` is correct.
+ //
+ // The cast from c_char to u8 is ok because a c_char is always one byte.
+ unsafe {
+ let len = sys::strlen(ptr);
+ let ptr = ptr as *const u8;
+ CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+ }
}
/// Creates a C string wrapper from a byte slice.
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
- &*(bytes as *const [u8] as *const CStr)
+ // SAFETY: Casting to CStr is safe because its internal representation
+ // is a [u8] too (safe only inside std).
+ // Dereferencing the obtained pointer is safe because it comes from a
+ // reference. Making a reference is then safe because its lifetime
+ // is bound by the lifetime of the given `bytes`.
+ unsafe { &*(bytes as *const [u8] as *const CStr) }
}
/// Returns the inner pointer to this C string.
///
/// This happens because the pointer returned by `as_ptr` does not carry any
/// lifetime information and the [`CString`] is deallocated immediately after
- /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated.
+ /// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
+ /// expression is evaluated.
/// To fix the problem, bind the `CString` to a local variable:
///
/// ```no_run
/// }
/// ```
///
- /// This way, the lifetime of the `CString` in `hello` encompasses
+ /// This way, the lifetime of the [`CString`] in `hello` encompasses
/// the lifetime of `ptr` and the `unsafe` block.
- ///
- /// [`CString`]: struct.CString.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
/// Converts this C string to a byte slice containing the trailing 0 byte.
///
- /// This function is the equivalent of [`to_bytes`] except that it will retain
- /// the trailing nul terminator instead of chopping it off.
+ /// This function is the equivalent of [`CStr::to_bytes`] except that it
+ /// will retain the trailing nul terminator instead of chopping it off.
///
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
///
- /// [`to_bytes`]: #method.to_bytes
- ///
/// # Examples
///
/// ```
/// function will return the corresponding [`&str`] slice. Otherwise,
/// it will return an error with details of where UTF-8 validation failed.
///
- /// [`&str`]: ../primitive.str.html
+ /// [`&str`]: str
///
/// # Examples
///
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
/// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
///
- /// [`Cow`]: ../borrow/enum.Cow.html
- /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
- /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
- /// [`str`]: ../primitive.str.html
- /// [`String`]: ../string/struct.String.html
- /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
+ /// [`Borrowed`]: Cow::Borrowed
+ /// [`Owned`]: Cow::Owned
+ /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
///
/// # Examples
///
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
///
- /// [`Box`]: ../boxed/struct.Box.html
- /// [`CString`]: struct.CString.html
- ///
/// # Examples
///
/// ```
//! [`env::var_os()`] is used to query environment variables; it
//! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable
//! exists you will get a [`Some`]`(os_string)`, which you can *then* try to
-//! convert to a Rust string. This yields a [`Result<>`], so that
+//! convert to a Rust string. This yields a [`Result`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! method is an [`OsString`] which can be round-tripped to a Windows
//! string losslessly.
//!
-//! [`String`]: ../string/struct.String.html
-//! [`str`]: ../primitive.str.html
-//! [`char`]: ../primitive.char.html
-//! [`u8`]: ../primitive.u8.html
-//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
-//! [`CString`]: struct.CString.html
-//! [`CStr`]: struct.CStr.html
-//! [`OsString`]: struct.OsString.html
-//! [`OsStr`]: struct.OsStr.html
-//! [`env::set_var()`]: ../env/fn.set_var.html
-//! [`env::var_os()`]: ../env/fn.var_os.html
-//! [`Result<>`]: ../result/enum.Result.html
-//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
-//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
-//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
-//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
-//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
-//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
-//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
-//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
-//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
-//! [`collect`]: ../iter/trait.Iterator.html#method.collect
-//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
-//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide
-//! [`Option`]: ../option/enum.Option.html
-//! [`Some`]: ../option/enum.Option.html#variant.Some
+//! [`env::set_var()`]: crate::env::set_var
+//! [`env::var_os()`]: crate::env::var_os
+//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt
+//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec
+//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec
+//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt
+//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes
+//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes
+//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt
+//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt
+//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide
+//! [`collect`]: crate::iter::Iterator::collect
+//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt
+//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide
#![stable(feature = "rust1", since = "1.0.0")]
/// create an `OsString` from a normal Rust string.
///
/// **From slices:** Just like you can start with an empty Rust
-/// [`String`] and then [`push_str`][String.push_str] `&str`
+/// [`String`] and then [`String::push_str`] `&str`
/// sub-string slices into it, you can create an empty `OsString` with
-/// the [`new`] method and then push string slices into it with the
-/// [`push`] method.
+/// the [`OsString::new`] method and then push string slices into it with the
+/// [`OsString::push`] method.
///
/// # Extracting a borrowed reference to the whole OS string
///
-/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from
+/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from
/// an `OsString`; this is effectively a borrowed reference to the
/// whole string.
///
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsString` implements for [conversions] from/to native representations.
///
-/// [`OsStr`]: struct.OsStr.html
-/// [`&OsStr`]: struct.OsStr.html
-/// [`CStr`]: struct.CStr.html
-/// [`From`]: ../convert/trait.From.html
-/// [`String`]: ../string/struct.String.html
-/// [`&str`]: ../primitive.str.html
-/// [`u8`]: ../primitive.u8.html
-/// [`u16`]: ../primitive.u16.html
-/// [String.push_str]: ../string/struct.String.html#method.push_str
-/// [`new`]: #method.new
-/// [`push`]: #method.push
-/// [`as_os_str`]: #method.as_os_str
+/// [`&OsStr`]: OsStr
+/// [`&str`]: str
+/// [`CStr`]: crate::ffi::CStr
/// [conversions]: index.html#conversions
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsStr` implements for [conversions] from/to native representations.
///
-/// [`OsString`]: struct.OsString.html
-/// [`&str`]: ../primitive.str.html
-/// [`String`]: ../string/struct.String.html
+/// [`&str`]: str
/// [conversions]: index.html#conversions
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
/// Converts to an [`OsStr`] slice.
///
- /// [`OsStr`]: struct.OsStr.html
- ///
/// # Examples
///
/// ```
///
/// On failure, ownership of the original `OsString` is returned.
///
- /// [`String`]: ../../std/string/struct.String.html
- ///
/// # Examples
///
/// ```
/// Extends the string with the given [`&OsStr`] slice.
///
- /// [`&OsStr`]: struct.OsStr.html
+ /// [`&OsStr`]: OsStr
///
/// # Examples
///
/// Converts this `OsString` into a boxed [`OsStr`].
///
- /// [`OsStr`]: struct.OsStr.html
- ///
/// # Examples
///
/// ```
/// Converts a [`String`] into a [`OsString`].
///
/// The conversion copies the data, and includes an allocation on the heap.
- ///
- /// [`OsString`]: ../../std/ffi/struct.OsString.html
fn from(s: String) -> OsString {
OsString { inner: Buf::from_string(s) }
}
///
/// This conversion may entail doing a check for UTF-8 validity.
///
- /// [`&str`]: ../../std/primitive.str.html
+ /// [`&str`]: str
///
/// # Examples
///
/// Any non-Unicode sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
///
- /// [`Cow`]: ../../std/borrow/enum.Cow.html
- /// [`str`]: ../../std/primitive.str.html
- /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
+ /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
///
/// # Examples
///
/// Copies the slice into an owned [`OsString`].
///
- /// [`OsString`]: struct.OsString.html
- ///
/// # Examples
///
/// ```
/// This number is simply useful for passing to other methods, like
/// [`OsString::with_capacity`] to avoid reallocations.
///
- /// [`OsString`]: struct.OsString.html
- /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
- ///
/// # Examples
///
/// ```
}
/// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
- ///
- /// [`Box`]: ../boxed/struct.Box.html
- /// [`OsString`]: struct.OsString.html
#[stable(feature = "into_boxed_os_str", since = "1.20.0")]
pub fn into_os_string(self: Box<OsStr>) -> OsString {
let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
/// but non-ASCII letters are unchanged.
///
/// To return a new lowercased value without modifying the existing one, use
- /// [`to_ascii_lowercase`].
- ///
- /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
+ /// [`OsStr::to_ascii_lowercase`].
///
/// # Examples
///
/// but non-ASCII letters are unchanged.
///
/// To return a new uppercased value without modifying the existing one, use
- /// [`to_ascii_uppercase`].
- ///
- /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
+ /// [`OsStr::to_ascii_uppercase`].
///
/// # Examples
///
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
///
- /// To lowercase the value in-place, use [`make_ascii_lowercase`].
- ///
- /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
+ /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
///
/// # Examples
///
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
///
- /// To uppercase the value in-place, use [`make_ascii_uppercase`].
- ///
- /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
+ /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
///
/// # Examples
///
impl From<Box<OsStr>> for OsString {
/// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or
/// allocating.
- ///
- /// [`Box`]: ../boxed/struct.Box.html
- /// [`OsStr`]: ../ffi/struct.OsStr.html
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
#[stable(feature = "box_from_os_string", since = "1.20.0")]
impl From<OsString> for Box<OsStr> {
/// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
- ///
- /// [`Box`]: ../boxed/struct.Box.html
- /// [`OsString`]: ../ffi/struct.OsString.html
fn from(s: OsString) -> Box<OsStr> {
s.into_boxed_os_str()
}
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
/// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
- ///
- /// [`Arc`]: ../sync/struct.Arc.html
- /// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
/// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
- ///
- /// [`Rc`]: ../rc/struct.Rc.html
- /// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();
#[doc(keyword = "unsafe")]
//
-/// Code or interfaces whose [memory safety] cannot be verified by the type system.
+/// Code or interfaces whose [memory safety] cannot be verified by the type
+/// system.
+///
+/// The `unsafe` keyword has two uses: to declare the existence of contracts the
+/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a
+/// programmer has checked that these contracts have been upheld (`unsafe {}`
+/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually
+/// exclusive, as can be seen in `unsafe fn`.
+///
+/// # Unsafe abilities
+///
+/// **No matter what, Safe Rust can't cause Undefined Behavior**. This is
+/// referred to as [soundness]: a well-typed program actually has the desired
+/// properties. The [Nomicon][nomicon-soundness] has a more detailed explanation
+/// on the subject.
+///
+/// To ensure soundness, Safe Rust is restricted enough that it can be
+/// automatically checked. Sometimes, however, it is necessary to write code
+/// that is correct for reasons which are too clever for the compiler to
+/// understand. In those cases, you need to use Unsafe Rust.
+///
+/// Here are the abilities Unsafe Rust has in addition to Safe Rust:
+///
+/// - Dereference [raw pointers]
+/// - Implement `unsafe` [`trait`]s
+/// - Call `unsafe` functions
+/// - Mutate [`static`]s (including [`extern`]al ones)
+/// - Access fields of [`union`]s
+///
+/// However, this extra power comes with extra responsibilities: it is now up to
+/// you to ensure soundness. The `unsafe` keyword helps by clearly marking the
+/// pieces of code that need to worry about this.
+///
+/// ## The different meanings of `unsafe`
+///
+/// Not all uses of `unsafe` are equivalent: some are here to mark the existence
+/// of a contract the programmer must check, others are to say "I have checked
+/// the contract, go ahead and do this". The following
+/// [discussion on Rust Internals] has more in-depth explanations about this but
+/// here is a summary of the main points:
+///
+/// - `unsafe fn`: calling this function means abiding by a contract the
+/// compiler cannot enforce.
+/// - `unsafe trait`: implementing the [`trait`] means abiding by a
+/// contract the compiler cannot enforce.
+/// - `unsafe {}`: the contract necessary to call the operations inside the
+/// block has been checked by the programmer and is guaranteed to be respected.
+/// - `unsafe impl`: the contract necessary to implement the trait has been
+/// checked by the programmer and is guaranteed to be respected.
+///
+/// `unsafe fn` also acts like an `unsafe {}` block
+/// around the code inside the function. This means it is not just a signal to
+/// the caller, but also promises that the preconditions for the operations
+/// inside the function are upheld. Mixing these two meanings can be confusing
+/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when
+/// making `unsafe` operations.
+///
+/// See the [Rustnomicon] and the [Reference] for more informations.
///
-/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
+/// # Examples
+///
+/// ## Marking elements as `unsafe`
+///
+/// `unsafe` can be used on functions. Note that functions and statics declared
+/// in [`extern`] blocks are implicitly marked as `unsafe` (but not functions
+/// declared as `extern "something" fn ...`). Mutable statics are always unsafe,
+/// wherever they are declared. Methods can also be declared as `unsafe`:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// static mut FOO: &str = "hello";
+///
+/// unsafe fn unsafe_fn() {}
+///
+/// extern "C" {
+/// fn unsafe_extern_fn();
+/// static BAR: *mut u32;
+/// }
+///
+/// trait SafeTraitWithUnsafeMethod {
+/// unsafe fn unsafe_method(&self);
+/// }
+///
+/// struct S;
+///
+/// impl S {
+/// unsafe fn unsafe_method_on_struct() {}
+/// }
+/// ```
+///
+/// Traits can also be declared as `unsafe`:
+///
+/// ```rust
+/// unsafe trait UnsafeTrait {}
+/// ```
///
+/// Since `unsafe fn` and `unsafe trait` indicate that there is a safety
+/// contract that the compiler cannot enforce, documenting it is important. The
+/// standard library has many examples of this, like the following which is an
+/// extract from [`Vec::set_len`]. The `# Safety` section explains the contract
+/// that must be fulfilled to safely call the function.
+///
+/// ```rust,ignore (stub-to-show-doc-example)
+/// /// Forces the length of the vector to `new_len`.
+/// ///
+/// /// This is a low-level operation that maintains none of the normal
+/// /// invariants of the type. Normally changing the length of a vector
+/// /// is done using one of the safe operations instead, such as
+/// /// `truncate`, `resize`, `extend`, or `clear`.
+/// ///
+/// /// # Safety
+/// ///
+/// /// - `new_len` must be less than or equal to `capacity()`.
+/// /// - The elements at `old_len..new_len` must be initialized.
+/// pub unsafe fn set_len(&mut self, new_len: usize)
+/// ```
+///
+/// ## Using `unsafe {}` blocks and `impl`s
+///
+/// Performing `unsafe` operations requires an `unsafe {}` block:
+///
+/// ```rust
+/// # #![allow(dead_code)]
+/// /// Dereference the given pointer.
+/// ///
+/// /// # Safety
+/// ///
+/// /// `ptr` must be aligned and must not be dangling.
+/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 {
+/// *ptr
+/// }
+///
+/// let a = 3;
+/// let b = &a as *const _;
+/// // SAFETY: `a` has not been dropped and references are always aligned,
+/// // so `b` is a valid address.
+/// unsafe { assert_eq!(*b, deref_unchecked(b)); };
+/// ```
+///
+/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This
+/// makes a guarantee to other `unsafe` code that the implementation satisfies
+/// the trait's safety contract. The [Send] and [Sync] traits are examples of
+/// this behaviour in the standard library.
+///
+/// ```rust
+/// /// Implementors of this trait must guarantee an element is always
+/// /// accessible with index 3.
+/// unsafe trait ThreeIndexable<T> {
+/// /// Returns a reference to the element with index 3 in `&self`.
+/// fn three(&self) -> &T;
+/// }
+///
+/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe`
+/// // because the implementor must abide by a contract the compiler cannot
+/// // check but as a programmer we know there will always be a valid element
+/// // at index 3 to access.
+/// unsafe impl<T> ThreeIndexable<T> for [T; 4] {
+/// fn three(&self) -> &T {
+/// // SAFETY: implementing the trait means there always is an element
+/// // with index 3 accessible.
+/// unsafe { self.get_unchecked(3) }
+/// }
+/// }
+///
+/// let a = [1, 2, 4, 8];
+/// assert_eq!(a.three(), &8);
+/// ```
+///
+/// [`extern`]: keyword.extern.html
+/// [`trait`]: keyword.trait.html
+/// [`static`]: keyword.static.html
+/// [`union`]: keyword.union.html
+/// [`impl`]: keyword.impl.html
+/// [Send]: marker/trait.Send.html
+/// [Sync]: marker/trait.Sync.html
+/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len
+/// [raw pointers]: ../reference/types/pointer.html
/// [memory safety]: ../book/ch19-01-unsafe-rust.html
-/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
+/// [Rustnomicon]: ../nomicon/index.html
+/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html
+/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
+/// [Reference]: ../reference/unsafety.html
+/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585
+/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696
mod unsafe_keyword {}
#[doc(keyword = "use")]
/// The size of a `SocketAddr` instance may vary depending on the target operating
/// system.
///
-/// [IP address]: ../../std/net/enum.IpAddr.html
-/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+/// [IP address]: IpAddr
///
/// # Examples
///
/// assert_eq!(socket.port(), 8080);
/// assert_eq!(socket.is_ipv4(), true);
/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum SocketAddr {
/// An IPv4 socket address.
/// An IPv4 socket address.
///
-/// IPv4 socket addresses consist of an [IPv4 address] and a 16-bit port number, as
+/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
/// stated in [IETF RFC 793].
///
/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
/// system.
///
/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`IPv4` address]: Ipv4Addr
///
/// # Examples
///
/// An IPv6 socket address.
///
-/// IPv6 socket addresses consist of an [Ipv6 address], a 16-bit port number, as well
+/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
/// as fields containing the traffic class, the flow label, and a scope identifier
/// (see [IETF RFC 2553, Section 3.3] for more details).
///
/// system.
///
/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-/// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`IPv6` address]: Ipv6Addr
///
/// # Examples
///
impl SocketAddr {
/// Creates a new socket address from an [IP address] and a port number.
///
- /// [IP address]: ../../std/net/enum.IpAddr.html
+ /// [IP address]: IpAddr
///
/// # Examples
///
}
/// Returns [`true`] if the [IP address] in this `SocketAddr` is an
- /// [IPv4 address], and [`false`] otherwise.
+ /// [`IPv4` address], and [`false`] otherwise.
///
- /// [`true`]: ../../std/primitive.bool.html
+ /// [IP address]: IpAddr
+ /// [`IPv4` address]: IpAddr::V4
/// [`false`]: ../../std/primitive.bool.html
- /// [IP address]: ../../std/net/enum.IpAddr.html
- /// [IPv4 address]: ../../std/net/enum.IpAddr.html#variant.V4
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
/// Returns [`true`] if the [IP address] in this `SocketAddr` is an
- /// [IPv6 address], and [`false`] otherwise.
+ /// [`IPv6` address], and [`false`] otherwise.
///
- /// [`true`]: ../../std/primitive.bool.html
+ /// [IP address]: IpAddr
+ /// [`IPv6` address]: IpAddr::V6
/// [`false`]: ../../std/primitive.bool.html
- /// [IP address]: ../../std/net/enum.IpAddr.html
- /// [IPv6 address]: ../../std/net/enum.IpAddr.html#variant.V6
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
}
impl SocketAddrV4 {
- /// Creates a new socket address from an [IPv4 address] and a port number.
+ /// Creates a new socket address from an [`IPv4` address] and a port number.
///
- /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+ /// [`IPv4` address]: Ipv4Addr
///
/// # Examples
///
}
impl SocketAddrV6 {
- /// Creates a new socket address from an [IPv6 address], a 16-bit port number,
+ /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
/// and the `flowinfo` and `scope_id` fields.
///
/// For more information on the meaning and layout of the `flowinfo` and `scope_id`
/// parameters, see [IETF RFC 2553, Section 3.3].
///
/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
- /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+ /// [`IPv6` address]: Ipv6Addr
///
/// # Examples
///
/// Changes the flow information associated with this socket address.
///
- /// See the [`flowinfo`] method's documentation for more details.
- ///
- /// [`flowinfo`]: #method.flowinfo
+ /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
///
/// # Examples
///
/// Changes the scope ID associated with this socket address.
///
- /// See the [`scope_id`] method's documentation for more details.
- ///
- /// [`scope_id`]: #method.scope_id
+ /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
///
/// # Examples
///
#[stable(feature = "ip_from_ip", since = "1.16.0")]
impl From<SocketAddrV4> for SocketAddr {
/// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
- ///
- /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
- /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
fn from(sock4: SocketAddrV4) -> SocketAddr {
SocketAddr::V4(sock4)
}
#[stable(feature = "ip_from_ip", since = "1.16.0")]
impl From<SocketAddrV6> for SocketAddr {
/// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
- ///
- /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
- /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
fn from(sock6: SocketAddrV6) -> SocketAddr {
SocketAddr::V6(sock6)
}
/// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`].
///
/// `u16` is treated as port of the newly created [`SocketAddr`].
- ///
- /// [`IpAddr`]: ../../std/net/enum.IpAddr.html
- /// [`IpAddr::V4`]: ../../std/net/enum.IpAddr.html#variant.V4
- /// [`IpAddr::V6`]: ../../std/net/enum.IpAddr.html#variant.V6
- /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
- /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4
- /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6
fn from(pieces: (I, u16)) -> SocketAddr {
SocketAddr::new(pieces.0.into(), pieces.1)
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for SocketAddrV4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// Addresses returned by the operating system that are not IP addresses are
/// silently ignored.
///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
-/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
-/// [`&str`]: ../../std/primitive.str.html
-/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
-/// [`to_socket_addrs`]: #tymethod.to_socket_addrs
-/// [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
-/// [`u16`]: ../../std/primitive.u16.html
+/// [`FromStr`]: crate::str::FromStr
+/// [`&str`]: str
+/// [`TcpStream`]: crate::net::TcpStream
+/// [`to_socket_addrs`]: ToSocketAddrs::to_socket_addrs
+/// [`UdpSocket`]: crate::net::UdpSocket
///
/// # Examples
///
/// let stream = TcpStream::connect((Ipv4Addr::new(127, 0, 0, 1), 443));
/// ```
///
-/// [`TcpStream::connect`]: ../../std/net/struct.TcpStream.html#method.connect
+/// [`TcpStream::connect`]: crate::net::TcpStream::connect
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToSocketAddrs {
/// Returned iterator over socket addresses which this type may correspond
/// The size of an `IpAddr` instance may vary depending on the target operating
/// system.
///
-/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-///
/// # Examples
///
/// ```
/// assert_eq!(localhost_v4.is_ipv4(), true);
/// ```
#[stable(feature = "ip_addr", since = "1.7.0")]
-#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum IpAddr {
/// An IPv4 address.
#[stable(feature = "ip_addr", since = "1.7.0")]
/// system.
///
/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
///
/// # Textual representation
///
/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
/// notation, divided by `.` (this is called "dot-decimal notation").
///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`FromStr`]: crate::str::FromStr
///
/// # Examples
///
/// system.
///
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
///
/// # Textual representation
///
/// notation, and segments are separated by `:`. For more information, see
/// [IETF RFC 5952].
///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`FromStr`]: crate::str::FromStr
/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
///
/// # Examples
impl IpAddr {
/// Returns [`true`] for the special 'unspecified' address.
///
- /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
- /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
+ /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
+ /// [`Ipv6Addr::is_unspecified()`] for more details.
///
- /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
- /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
/// Returns [`true`] if this is a loopback address.
///
- /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
- /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
+ /// See the documentation for [`Ipv4Addr::is_loopback()`] and
+ /// [`Ipv6Addr::is_loopback()`] for more details.
///
- /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
- /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
/// Returns [`true`] if the address appears to be globally routable.
///
- /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
- /// [`Ipv6Addr::is_global`][IPv6] for more details.
+ /// See the documentation for [`Ipv4Addr::is_global()`] and
+ /// [`Ipv6Addr::is_global()`] for more details.
///
- /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
- /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
/// Returns [`true`] if this is a multicast address.
///
- /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
- /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
+ /// See the documentation for [`Ipv4Addr::is_multicast()`] and
+ /// [`Ipv6Addr::is_multicast()`] for more details.
///
- /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
- /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
/// Returns [`true`] if this address is in a range designated for documentation.
///
- /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
- /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
+ /// See the documentation for [`Ipv4Addr::is_documentation()`] and
+ /// [`Ipv6Addr::is_documentation()`] for more details.
///
- /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
- /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
}
}
- /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
+ /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
+ /// otherwise.
///
/// [`true`]: ../../std/primitive.bool.html
/// [`false`]: ../../std/primitive.bool.html
- /// [IPv4 address]: #variant.V4
+ /// [`IPv4` address]: IpAddr::V4
///
/// # Examples
///
matches!(self, IpAddr::V4(_))
}
- /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
+ /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
+ /// otherwise.
///
/// [`true`]: ../../std/primitive.bool.html
/// [`false`]: ../../std/primitive.bool.html
- /// [IPv6 address]: #variant.V6
+ /// [`IPv6` address]: IpAddr::V6
///
/// # Examples
///
/// This property is defined in _UNIX Network Programming, Second Edition_,
/// W. Richard Stevens, p. 891; see also [ip7].
///
- /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
/// [`true`]: ../../std/primitive.bool.html
+ /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
///
/// # Examples
///
///
/// This property is defined by [IETF RFC 1122].
///
- /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
///
/// # Examples
///
/// - 172.16.0.0/12
/// - 192.168.0.0/16
///
- /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
///
/// # Examples
///
///
/// This property is defined by [IETF RFC 3927].
///
- /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
///
/// # Examples
///
/// Returns [`true`] if the address appears to be globally routable.
/// See [iana-ipv4-special-registry][ipv4-sr].
///
- /// The following return false:
+ /// The following return [`false`]:
///
- /// - private addresses (see [`is_private()`](#method.is_private))
- /// - the loopback address (see [`is_loopback()`](#method.is_loopback))
- /// - the link-local address (see [`is_link_local()`](#method.is_link_local))
- /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
- /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
- /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
+ /// - private addresses (see [`Ipv4Addr::is_private()`])
+ /// - the loopback address (see [`Ipv4Addr::is_loopback()`])
+ /// - the link-local address (see [`Ipv4Addr::is_link_local()`])
+ /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
+ /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
+ /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
/// 0.0.0.0/8 block
/// - addresses reserved for future protocols (see
- /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
+ /// [`Ipv4Addr::is_ietf_protocol_assignment()`], except
/// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
- /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved)
+ /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
/// - addresses reserved for networking devices benchmarking (see
- /// [`is_benchmarking`](#method.is_benchmarking))
+ /// [`Ipv4Addr::is_benchmarking()`])
///
- /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
/// [`true`]: ../../std/primitive.bool.html
+ /// [`false`]: ../../std/primitive.bool.html
+ /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
///
/// # Examples
///
/// Returns [`true`] if this address is part of the Shared Address Space defined in
/// [IETF RFC 6598] (`100.64.0.0/10`).
///
- /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
///
/// # Examples
///
/// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
/// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
///
+ /// [`true`]: ../../std/primitive.bool.html
/// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
/// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
/// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
/// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
- /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
/// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
/// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
///
+ /// [`true`]: ../../std/primitive.bool.html
/// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
/// [errata 423]: https://www.rfc-editor.org/errata/eid423
- /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
/// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
/// it is obviously not reserved for future use.
///
- /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
///
/// # Warning
///
/// Multicast addresses have a most significant octet between 224 and 239,
/// and is defined by [IETF RFC 5771].
///
- /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
///
/// # Examples
///
///
/// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
///
- /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
///
/// # Examples
///
/// - 198.51.100.0/24 (TEST-NET-2)
/// - 203.0.113.0/24 (TEST-NET-3)
///
- /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
///
/// # Examples
///
}
}
- /// Converts this address to an IPv4-compatible [IPv6 address].
+ /// Converts this address to an IPv4-compatible [`IPv6` address].
///
/// a.b.c.d becomes ::a.b.c.d
///
- /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+ /// [`IPv6` address]: Ipv6Addr
///
/// # Examples
///
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
}
- /// Converts this address to an IPv4-mapped [IPv6 address].
+ /// Converts this address to an IPv4-mapped [`IPv6` address].
///
/// a.b.c.d becomes ::ffff:a.b.c.d
///
- /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+ /// [`IPv6` address]: Ipv6Addr
///
/// # Examples
///
}
}
+#[stable(feature = "ip_addr", since = "1.7.0")]
+impl fmt::Debug for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(self, fmt)
+ }
+}
+
#[stable(feature = "ip_from_ip", since = "1.16.0")]
impl From<Ipv4Addr> for IpAddr {
/// Copies this address to a new `IpAddr::V4`.
///
/// This property is defined in [IETF RFC 4291].
///
- /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
///
/// # Examples
///
///
/// This property is defined in [IETF RFC 4291].
///
- /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
///
/// # Examples
///
/// This property is defined in [IETF RFC 4193].
///
/// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+ ///
/// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
/// This method validates the format defined in the RFC and won't recognize the following
/// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
- /// If you need a less strict validation use [`is_unicast_link_local()`] instead.
+ /// If you need a less strict validation use [`Ipv6Addr::is_unicast_link_local()`] instead.
+ ///
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
/// - [IETF RFC 4291 section 2.5.6]
/// - [RFC 4291 errata 4406] (which has been rejected but provides useful
/// insight)
- /// - [`is_unicast_link_local()`]
+ /// - [`Ipv6Addr::is_unicast_link_local()`]
///
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
/// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
- /// [`true`]: ../../std/primitive.bool.html
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
- /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local
pub fn is_unicast_link_local_strict(&self) -> bool {
(self.segments()[0] & 0xffff) == 0xfe80
&& (self.segments()[1] & 0xffff) == 0
/// ```
///
/// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
- /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you
- /// need a strict validation fully compliant with the RFC, use
- /// [`is_unicast_link_local_strict()`].
+ /// unicast link-local addresses, whereas [`Ipv6Addr::is_unicast_link_local_strict()`] does not.
+ /// If you need a strict validation fully compliant with the RFC, use
+ /// [`Ipv6Addr::is_unicast_link_local_strict()`] instead.
+ ///
+ /// [`true`]: ../../std/primitive.bool.html
///
/// # Examples
///
/// insight)
///
/// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
- /// [`true`]: ../../std/primitive.bool.html
/// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
- /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict
pub fn is_unicast_link_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfe80
}
///
/// This property is defined in [IETF RFC 3849].
///
- /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
///
/// # Examples
///
///
/// This property is defined by [IETF RFC 4291].
///
- /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
/// [`true`]: ../../std/primitive.bool.html
+ /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
///
/// # Examples
///
(self.segments()[0] & 0xff00) == 0xff00
}
- /// Converts this address to an [IPv4 address] if it's an "IPv4-mapped IPv6 address"
+ /// Converts this address to an [`IPv4` address] if it's an "IPv4-mapped IPv6 address"
/// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
///
/// `::ffff:a.b.c.d` becomes `a.b.c.d`.
/// All addresses *not* starting with `::ffff` will return `None`.
///
- /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
+ /// [`IPv4` address]: Ipv4Addr
/// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
///
/// # Examples
}
}
- /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
+ /// Converts this address to an [`IPv4` address]. Returns [`None`] if this address is
/// neither IPv4-compatible or IPv4-mapped.
///
/// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
///
- /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
+ /// [`IPv4` address]: Ipv4Addr
///
/// # Examples
///
//! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting
//! with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`]
//! * Other types are return or parameter types for various methods in this module
-//!
-//! [`IpAddr`]: ../../std/net/enum.IpAddr.html
-//! [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-//! [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-//! [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-//! [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-//! [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
-//! [`TcpListener`]: ../../std/net/struct.TcpListener.html
-//! [`TcpStream`]: ../../std/net/struct.TcpStream.html
-//! [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
-//! [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
#![stable(feature = "rust1", since = "1.0.0")]
mod test;
mod udp;
-/// Possible values which can be passed to the [`shutdown`] method of
-/// [`TcpStream`].
-///
-/// [`shutdown`]: struct.TcpStream.html#method.shutdown
-/// [`TcpStream`]: struct.TcpStream.html
+/// Possible values which can be passed to the [`TcpStream::shutdown`] method.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Shutdown {
/// The reading portion of the [`TcpStream`] should be shut down.
///
- /// All currently blocked and future [reads] will return [`Ok(0)`].
+ /// All currently blocked and future [reads] will return [`Ok`]`(0)`.
///
- /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
- /// [reads]: ../../std/io/trait.Read.html
- /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
+ /// [reads]: crate::io::Read
#[stable(feature = "rust1", since = "1.0.0")]
Read,
/// The writing portion of the [`TcpStream`] should be shut down.
///
/// All currently blocked and future [writes] will return an error.
///
- /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
- /// [writes]: ../../std/io/trait.Write.html
+ /// [writes]: crate::io::Write
#[stable(feature = "rust1", since = "1.0.0")]
Write,
/// Both the reading and the writing portions of the [`TcpStream`] should be shut down.
///
/// See [`Shutdown::Read`] and [`Shutdown::Write`] for more information.
- ///
- /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
- /// [`Shutdown::Read`]: #variant.Read
- /// [`Shutdown::Write`]: #variant.Write
#[stable(feature = "rust1", since = "1.0.0")]
Both,
}
/// // No problem, the `panic!` message has disappeared.
/// let _foo: SocketAddr = "127.0.0.1:8080".parse().expect("unreachable panic");
/// ```
-///
-/// [`FromStr`]: ../../std/str/trait.FromStr.html
-/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
-/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
-/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
-/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
-/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AddrParseError(());
///
/// The Transmission Control Protocol is specified in [IETF RFC 793].
///
-/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
-/// [`connect`]: #method.connect
+/// [`accept`]: TcpListener::accept
+/// [`connect`]: TcpStream::connect
/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [reading]: ../../std/io/trait.Read.html
-/// [`shutdown`]: #method.shutdown
-/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
-/// [writing]: ../../std/io/trait.Write.html
+/// [reading]: Read
+/// [`shutdown`]: TcpStream::shutdown
+/// [writing]: Write
///
/// # Examples
///
///
/// The Transmission Control Protocol is specified in [IETF RFC 793].
///
-/// [`accept`]: #method.accept
-/// [`bind`]: #method.bind
+/// [`accept`]: TcpListener::accept
+/// [`bind`]: TcpListener::bind
/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [`Incoming`]: ../../std/net/struct.Incoming.html
-/// [`TcpListener::incoming`]: #method.incoming
///
/// # Examples
///
/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
///
-/// This `struct` is created by the [`incoming`] method on [`TcpListener`].
+/// This `struct` is created by the [`TcpListener::incoming`] method.
/// See its documentation for more.
///
-/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
-/// [`incoming`]: ../../std/net/struct.TcpListener.html#method.incoming
-/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+/// [`accept`]: TcpListener::accept
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Incoming<'a> {
/// the addresses result in a successful connection, the error returned from
/// the last connection attempt (the last address) is returned.
///
- /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
- ///
/// # Examples
///
/// Open a TCP connection to `127.0.0.1:8080`:
/// single system call. It instead calls `connect` in nonblocking mode and
/// then uses an OS-specific mechanism to await the completion of the
/// connection request.
- ///
- /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
#[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")]
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
/// portions to return immediately with an appropriate value (see the
/// documentation of [`Shutdown`]).
///
- /// [`Shutdown`]: ../../std/net/enum.Shutdown.html
- ///
/// # Platform-specific behavior
///
/// Calling this function multiple times may result in different behavior,
/// a result of setting this option. For example Unix typically returns an
/// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
- /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
- /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
- /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
- /// [`Duration`]: ../../std/time/struct.Duration.html
+ /// [`read`]: Read::read
+ /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+ /// [`TimedOut`]: io::ErrorKind::TimedOut
///
/// # Examples
///
/// as a result of setting this option. For example Unix typically returns
/// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
- /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
- /// [`Duration`]: ../../std/time/struct.Duration.html
- /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
- /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+ /// [`write`]: Write::write
+ /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+ /// [`TimedOut`]: io::ErrorKind::TimedOut
///
/// # Examples
///
///
/// Some platforms do not provide access to the current timeout.
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
+ /// [`read`]: Read::read
///
/// # Examples
///
///
/// Some platforms do not provide access to the current timeout.
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
+ /// [`write`]: Write::write
///
/// # Examples
///
/// Gets the value of the `TCP_NODELAY` option on this socket.
///
- /// For more information about this option, see [`set_nodelay`][link].
- ///
- /// [link]: #method.set_nodelay
+ /// For more information about this option, see [`TcpStream::set_nodelay`].
///
/// # Examples
///
/// Gets the value of the `IP_TTL` option for this socket.
///
- /// For more information about this option, see [`set_ttl`][link].
- ///
- /// [link]: #method.set_ttl
+ /// For more information about this option, see [`TcpStream::set_ttl`].
///
/// # Examples
///
/// };
/// println!("bytes: {:?}", buf);
/// ```
- ///
- /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
///
/// Binding with a port number of 0 will request that the OS assigns a port
/// to this listener. The port allocated can be queried via the
- /// [`local_addr`] method.
+ /// [`TcpListener::local_addr`] method.
///
/// The address type can be any implementor of [`ToSocketAddrs`] trait. See
/// its documentation for concrete examples.
/// none of the addresses succeed in creating a listener, the error returned
/// from the last attempt (the last address) is returned.
///
- /// [`local_addr`]: #method.local_addr
- /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
- ///
/// # Examples
///
/// Creates a TCP listener bound to `127.0.0.1:80`:
/// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other.
///
- /// [`TcpListener`]: ../../std/net/struct.TcpListener.html
- ///
/// # Examples
///
/// ```no_run
/// is established. When established, the corresponding [`TcpStream`] and the
/// remote peer's address will be returned.
///
- /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
- ///
/// # Examples
///
/// ```no_run
///
/// The returned iterator will never return [`None`] and will also not yield
/// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
- /// calling [`accept`] in a loop.
- ///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
- /// [`accept`]: #method.accept
+ /// calling [`TcpListener::accept`] in a loop.
///
/// # Examples
///
/// Gets the value of the `IP_TTL` option for this socket.
///
- /// For more information about this option, see [`set_ttl`][link].
- ///
- /// [link]: #method.set_ttl
+ /// For more information about this option, see [`TcpListener::set_ttl`].
///
/// # Examples
///
/// }
/// }
/// ```
- ///
- /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
/// an unordered, unreliable protocol; refer to [`TcpListener`] and [`TcpStream`] for TCP
/// primitives.
///
-/// [`bind`]: #method.bind
-/// [`connect`]: #method.connect
+/// [`bind`]: UdpSocket::bind
+/// [`connect`]: UdpSocket::connect
/// [IETF RFC 768]: https://tools.ietf.org/html/rfc768
-/// [`recv`]: #method.recv
-/// [received from]: #method.recv_from
-/// [`send`]: #method.send
-/// [sent to]: #method.send_to
-/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
-/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+/// [`recv`]: UdpSocket::recv
+/// [received from]: UdpSocket::recv_from
+/// [`send`]: UdpSocket::send
+/// [sent to]: UdpSocket::send_to
+/// [`TcpListener`]: crate::net::TcpListener
+/// [`TcpStream`]: crate::net::TcpStream
///
/// # Examples
///
/// of the addresses succeed in creating a socket, the error returned from
/// the last attempt (the last address) is returned.
///
- /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
- ///
/// # Examples
///
/// Creates a UDP socket bound to `127.0.0.1:3400`:
///
/// See issue #34202 for more details.
///
- /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
- ///
/// # Examples
///
/// ```no_run
///
/// If the socket isn't connected, it will return a [`NotConnected`] error.
///
- /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected
+ /// [`NotConnected`]: io::ErrorKind::NotConnected
///
/// ```no_run
/// use std::net::UdpSocket;
/// a result of setting this option. For example Unix typically returns an
/// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
- /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
- /// [`Duration`]: ../../std/time/struct.Duration.html
- /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
- /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+ /// [`read`]: io::Read::read
+ /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+ /// [`TimedOut`]: io::ErrorKind::TimedOut
///
/// # Examples
///
/// as a result of setting this option. For example Unix typically returns
/// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
- /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
- /// [`Duration`]: ../../std/time/struct.Duration.html
- /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
- /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
+ /// [`write`]: io::Write::write
+ /// [`WouldBlock`]: io::ErrorKind::WouldBlock
+ /// [`TimedOut`]: io::ErrorKind::TimedOut
///
/// # Examples
///
///
/// If the timeout is [`None`], then [`read`] calls will block indefinitely.
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
+ /// [`read`]: io::Read::read
///
/// # Examples
///
///
/// If the timeout is [`None`], then [`write`] calls will block indefinitely.
///
- /// [`None`]: ../../std/option/enum.Option.html#variant.None
- /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
+ /// [`write`]: io::Write::write
///
/// # Examples
///
/// Gets the value of the `SO_BROADCAST` option for this socket.
///
- /// For more information about this option, see
- /// [`set_broadcast`][link].
- ///
- /// [link]: #method.set_broadcast
+ /// For more information about this option, see [`UdpSocket::set_broadcast`].
///
/// # Examples
///
/// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
///
- /// For more information about this option, see
- /// [`set_multicast_loop_v4`][link].
- ///
- /// [link]: #method.set_multicast_loop_v4
+ /// For more information about this option, see [`UdpSocket::set_multicast_loop_v4`].
///
/// # Examples
///
/// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
///
- /// For more information about this option, see
- /// [`set_multicast_ttl_v4`][link].
- ///
- /// [link]: #method.set_multicast_ttl_v4
+ /// For more information about this option, see [`UdpSocket::set_multicast_ttl_v4`].
///
/// # Examples
///
/// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
///
- /// For more information about this option, see
- /// [`set_multicast_loop_v6`][link].
- ///
- /// [link]: #method.set_multicast_loop_v6
+ /// For more information about this option, see [`UdpSocket::set_multicast_loop_v6`].
///
/// # Examples
///
/// Gets the value of the `IP_TTL` option for this socket.
///
- /// For more information about this option, see [`set_ttl`][link].
- ///
- /// [link]: #method.set_ttl
+ /// For more information about this option, see [`UdpSocket::set_ttl`].
///
/// # Examples
///
/// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
///
- /// For more information about this option, see
- /// [`join_multicast_v4`][link].
- ///
- /// [link]: #method.join_multicast_v4
+ /// For more information about this option, see [`UdpSocket::join_multicast_v4`].
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
self.0.leave_multicast_v4(multiaddr, interface)
/// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
///
- /// For more information about this option, see
- /// [`join_multicast_v6`][link].
- ///
- /// [link]: #method.join_multicast_v6
+ /// For more information about this option, see [`UdpSocket::join_multicast_v6`].
#[stable(feature = "net2_mutators", since = "1.9.0")]
pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
self.0.leave_multicast_v6(multiaddr, interface)
/// Sends data on the socket to the remote address to which it is connected.
///
- /// The [`connect`] method will connect this socket to a remote address. This
+ /// [`UdpSocket::connect`] will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
///
- /// [`connect`]: #method.connect
- ///
/// # Examples
///
/// ```no_run
/// hold the message bytes. If a message is too long to fit in the supplied buffer,
/// excess bytes may be discarded.
///
- /// The [`connect`] method will connect this socket to a remote address. This
+ /// [`UdpSocket::connect`] will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
///
- /// [`connect`]: #method.connect
- ///
/// # Examples
///
/// ```no_run
/// Do not use this function to implement busy waiting, instead use `libc::poll` to
/// synchronize IO events on one or more sockets.
///
- /// The [`connect`] method will connect this socket to a remote address. This
+ /// [`UdpSocket::connect`] will connect this socket to a remote address. This
/// method will fail if the socket is not connected.
///
- /// [`connect`]: #method.connect
- ///
/// # Errors
///
/// This method will fail if the socket is not connected. The `connect` method
/// `FIONBIO`. On Windows calling this method corresponds to calling
/// `ioctlsocket` `FIONBIO`.
///
- /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
- ///
/// # Examples
///
/// Creates a UDP socket bound to `127.0.0.1:7878` and read bytes in
impl MetadataExt for Metadata {
#[allow(deprecated)]
fn as_raw_stat(&self) -> &raw::stat {
- unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) }
+ // The methods below use libc::stat, so they work fine when libc is built with FreeBSD 12 ABI.
+ // This method would just return nonsense.
+ #[cfg(freebsd12)]
+ panic!("as_raw_stat not supported with FreeBSD 12 ABI");
+ #[cfg(not(freebsd12))]
+ unsafe {
+ &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat)
+ }
}
fn st_dev(&self) -> u64 {
self.as_inner().as_inner().st_dev as u64
fn st_flags(&self) -> u32 {
self.as_inner().as_inner().st_flags as u32
}
+ #[cfg(freebsd12)]
+ fn st_lspare(&self) -> u32 {
+ panic!("st_lspare not supported with FreeBSD 12 ABI");
+ }
+ #[cfg(not(freebsd12))]
fn st_lspare(&self) -> u32 {
self.as_inner().as_inner().st_lspare as u32
}
C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
[C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types
-[Rust's `char` type]: ../../primitive.char.html
-[`CStr`]: ../../ffi/struct.CStr.html
-[`i8`]: ../../primitive.i8.html
-[`u8`]: ../../primitive.u8.html
+[Rust's `char` type]: char
+[`CStr`]: crate::ffi::CStr
This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard.
[IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754
-[`float`]: type.c_float.html
-[`f64`]: ../../primitive.f64.html
+[`float`]: c_float
This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all.
[IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754
-[`f32`]: ../../primitive.f32.html
This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example.
-[`short`]: type.c_short.html
-[`i32`]: ../../primitive.i32.html
-[`i16`]: ../../primitive.i16.html
+[`short`]: c_short
This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`.
-[`int`]: type.c_int.html
-[`i32`]: ../../primitive.i32.html
-[`i64`]: ../../primitive.i64.html
+[`int`]: c_int
This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type.
-[`long`]: type.c_int.html
-[`i64`]: ../../primitive.i64.html
-[`i128`]: ../../primitive.i128.html
+[`long`]: c_int
This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`].
-[`char`]: type.c_char.html
-[`i8`]: ../../primitive.i8.html
+[`char`]: c_char
This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example.
-[`char`]: type.c_char.html
-[`i16`]: ../../primitive.i16.html
+[`char`]: c_char
This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`].
-[`char`]: type.c_char.html
-[`u8`]: ../../primitive.u8.html
+[`char`]: c_char
This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example.
-[`int`]: type.c_int.html
-[`u32`]: ../../primitive.u32.html
-[`u16`]: ../../primitive.u16.html
+[`int`]: c_int
This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`.
-[`long`]: type.c_long.html
-[`u32`]: ../../primitive.u32.html
-[`u64`]: ../../primitive.u64.html
+[`long`]: c_long
This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type.
-[`long long`]: type.c_longlong.html
-[`u64`]: ../../primitive.u64.html
-[`u128`]: ../../primitive.u128.html
+[`long long`]: c_longlong
This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`].
-[`short`]: type.c_short.html
-[`u16`]: ../../primitive.u16.html
+[`short`]: c_short
/// ```
/// use std::path::Path;
///
- /// let path = Path::new("/etc/passwd");
+ /// let path = Path::new("/etc/resolv.conf");
+ ///
+ /// assert!(path.ends_with("resolv.conf"));
+ /// assert!(path.ends_with("etc/resolv.conf"));
+ /// assert!(path.ends_with("/etc/resolv.conf"));
///
- /// assert!(path.ends_with("passwd"));
+ /// assert!(!path.ends_with("/resolv.conf"));
+ /// assert!(!path.ends_with("conf")); // use .extension() instead
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
/// pointers, make your type `Option<fn()>` with your required signature.
///
+/// ### Safety
+///
/// Plain function pointers are obtained by casting either plain functions, or closures that don't
/// capture an environment:
///
/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
/// ```
///
-/// On top of that, function pointers can vary based on what ABI they use. This is achieved by
-/// adding the `extern` keyword to the type name, followed by the ABI in question. For example,
-/// `fn()` is different from `extern "C" fn()`, which itself is different from `extern "stdcall"
-/// fn()`, and so on for the various ABIs that Rust supports. Non-`extern` functions have an ABI
-/// of `"Rust"`, and `extern` functions without an explicit ABI have an ABI of `"C"`. For more
-/// information, see [the nomicon's section on foreign calling conventions][nomicon-abi].
+/// ### ABI
+///
+/// On top of that, function pointers can vary based on what ABI they use. This
+/// is achieved by adding the `extern` keyword before the type, followed by the
+/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
+/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
+/// type `extern "C" fn()`.
+///
+/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
+/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
+/// ABI.
+///
+/// For more information and a list of supported ABIs, see [the nomicon's
+/// section on foreign calling conventions][nomicon-abi].
///
-/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
+/// ### Variadic functions
///
/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
-/// to be called with a variable number of arguments. Normal rust functions, even those with an
+/// to be called with a variable number of arguments. Normal Rust functions, even those with an
/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
/// variadic functions][nomicon-variadic].
///
/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
///
-/// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
+/// ### Creating function pointers
+///
+/// When `bar` is the name of a function, then the expression `bar` is *not* a
+/// function pointer. Rather, it denotes a value of an unnameable type that
+/// uniquely identifies the function `bar`. The value is zero-sized because the
+/// type already identifies the function. This has the advantage that "calling"
+/// the value (it implements the `Fn*` traits) does not require dynamic
+/// dispatch.
+///
+/// This zero-sized type *coerces* to a regular function pointer. For example:
+///
+/// ```rust
+/// use std::mem;
+///
+/// fn bar(x: i32) {}
+///
+/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
+/// assert_eq!(mem::size_of_val(¬_bar_ptr), 0);
+///
+/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
+/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
+///
+/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
+/// ```
+///
+/// The last line shows that `&bar` is not a function pointer either. Rather, it
+/// is a reference to the function-specific ZST. `&bar` is basically never what you
+/// want when `bar` is a function.
+///
+/// ### Traits
///
/// Function pointers implement the following traits:
///
//! assert_eq!(b"test", output.stdout.as_slice());
//! ```
//!
-//! [`abort`]: fn.abort.html
-//! [`exit`]: fn.exit.html
+//! [`spawn`]: Command::spawn
+//! [`output`]: Command::output
//!
-//! [`Command`]: struct.Command.html
-//! [`spawn`]: struct.Command.html#method.spawn
-//! [`output`]: struct.Command.html#method.output
+//! [`stdout`]: Command::stdout
+//! [`stdin`]: Command::stdin
+//! [`stderr`]: Command::stderr
//!
-//! [`Child`]: struct.Child.html
-//! [`ChildStdin`]: struct.ChildStdin.html
-//! [`ChildStdout`]: struct.ChildStdout.html
-//! [`ChildStderr`]: struct.ChildStderr.html
-//! [`Stdio`]: struct.Stdio.html
-//!
-//! [`stdout`]: struct.Command.html#method.stdout
-//! [`stdin`]: struct.Command.html#method.stdin
-//! [`stderr`]: struct.Command.html#method.stderr
-//!
-//! [`Write`]: ../io/trait.Write.html
-//! [`Read`]: ../io/trait.Read.html
+//! [`Write`]: io::Write
+//! [`Read`]: io::Read
#![stable(feature = "process", since = "1.0.0")]
/// run, even after the `Child` handle to the child process has gone out of
/// scope.
///
-/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make
+/// Calling [`wait`] (or other functions that wrap around it) will make
/// the parent process wait until the child has actually exited before
/// continuing.
///
/// assert!(ecode.success());
/// ```
///
-/// [`Command`]: struct.Command.html
-/// [`Drop`]: ../../core/ops/trait.Drop.html
-/// [`wait`]: #method.wait
+/// [`wait`]: Child::wait
#[stable(feature = "process", since = "1.0.0")]
pub struct Child {
handle: imp::Process,
/// The handle for writing to the child's standard input (stdin), if it has
- /// been captured.
+ /// been captured. To avoid partially moving
+ /// the `child` and thus blocking yourself from calling
+ /// functions on `child` while using `stdin`,
+ /// you might find it helpful:
+ ///
+ /// ```compile_fail,E0425
+ /// let stdin = child.stdin.take().unwrap();
+ /// ```
#[stable(feature = "process", since = "1.0.0")]
pub stdin: Option<ChildStdin>,
/// The handle for reading from the child's standard output (stdout), if it
- /// has been captured.
+ /// has been captured. You might find it helpful to do
+ ///
+ /// ```compile_fail,E0425
+ /// let stdout = child.stdout.take().unwrap();
+ /// ```
+ ///
+ /// to avoid partially moving the `child` and thus blocking yourself from calling
+ /// functions on `child` while using `stdout`.
#[stable(feature = "process", since = "1.0.0")]
pub stdout: Option<ChildStdout>,
/// The handle for reading from the child's standard error (stderr), if it
- /// has been captured.
+ /// has been captured. You might find it helpful to do
+ ///
+ /// ```compile_fail,E0425
+ /// let stderr = child.stderr.take().unwrap();
+ /// ```
+ ///
+ /// to avoid partially moving the `child` and thus blocking yourself from calling
+ /// functions on `child` while using `stderr`.
#[stable(feature = "process", since = "1.0.0")]
pub stderr: Option<ChildStderr>,
}
/// file handle will be closed. If the child process was blocked on input prior
/// to being dropped, it will become unblocked after dropping.
///
-/// [`Child`]: struct.Child.html
-/// [`stdin`]: struct.Child.html#structfield.stdin
-/// [dropped]: ../ops/trait.Drop.html
+/// [`stdin`]: Child::stdin
+/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdin {
inner: AnonPipe,
/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
/// underlying file handle will be closed.
///
-/// [`Child`]: struct.Child.html
-/// [`stdout`]: struct.Child.html#structfield.stdout
-/// [dropped]: ../ops/trait.Drop.html
+/// [`stdout`]: Child::stdout
+/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdout {
inner: AnonPipe,
/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
/// underlying file handle will be closed.
///
-/// [`Child`]: struct.Child.html
-/// [`stderr`]: struct.Child.html#structfield.stderr
-/// [dropped]: ../ops/trait.Drop.html
+/// [`stderr`]: Child::stderr
+/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStderr {
inner: AnonPipe,
///
/// To pass multiple arguments see [`args`].
///
- /// [`args`]: #method.args
+ /// [`args`]: Command::args
///
/// # Examples
///
///
/// To pass a single argument see [`arg`].
///
- /// [`arg`]: #method.arg
+ /// [`arg`]: Command::arg
///
/// # Examples
///
/// .expect("ls command failed to start");
/// ```
///
- /// [`canonicalize`]: ../fs/fn.canonicalize.html
+ /// [`canonicalize`]: crate::fs::canonicalize
#[stable(feature = "process", since = "1.0.0")]
pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
self.inner.cwd(dir.as_ref().as_ref());
/// Defaults to [`inherit`] when used with `spawn` or `status`, and
/// defaults to [`piped`] when used with `output`.
///
- /// [`inherit`]: struct.Stdio.html#method.inherit
- /// [`piped`]: struct.Stdio.html#method.piped
+ /// [`inherit`]: Stdio::inherit
+ /// [`piped`]: Stdio::piped
///
/// # Examples
///
/// Defaults to [`inherit`] when used with `spawn` or `status`, and
/// defaults to [`piped`] when used with `output`.
///
- /// [`inherit`]: struct.Stdio.html#method.inherit
- /// [`piped`]: struct.Stdio.html#method.piped
+ /// [`inherit`]: Stdio::inherit
+ /// [`piped`]: Stdio::piped
///
/// # Examples
///
/// Defaults to [`inherit`] when used with `spawn` or `status`, and
/// defaults to [`piped`] when used with `output`.
///
- /// [`inherit`]: struct.Stdio.html#method.inherit
- /// [`piped`]: struct.Stdio.html#method.piped
+ /// [`inherit`]: Stdio::inherit
+ /// [`piped`]: Stdio::piped
///
/// # Examples
///
/// [`Command`], or the [`wait_with_output`] method of a [`Child`]
/// process.
///
-/// [`Command`]: struct.Command.html
-/// [`Child`]: struct.Child.html
-/// [`output`]: struct.Command.html#method.output
-/// [`wait_with_output`]: struct.Child.html#method.wait_with_output
+/// [`output`]: Command::output
+/// [`wait_with_output`]: Child::wait_with_output
#[derive(PartialEq, Eq, Clone)]
#[stable(feature = "process", since = "1.0.0")]
pub struct Output {
/// Describes what to do with a standard I/O stream for a child process when
/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
///
-/// [`stdin`]: struct.Command.html#method.stdin
-/// [`stdout`]: struct.Command.html#method.stdout
-/// [`stderr`]: struct.Command.html#method.stderr
-/// [`Command`]: struct.Command.html
+/// [`stdin`]: Command::stdin
+/// [`stdout`]: Command::stdout
+/// [`stderr`]: Command::stderr
#[stable(feature = "process", since = "1.0.0")]
pub struct Stdio(imp::Stdio);
/// status is exposed through the [`status`] method, or the [`wait`] method
/// of a [`Child`] process.
///
-/// [`Command`]: struct.Command.html
-/// [`Child`]: struct.Child.html
-/// [`status`]: struct.Command.html#method.status
-/// [`wait`]: struct.Child.html#method.wait
+/// [`status`]: Command::status
+/// [`wait`]: Child::wait
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "process", since = "1.0.0")]
pub struct ExitStatus(imp::ExitStatus);
/// For the platform's canonical successful and unsuccessful codes, see
/// the [`SUCCESS`] and [`FAILURE`] associated items.
///
-/// [`SUCCESS`]: #associatedconstant.SUCCESS
-/// [`FAILURE`]: #associatedconstant.FAILURE
+/// [`SUCCESS`]: ExitCode::SUCCESS
+/// [`FAILURE`]: ExitCode::FAILURE
///
/// **Warning**: While various forms of this were discussed in [RFC #1937],
/// it was ultimately cut from that RFC, and thus this type is more subject
/// }
/// ```
///
- /// [`ErrorKind`]: ../io/enum.ErrorKind.html
- /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
- /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
+ /// [`ErrorKind`]: io::ErrorKind
+ /// [`InvalidInput`]: io::ErrorKind::InvalidInput
+ /// [`Other`]: io::ErrorKind::Other
#[stable(feature = "process", since = "1.0.0")]
pub fn kill(&mut self) -> io::Result<()> {
self.handle.kill()
/// }
/// ```
///
-/// [`panic!`]: ../../std/macro.panic.html
-/// [panic hook]: ../../std/panic/fn.set_hook.html
+/// [panic hook]: crate::panic::set_hook
#[stable(feature = "process_abort", since = "1.17.0")]
pub fn abort() -> ! {
crate::sys::abort_internal();
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
- Ok(if self.t.tv_nsec >= other.t.tv_nsec {
- Duration::new(
- (self.t.tv_sec - other.t.tv_sec) as u64,
- (self.t.tv_nsec - other.t.tv_nsec) as u32,
- )
+ // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
+ // to optimize it into a branchless form (see also #75545):
+ //
+ // 1. `self.t.tv_sec - other.t.tv_sec` shows up as a common expression
+ // in both branches, i.e. the `else` must have its `- 1`
+ // subtraction after the common one, not interleaved with it
+ // (it used to be `self.t.tv_sec - 1 - other.t.tv_sec`)
+ //
+ // 2. the `Duration::new` call (or any other additional complexity)
+ // is outside of the `if`-`else`, not duplicated in both branches
+ //
+ // Ideally this code could be rearranged such that it more
+ // directly expresses the lower-cost behavior we want from it.
+ let (secs, nsec) = if self.t.tv_nsec >= other.t.tv_nsec {
+ ((self.t.tv_sec - other.t.tv_sec) as u64, (self.t.tv_nsec - other.t.tv_nsec) as u32)
} else {
- Duration::new(
- (self.t.tv_sec - 1 - other.t.tv_sec) as u64,
+ (
+ (self.t.tv_sec - other.t.tv_sec - 1) as u64,
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32,
)
- })
+ };
+
+ Ok(Duration::new(secs, nsec))
} else {
match other.sub_timespec(self) {
Ok(d) => Err(d),
use crate::sys::platform::fs::MetadataExt as UnixMetadataExt;
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
-/// Unix-specific extensions to [`File`].
-///
-/// [`File`]: ../../../../std/fs/struct.File.html
+/// Unix-specific extensions to [`fs::File`].
#[stable(feature = "file_offset", since = "1.15.0")]
pub trait FileExt {
/// Reads a number of bytes starting from a given offset.
/// Note that similar to [`File::read`], it is not an error to return with a
/// short read.
///
- /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
+ /// [`File::read`]: fs::File::read
///
/// # Examples
///
///
/// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
///
- /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
- /// [`read_at`]: #tymethod.read_at
+ /// [`Read::read_exact`]: io::Read::read_exact
+ /// [`read_at`]: FileExt::read_at
///
/// # Errors
///
/// has read, but it will never read more than would be necessary to
/// completely fill the buffer.
///
- /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
- /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
+ /// [`ErrorKind::Interrupted`]: io::ErrorKind::Interrupted
+ /// [`ErrorKind::UnexpectedEof`]: io::ErrorKind::UnexpectedEof
///
/// # Examples
///
/// Note that similar to [`File::write`], it is not an error to return a
/// short write.
///
- /// [`File::write`]: ../../../../std/fs/struct.File.html#method.write
+ /// [`File::write`]: fs::File::write
///
/// # Examples
///
/// This function will return the first error of
/// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
///
- /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
- /// [`write_at`]: #tymethod.write_at
+ /// [`ErrorKind::Interrupted`]: io::ErrorKind::Interrupted
+ /// [`write_at`]: FileExt::write_at
///
/// # Examples
///
}
/// Unix-specific extensions to [`fs::Permissions`].
-///
-/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
#[stable(feature = "fs_ext", since = "1.1.0")]
pub trait PermissionsExt {
/// Returns the underlying raw `st_mode` bits that contain the standard
}
/// Unix-specific extensions to [`fs::OpenOptions`].
-///
-/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
#[stable(feature = "fs_ext", since = "1.1.0")]
pub trait OpenOptionsExt {
/// Sets the mode bits that a new file will be created with.
*/
/// Unix-specific extensions to [`fs::Metadata`].
-///
-/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Returns the ID of the device containing the file.
}
}
-/// Unix-specific extensions for [`FileType`].
+/// Unix-specific extensions for [`fs::FileType`].
///
/// Adds support for special Unix file types such as block/character devices,
/// pipes, and sockets.
-///
-/// [`FileType`]: ../../../../std/fs/struct.FileType.html
#[stable(feature = "file_type_ext", since = "1.5.0")]
pub trait FileTypeExt {
/// Returns whether this file type is a block device.
}
/// Unix-specific extension methods for [`fs::DirEntry`].
-///
-/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
pub trait DirEntryExt {
/// Returns the underlying `d_ino` field in the contained `dirent`
}
/// Unix-specific extensions to [`fs::DirBuilder`].
-///
-/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
#[stable(feature = "dir_builder", since = "1.6.0")]
pub trait DirBuilderExt {
/// Sets the mode to create new directories with. This option defaults to
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
/// Unix-specific extensions to the [`process::Command`] builder.
-///
-/// [`process::Command`]: ../../../../std/process/struct.Command.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait CommandExt {
/// Sets the child process's user ID. This translates to a
/// This method is stable and usable, but it should be unsafe. To fix
/// that, it got deprecated in favor of the unsafe [`pre_exec`].
///
- /// [`pre_exec`]: #tymethod.pre_exec
+ /// [`pre_exec`]: CommandExt::pre_exec
#[stable(feature = "process_exec", since = "1.15.0")]
#[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
fn before_exec<F>(&mut self, f: F) -> &mut process::Command
/// a new child. Like spawn, however, the default behavior for the stdio
/// descriptors will be to inherited from the current process.
///
- /// [`process::exit`]: ../../../process/fn.exit.html
///
/// # Notes
///
}
/// Unix-specific extensions to [`process::ExitStatus`].
-///
-/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ExitStatusExt {
/// Creates a new `ExitStatus` from the raw underlying `i32` return value of
cmd.arg(arg);
}
- // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick
- // it up so we can make rustdoc print this into the docs
- if let Some(version) = env::var_os("RUSTDOC_CRATE_VERSION") {
- cmd.arg("--crate-version").arg(version);
- }
-
// Needed to be able to run all rustdoc tests.
if let Some(ref x) = env::var_os("RUSTDOC_RESOURCE_SUFFIX") {
// This "unstable-options" can be removed when `--resource-suffix` is stabilized
.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler))
.env("CFG_RELEASE_CHANNEL", &self.config.channel)
.env("RUSTDOC_REAL", self.rustdoc(compiler))
- .env("RUSTDOC_CRATE_VERSION", self.rust_version())
.env("RUSTC_BOOTSTRAP", "1")
.arg("-Winvalid_codeblock_attributes");
if self.config.deny_warnings {
rustflags.arg("--cfg=bootstrap");
}
+ if self.config.rust_new_symbol_mangling {
+ rustflags.arg("-Zsymbol-mangling-version=v0");
+ }
+
// FIXME: It might be better to use the same value for both `RUSTFLAGS` and `RUSTDOCFLAGS`,
// but this breaks CI. At the very least, stage0 `rustdoc` needs `--cfg bootstrap`. See
// #71458.
}
// For `cargo doc` invocations, make rustdoc print the Rust version into the docs
- cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version());
+ // This replaces spaces with newlines because RUSTDOCFLAGS does not
+ // support arguments with regular spaces. Hopefully someday Cargo will
+ // have space support.
+ let rust_version = self.rust_version().replace(' ', "\n");
+ rustdocflags.arg("--crate-version").arg(&rust_version);
// Environment variables *required* throughout the build
//
fn env(&mut self, env: &str) {
if let Ok(s) = env::var(env) {
- for part in s.split_whitespace() {
+ for part in s.split(' ') {
self.arg(part);
}
}
}
fn arg(&mut self, arg: &str) -> &mut Self {
- assert_eq!(arg.split_whitespace().count(), 1);
+ assert_eq!(arg.split(' ').count(), 1);
if !self.0.is_empty() {
self.0.push_str(" ");
}
pub rust_verify_llvm_ir: bool,
pub rust_thin_lto_import_instr_limit: Option<u32>,
pub rust_remap_debuginfo: bool,
+ pub rust_new_symbol_mangling: bool,
pub build: TargetSelection,
pub hosts: Vec<TargetSelection>,
test_compare_mode: Option<bool>,
llvm_libunwind: Option<bool>,
control_flow_guard: Option<bool>,
+ new_symbol_mangling: Option<bool>,
}
/// TOML representation of how each build target is configured.
debuginfo_level_tests = rust.debuginfo_level_tests;
optimize = rust.optimize;
ignore_git = rust.ignore_git;
+ set(&mut config.rust_new_symbol_mangling, rust.new_symbol_mangling);
set(&mut config.rust_optimize_tests, rust.optimize_tests);
set(&mut config.codegen_tests, rust.codegen_tests);
set(&mut config.rust_rpath, rust.rpath);
.define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
.define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
- if !target.contains("netbsd") {
+ if !target.contains("netbsd") && target != "aarch64-apple-darwin" {
cfg.define("LLVM_ENABLE_ZLIB", "ON");
} else {
// FIXME: Enable zlib on NetBSD too
"LLVM_CONFIG_PATH",
host_bin.join("llvm-config").with_extension(EXE_EXTENSION),
);
-
- if target.contains("netbsd") {
- cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
- } else if target.contains("freebsd") {
- cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
- } else if target.contains("windows") {
- cfg.define("CMAKE_SYSTEM_NAME", "Windows");
- }
}
if let Some(ref suffix) = builder.config.llvm_version_suffix {
}
cfg.target(&target.triple).host(&builder.config.build.triple);
+ if target != builder.config.build {
+ if target.contains("netbsd") {
+ cfg.define("CMAKE_SYSTEM_NAME", "NetBSD");
+ } else if target.contains("freebsd") {
+ cfg.define("CMAKE_SYSTEM_NAME", "FreeBSD");
+ } else if target.contains("windows") {
+ cfg.define("CMAKE_SYSTEM_NAME", "Windows");
+ }
+ // When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in
+ // that case like CMake we cannot easily determine system version either.
+ //
+ // Since, the LLVM itself makes rather limited use of version checks in
+ // CMakeFiles (and then only in tests), and so far no issues have been
+ // reported, the system version is currently left unset.
+ }
+
let sanitize_cc = |cc: &Path| {
if target.contains("msvc") {
OsString::from(cc.to_str().unwrap().replace("\\", "/"))
}
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
+ "x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]),
"x86_64-unknown-linux-gnu" => {
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
}
.env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
.env("CFG_RELEASE_CHANNEL", &builder.config.channel)
.env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
- .env("RUSTDOC_CRATE_VERSION", builder.rust_version())
.env("RUSTC_BOOTSTRAP", "1");
if let Some(linker) = builder.linker(self.compiler.host, true) {
cmd.env("RUSTC_TARGET_LINKER", linker);
ENV HOSTS=x86_64-unknown-freebsd
-ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --enable-sanitizers --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
+RUN mkdir -p /config
+RUN echo "[rust]" > /config/nopt-std-config.toml
+RUN echo "optimize = false" >> /config/nopt-std-config.toml
+
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
-ENV SCRIPT python3 ../x.py --stage 2 test
+ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
+ && python3 ../x.py --stage 2 test
# FIXME(#59637) takes too long on CI right now
ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
+RUN mkdir -p /config
+RUN echo "[rust]" > /config/nopt-std-config.toml
+RUN echo "optimize = false" >> /config/nopt-std-config.toml
+
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
--disable-optimize-tests \
--set rust.test-compare-mode
-ENV SCRIPT python3 ../x.py --stage 2 test
+ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
+ && python3 ../x.py --stage 2 test
#[macro_export]
macro_rules! declare_arena {
- // This macro has to take the same input as
- // `impl_arena_allocatable_decoders` which requires a second version of
- // each type. We ignore that type until we can fix
- // `impl_arena_allocatable_decoders`.
- ([], [$($a:tt $name:ident: $ty:ty, $_gen_ty:ty;)*], $tcx:lifetime) => {
+ ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
#[derive(Default)]
pub struct Arena<$tcx> {
pub dropless: $crate::DroplessArena,
[dependencies]
rustc_serialize = { path = "../librustc_serialize" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_span = { path = "../librustc_span" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_index = { path = "../librustc_index" }
/// ```
///
/// `'outer` is a label.
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Copy, HashStable_Generic)]
pub struct Label {
pub ident: Ident,
}
/// A "Lifetime" is an annotation of the scope in which variable
/// can be used, e.g. `'a` in `&'a i32`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, Encodable, Decodable, Copy)]
pub struct Lifetime {
pub id: NodeId,
pub ident: Ident,
/// along with a bunch of supporting information.
///
/// E.g., `std::cmp::PartialEq`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Path {
pub span: Span,
/// The segments in the path: the things separated by `::`.
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
///
/// E.g., `std`, `String` or `Box<T>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct PathSegment {
/// The identifier portion of this path segment.
pub ident: Ident,
/// The arguments of a path segment.
///
/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericArgs {
/// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`.
AngleBracketed(AngleBracketedArgs),
}
/// Concrete argument in the sequence of generic args.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericArg {
/// `'a` in `Foo<'a>`
Lifetime(Lifetime),
}
/// A path like `Foo<'a, T>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
+#[derive(Clone, Encodable, Decodable, Debug, Default)]
pub struct AngleBracketedArgs {
/// The overall span.
pub span: Span,
/// Either an argument for a parameter e.g., `'a`, `Vec<u8>`, `0`,
/// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AngleBracketedArg {
/// Argument for a generic parameter.
Arg(GenericArg),
}
/// A path like `Foo(A, B) -> C`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ParenthesizedArgs {
/// Overall span
pub span: Span,
/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
///
/// Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
pub enum TraitBoundModifier {
/// No modifiers
None,
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericBound {
Trait(PolyTraitRef, TraitBoundModifier),
Outlives(Lifetime),
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericParamKind {
/// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
Lifetime,
},
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct GenericParam {
pub id: NodeId,
pub ident: Ident,
/// Represents lifetime, type and const parameters attached to a declaration of
/// a function, enum, trait, etc.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Generics {
pub params: Vec<GenericParam>,
pub where_clause: WhereClause,
}
/// A where-clause in a definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereClause {
/// `true` if we ate a `where` token: this can happen
/// if we parsed no predicates (e.g. `struct Foo where {}`).
}
/// A single predicate in a where-clause.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum WherePredicate {
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
BoundPredicate(WhereBoundPredicate),
/// A type bound.
///
/// E.g., `for<'c> Foo: Send + Clone + 'c`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereBoundPredicate {
pub span: Span,
/// Any generics from a `for` binding.
/// A lifetime predicate.
///
/// E.g., `'a: 'b + 'c`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereRegionPredicate {
pub span: Span,
pub lifetime: Lifetime,
/// An equality predicate (unsupported).
///
/// E.g., `T = int`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereEqPredicate {
pub id: NodeId,
pub span: Span,
pub rhs_ty: P<Ty>,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Crate {
pub module: Mod,
pub attrs: Vec<Attribute>,
/// Possible values inside of compile-time attribute lists.
///
/// E.g., the '..' in `#[name(..)]`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum NestedMetaItem {
/// A full MetaItem, for recursive meta items.
MetaItem(MetaItem),
/// A spanned compile-time attribute item.
///
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MetaItem {
pub path: Path,
pub kind: MetaItemKind,
/// A compile-time attribute item.
///
/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MetaItemKind {
/// Word meta item.
///
/// A block (`{ .. }`).
///
/// E.g., `{ .. }` as in `fn foo() { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Block {
/// The statements in the block.
pub stmts: Vec<Stmt>,
/// A match pattern.
///
/// Patterns appear in match statements and some other contexts, such as `let` and `if let`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Pat {
pub id: NodeId,
pub kind: PatKind,
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
/// are treated the same as` x: x, y: ref y, z: ref mut z`,
/// except is_shorthand is true
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FieldPat {
/// The identifier for the field
pub ident: Ident,
pub is_placeholder: bool,
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BindingMode {
ByRef(Mutability),
ByValue(Mutability),
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum RangeEnd {
Included(RangeSyntax),
Excluded,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum RangeSyntax {
/// `...`
DotDotDot,
DotDotEq,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum PatKind {
/// Represents a wildcard pattern (`_`).
Wild,
MacCall(MacCall),
}
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum Mutability {
Mut,
Not,
/// The kind of borrow in an `AddrOf` expression,
/// e.g., `&place` or `&raw const place`.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum BorrowKind {
/// A normal borrow, `&$expr` or `&mut $expr`.
/// The resulting type is either `&'a T` or `&'a mut T`
Raw,
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BinOpKind {
/// The `+` operator (addition)
Add,
/// Unary operator.
///
/// Note that `&data` is not an operator, it's an `AddrOf` expression.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy)]
pub enum UnOp {
/// The `*` operator for dereferencing
Deref,
}
/// A statement
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Stmt {
pub id: NodeId,
pub kind: StmtKind,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum StmtKind {
/// A local (let) binding.
Local(P<Local>),
MacCall(P<(MacCall, MacStmtStyle, AttrVec)>),
}
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
pub enum MacStmtStyle {
/// The macro statement had a trailing semicolon (e.g., `foo! { ... };`
/// `foo!(...);`, `foo![...];`).
}
/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Local {
pub id: NodeId,
pub pat: P<Pat>,
/// _ => { println!("no match!") },
/// }
/// ```
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Arm {
pub attrs: Vec<Attribute>,
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
}
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Field {
pub attrs: AttrVec,
pub id: NodeId,
pub is_placeholder: bool,
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BlockCheckMode {
Default,
Unsafe(UnsafeSource),
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
/// These are usually found nested inside types (e.g., array lengths)
/// or expressions (e.g., repeat counts), and also used to define
/// explicit discriminant values for enum variants.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct AnonConst {
pub id: NodeId,
pub value: P<Expr>,
}
/// An expression.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Expr {
pub id: NodeId,
pub kind: ExprKind,
}
/// Limit types of a range (inclusive or exclusive)
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
pub enum RangeLimits {
/// Inclusive at the beginning, exclusive at the end
HalfOpen,
Closed,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ExprKind {
/// A `box x` expression.
Box(P<Expr>),
/// ^~~~~ ^
/// ty position = 0
/// ```
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct QSelf {
pub ty: P<Ty>,
}
/// A capture clause used in closures and `async` blocks.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CaptureBy {
/// `move |x| y + x`.
Value,
/// The movability of a generator / closure literal:
/// whether a generator contains self-references, causing it to be `!Unpin`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
#[derive(HashStable_Generic)]
pub enum Movability {
/// May contain self-references, `!Unpin`.
/// Represents a macro invocation. The `path` indicates which macro
/// is being invoked, and the `args` are arguments passed to it.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MacCall {
pub path: Path,
pub args: P<MacArgs>,
}
/// Arguments passed to an attribute or a function-like macro.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacArgs {
/// No arguments - `#[attr]`.
Empty,
}
}
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacDelimiter {
Parenthesis,
Bracket,
}
/// Represents a macro definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MacroDef {
pub body: P<MacArgs>,
/// `true` if macro was defined with `macro_rules`.
pub macro_rules: bool,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy, Hash, Eq, PartialEq)]
#[derive(HashStable_Generic)]
pub enum StrStyle {
/// A regular string, like `"foo"`.
}
/// An AST literal.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Lit {
/// The original literal token as written in source code.
pub token: token::Lit,
}
/// Same as `Lit`, but restricted to string literals.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct StrLit {
/// The original literal token as written in source code.
pub style: StrStyle,
}
/// Type of the integer literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
#[derive(HashStable_Generic)]
pub enum LitIntType {
/// e.g. `42_i32`.
}
/// Type of the float literal based on provided suffix.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
#[derive(HashStable_Generic)]
pub enum LitFloatType {
/// A float literal with a suffix (`1f32` or `1E10f32`).
/// Literal kind.
///
/// E.g., `"foo"`, `42`, `12.34`, or `bool`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
pub enum LitKind {
/// A string literal (`"foo"`).
Str(Symbol, StrStyle),
// N.B., If you change this, you'll probably want to change the corresponding
// type structure in `middle/ty.rs` as well.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MutTy {
pub ty: P<Ty>,
pub mutbl: Mutability,
/// Represents a function's signature in a trait declaration,
/// trait implementation, or free function.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FnSig {
pub header: FnHeader,
pub decl: P<FnDecl>,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum FloatTy {
F32,
F64,
}
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum IntTy {
Isize,
I8,
}
}
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum UintTy {
Usize,
U8,
/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
/// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct AssocTyConstraint {
pub id: NodeId,
pub ident: Ident,
}
/// The kinds of an `AssocTyConstraint`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AssocTyConstraintKind {
/// E.g., `A = Bar` in `Foo<A = Bar>`.
Equality { ty: P<Ty> },
Bound { bounds: GenericBounds },
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Ty {
pub id: NodeId,
pub kind: TyKind,
pub span: Span,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct BareFnTy {
pub unsafety: Unsafe,
pub ext: Extern,
}
/// The various kinds of type recognized by the compiler.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum TyKind {
/// A variable-length slice (`[T]`).
Slice(P<Ty>),
}
/// Syntax used to declare a trait object.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
pub enum TraitObjectSyntax {
Dyn,
None,
/// Inline assembly operand explicit register or register class.
///
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub enum InlineAsmRegOrRegClass {
Reg(Symbol),
RegClass(Symbol),
}
bitflags::bitflags! {
- #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+ #[derive(Encodable, Decodable, HashStable_Generic)]
pub struct InlineAsmOptions: u8 {
const PURE = 1 << 0;
const NOMEM = 1 << 1;
}
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum InlineAsmTemplatePiece {
String(String),
Placeholder { operand_idx: usize, modifier: Option<char>, span: Span },
/// Inline assembly operand.
///
/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum InlineAsmOperand {
In {
reg: InlineAsmRegOrRegClass,
/// Inline assembly.
///
/// E.g., `asm!("NOP");`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct InlineAsm {
pub template: Vec<InlineAsmTemplatePiece>,
pub operands: Vec<(InlineAsmOperand, Span)>,
/// Inline assembly dialect.
///
/// E.g., `"intel"` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
pub enum LlvmAsmDialect {
Att,
Intel,
/// LLVM-style inline assembly.
///
/// E.g., `"={eax}"(result)` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct LlvmInlineAsmOutput {
pub constraint: Symbol,
pub expr: P<Expr>,
/// LLVM-style inline assembly.
///
/// E.g., `llvm_asm!("NOP");`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct LlvmInlineAsm {
pub asm: Symbol,
pub asm_str_style: StrStyle,
/// A parameter in a function header.
///
/// E.g., `bar: usize` as in `fn foo(bar: usize)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Param {
pub attrs: AttrVec,
pub ty: P<Ty>,
/// Alternative representation for `Arg`s describing `self` parameter of methods.
///
/// E.g., `&mut self` as in `fn foo(&mut self)`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum SelfKind {
/// `self`, `mut self`
Value(Mutability),
///
/// Please note that it's different from `FnHeader` structure
/// which contains metadata about function safety, asyncness, constness and ABI.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FnDecl {
pub inputs: Vec<Param>,
pub output: FnRetTy,
}
/// Is the trait definition an auto trait?
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum IsAuto {
Yes,
No,
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum Unsafe {
Yes(Span),
No,
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug)]
pub enum Async {
Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
No,
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum Const {
Yes(Span),
/// Item defaultness.
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum Defaultness {
Default(Span),
Final,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FnRetTy {
/// Returns type is not specified.
///
/// Module declaration.
///
/// E.g., `mod foo;` or `mod foo { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
+#[derive(Clone, Encodable, Decodable, Debug, Default)]
pub struct Mod {
/// A span from the first token past `{` to the last token until `}`.
/// For `mod foo;`, the inner span ranges from the first token
/// Foreign module declaration.
///
/// E.g., `extern { .. }` or `extern C { .. }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ForeignMod {
pub abi: Option<StrLit>,
pub items: Vec<P<ForeignItem>>,
/// Global inline assembly.
///
/// Also known as "module-level assembly" or "file-scoped assembly".
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy)]
pub struct GlobalAsm {
pub asm: Symbol,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct EnumDef {
pub variants: Vec<Variant>,
}
/// Enum variant.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Variant {
/// Attributes of the variant.
pub attrs: Vec<Attribute>,
}
/// Part of `use` item to the right of its prefix.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum UseTreeKind {
/// `use prefix` or `use prefix as rename`
///
/// A tree of paths sharing common prefixes.
/// Used in `use` items both at top-level and inside of braces in import groups.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct UseTree {
pub prefix: Path,
pub kind: UseTreeKind,
/// Distinguishes between `Attribute`s that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
pub enum AttrStyle {
Outer,
Inner,
}
}
-impl rustc_serialize::Encodable for AttrId {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_unit()
}
}
-impl rustc_serialize::Decodable for AttrId {
- fn decode<D: Decoder>(d: &mut D) -> Result<AttrId, D::Error> {
+impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
+ fn decode(d: &mut D) -> Result<AttrId, D::Error> {
d.read_nil().map(|_| crate::attr::mk_attr_id())
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AttrItem {
pub path: Path,
pub args: MacArgs,
pub type AttrVec = ThinVec<Attribute>;
/// Metadata associated with an item.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Attribute {
pub kind: AttrKind,
pub id: AttrId,
pub span: Span,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AttrKind {
/// A normal attribute.
Normal(AttrItem),
/// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl.
/// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the
/// same as the impl's `NodeId`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TraitRef {
pub path: Path,
pub ref_id: NodeId,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `<'a> Foo<&'a T>`.
pub bound_generic_params: Vec<GenericParam>,
}
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CrateSugar {
/// Source is `pub(crate)`.
PubCrate,
pub type Visibility = Spanned<VisibilityKind>;
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum VisibilityKind {
Public,
Crate(CrateSugar),
/// Field of a struct.
///
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct StructField {
pub attrs: Vec<Attribute>,
pub id: NodeId,
}
/// Fields and constructor ids of enum variants and structs.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum VariantData {
/// Struct variant.
///
}
/// An item definition.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Item<K = ItemKind> {
pub attrs: Vec<Attribute>,
pub id: NodeId,
}
/// `extern` qualifier on a function item or function type.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub enum Extern {
None,
Implicit,
///
/// All the information between the visibility and the name of the function is
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct FnHeader {
pub unsafety: Unsafe,
pub asyncness: Async,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ItemKind {
/// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
///
/// In an implementation, all items must be provided.
/// The `Option`s below denote the bodies, where `Some(_)`
/// means "provided" and conversely `None` means "required".
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AssocItemKind {
/// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
/// If `def` is parsed, then the constant is provided, and otherwise required.
}
/// An item in `extern` block.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ForeignItemKind {
/// A foreign static item (`static FOO: u8`).
Static(P<Ty>, Mutability, Option<P<Expr>>),
// Are ASTs encodable?
#[test]
fn check_asts_encodable() {
- fn assert_encodable<T: rustc_serialize::Encodable>() {}
+ fn assert_encodable<
+ T: for<'a> rustc_serialize::Encodable<rustc_serialize::json::Encoder<'a>>,
+ >() {
+ }
assert_encodable::<Crate>();
}
/// Hash value constructed out of all the `-C metadata` arguments passed to the
/// compiler. Together with the crate-name forms a unique global identifier for
/// the crate.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
pub struct CrateDisambiguator(Fingerprint);
impl CrateDisambiguator {
#![feature(unicode_internals)]
#![recursion_limit = "256"]
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
extern crate rustc_macros;
#[macro_export]
-use rustc_serialize::{Decoder, Encoder};
use rustc_span::ExpnId;
use std::fmt;
rustc_index::newtype_index! {
pub struct NodeId {
- ENCODABLE = custom
DEBUG_FORMAT = "NodeId({})"
}
}
fmt::Display::fmt(&self.as_u32(), f)
}
}
-
-impl rustc_serialize::UseSpecializedEncodable for NodeId {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u32(self.as_u32())
- }
-}
-
-impl rustc_serialize::UseSpecializedDecodable for NodeId {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<NodeId, D::Error> {
- d.read_u32().map(NodeId::from_u32)
- }
-}
}
}
-impl<T: 'static + Decodable> Decodable for P<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
+impl<D: Decoder, T: 'static + Decodable<D>> Decodable<D> for P<T> {
+ fn decode(d: &mut D) -> Result<P<T>, D::Error> {
Decodable::decode(d).map(P)
}
}
-impl<T: Encodable> Encodable for P<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
}
}
-impl<T: Encodable> Encodable for P<[T]> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&**self, s)
}
}
-impl<T: Decodable> Decodable for P<[T]> {
- fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for P<[T]> {
+ fn decode(d: &mut D) -> Result<P<[T]>, D::Error> {
Ok(P::from_vec(Decodable::decode(d)?))
}
}
use std::borrow::Cow;
use std::{fmt, mem};
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CommentKind {
Line,
Block,
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)]
#[derive(HashStable_Generic)]
pub enum BinOpToken {
Plus,
}
/// A delimiter token.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy)]
#[derive(HashStable_Generic)]
pub enum DelimToken {
/// A round parenthesis (i.e., `(` or `)`).
}
}
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum LitKind {
Bool, // AST only, must never appear in a `Token`
Byte,
}
/// A literal token.
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Lit {
pub kind: LitKind,
pub symbol: Symbol,
.contains(&name)
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TokenKind {
/* Expression-operator symbols. */
Eq,
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(TokenKind, 16);
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,
pub span: Span,
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Encodable, Decodable)]
/// For interpolation during macro expansion.
pub enum Nonterminal {
NtItem(P<ast::Item>),
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(Nonterminal, 40);
-#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
pub enum NonterminalKind {
Item,
Block,
///
/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
-#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum TokenTree {
/// A single token
Token(Token),
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
/// instead of a representation of the abstract syntax tree.
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
-#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
pub type TreeAndJoint = (TokenTree, IsJoint);
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(TokenStream, 8);
-#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
pub enum IsJoint {
Joint,
NonJoint,
}
}
-#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub struct DelimSpan {
pub open: Span,
pub close: Span,
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
-use log::debug;
use std::ascii;
+use tracing::debug;
pub enum LitError {
NotLiteral,
Greater | // `{ 42 } > 3`
GreaterEqual | // `{ 42 } >= 3`
AssignOp(_) | // `{ 42 } +=`
- LAnd | // `{ 42 } &&foo`
As | // `{ 42 } as usize`
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
}
}
+ pub fn ident(&self) -> Option<&Ident> {
+ match self {
+ FnKind::Fn(_, ident, ..) => Some(ident),
+ _ => None,
+ }
+ }
+
pub fn decl(&self) -> &'a FnDecl {
match self {
FnKind::Fn(_, _, sig, _, _) => &sig.decl,
use rustc_ast::ast::*;
use rustc_ast::node_id::NodeMap;
use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
}
}
+ fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) {
+ match fk {
+ FnKind::Fn(FnCtxt::Foreign, _, sig, _, _) => {
+ self.visit_fn_header(&sig.header);
+ visit::walk_fn_decl(self, &sig.decl);
+ // Don't visit the foreign function body even if it has one, since lowering the
+ // body would have no meaning and will have already been caught as a parse error.
+ }
+ _ => visit::walk_fn(self, fk, sp),
+ }
+ }
+
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
AssocCtxt::Trait => {
}
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Encodable, Decodable)]
pub enum InlineAttr {
None,
Hint,
Never,
}
-#[derive(Clone, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Encodable, Decodable)]
pub enum OptimizeAttr {
None,
Speed,
///
/// - `#[stable]`
/// - `#[unstable]`
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)]
pub struct Stability {
pub level: StabilityLevel,
}
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)]
pub struct ConstStability {
pub level: StabilityLevel,
}
/// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
+#[derive(Encodable, Decodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
#[derive(HashStable_Generic)]
pub enum StabilityLevel {
// Reason for the current stability level and the relevant rust-lang issue
}
}
-#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
+#[derive(Encodable, Decodable, Clone, HashStable_Generic)]
pub struct Deprecation {
pub since: Option<Symbol>,
/// The note to issue a reason.
depr
}
-#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
+#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)]
pub enum ReprAttr {
ReprInt(IntType),
ReprC,
ReprNoNiche,
}
-#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum IntType {
SignedInt(ast::IntTy),
UnsignedInt(ast::UintTy),
#![feature(or_patterns)]
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
extern crate rustc_macros;
mod builtin;
return Err(err);
} else {
// ...after that delegate to `expect` to also include the other expected tokens.
- return Err(p.expect(&token::Comma).err().unwrap());
+ let _ = p.expect(&token::Comma)?;
}
}
first = false;
// for `println!("{7:7$}", 1);`
refs.sort();
refs.dedup();
- let (arg_list, mut sp) = if refs.len() == 1 {
- let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
- (
- format!("argument {}", refs[0]),
- if spans.is_empty() {
- MultiSpan::from_span(self.fmtsp)
- } else {
- MultiSpan::from_spans(spans)
- },
- )
+ let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
+ let sp = if self.arg_spans.is_empty() || spans.is_empty() {
+ MultiSpan::from_span(self.fmtsp)
+ } else {
+ MultiSpan::from_spans(spans)
+ };
+ let arg_list = if refs.len() == 1 {
+ format!("argument {}", refs[0])
} else {
- let pos = MultiSpan::from_spans(spans.into_iter().map(|s| *s.unwrap()).collect());
let reg = refs.pop().unwrap();
- (format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg,), pos)
+ format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg)
};
- if self.arg_spans.is_empty() {
- sp = MultiSpan::from_span(self.fmtsp);
- }
e = self.ecx.struct_span_err(
sp,
let args_unused = errs_len;
let mut diag = {
- if errs_len == 1 {
- let (sp, msg) = errs.into_iter().next().unwrap();
- let mut diag = cx.ecx.struct_span_err(sp, msg);
- diag.span_label(sp, msg);
+ if let [(sp, msg)] = &errs[..] {
+ let mut diag = cx.ecx.struct_span_err(*sp, *msg);
+ diag.span_label(*sp, *msg);
diag
} else {
let mut diag = cx.ecx.struct_span_err(
debug!("get_static: sym={} instance={:?}", sym, instance);
let g = if let Some(def_id) = def_id.as_local() {
- let id = self.tcx.hir().as_local_hir_id(def_id);
+ let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let llty = self.layout_of(ty).llvm_type(self);
// FIXME: refactor this to work without accessing the HIR
let (g, attrs) = match self.tcx.hir().get(id) {
use log::debug;
use rustc_codegen_ssa::coverageinfo::map::{CounterExpression, ExprKind, FunctionCoverage, Region};
use rustc_codegen_ssa::traits::{
- BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, StaticMethods,
+ BaseTypeMethods, CoverageInfoBuilderMethods, CoverageInfoMethods, MiscMethods, StaticMethods,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_llvm::RustString;
}
impl CoverageInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
+ /// Calls llvm::createPGOFuncNameVar() with the given function instance's mangled function name.
+ /// The LLVM API returns an llvm::GlobalVariable containing the function name, with the specific
+ /// variable name and linkage required by LLVM InstrProf source-based coverage instrumentation.
+ fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value {
+ let llfn = self.cx.get_fn(instance);
+ let mangled_fn_name = CString::new(self.tcx.symbol_name(instance).name)
+ .expect("error converting function name to C string");
+ unsafe { llvm::LLVMRustCoverageCreatePGOFuncNameVar(llfn, mangled_fn_name.as_ptr()) }
+ }
+
fn add_counter_region(
&mut self,
instance: Instance<'tcx>,
self.call(llfn, &[], None)
}
sym::count_code_region => {
- let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
- let mangled_fn = tcx.symbol_name(caller_instance);
- let (mangled_fn_name, _len_val) = self.const_str(Symbol::intern(mangled_fn.name));
- let num_counters = self.const_u32(coverageinfo.num_counters);
use coverage::count_code_region_args::*;
+ let coverageinfo = tcx.coverageinfo(caller_instance.def_id());
+
+ let fn_name = self.create_pgo_func_name_var(caller_instance);
let hash = args[FUNCTION_SOURCE_HASH].immediate();
+ let num_counters = self.const_u32(coverageinfo.num_counters);
let index = args[COUNTER_ID].immediate();
debug!(
"translating Rust intrinsic `count_code_region()` to LLVM intrinsic: \
- instrprof.increment(fn_name={}, hash={:?}, num_counters={:?}, index={:?})",
- mangled_fn.name, hash, num_counters, index,
+ instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
+ fn_name, hash, num_counters, index,
);
- self.instrprof_increment(mangled_fn_name, hash, num_counters, index)
+ self.instrprof_increment(fn_name, hash, num_counters, index)
}
sym::va_start => self.va_start(args[0].immediate()),
sym::va_end => self.va_end(args[0].immediate()),
BufferOut: &RustString,
);
+ pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char)
+ -> &'a Value;
pub fn LLVMRustCoverageComputeHash(Name: *const c_char) -> u64;
#[allow(improper_ctypes)]
llvm_c_strs.push(s);
}
};
- add("rustc", true); // fake program name
+ // Set the llvm "program name" to make usage and invalid argument messages more clear.
+ add("rustc -Cllvm-args=\"...\" with", true);
if sess.time_llvm_passes() {
add("-time-passes", false);
}
rustc_hir = { path = "../librustc_hir" }
rustc_incremental = { path = "../librustc_incremental" }
rustc_index = { path = "../librustc_index" }
+rustc_macros = { path = "../librustc_macros" }
rustc_target = { path = "../librustc_target" }
rustc_session = { path = "../librustc_session" }
}
fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
- if crate_type != CrateType::Executable {
+ // On macOS the runtimes are distributed as dylibs which should be linked to
+ // both executables and dynamic shared objects. Everywhere else the runtimes
+ // are currently distributed as static liraries which should be linked to
+ // executables only.
+ let needs_runtime = match crate_type {
+ CrateType::Executable => true,
+ CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => {
+ sess.target.target.options.is_like_osx
+ }
+ CrateType::Rlib | CrateType::Staticlib => false,
+ };
+
+ if !needs_runtime {
return;
}
+
let sanitizer = sess.opts.debugging_opts.sanitizer;
if sanitizer.contains(SanitizerSet::ADDRESS) {
link_sanitizer_runtime(sess, linker, "asan");
"aarch64-fuchsia"
| "aarch64-unknown-linux-gnu"
| "x86_64-fuchsia"
+ | "x86_64-unknown-freebsd"
| "x86_64-unknown-linux-gnu" => {
let filename = format!("librustc{}_rt.{}.a", channel, name);
let path = default_tlib.join(&filename);
/// For all the linkers we support, and information they might
/// need out of the shared crate context before we get rid of it.
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
pub struct LinkerInfo {
exports: FxHashMap<CrateType, Vec<String>>,
}
let mut reachable_non_generics: DefIdMap<_> = tcx
.reachable_set(LOCAL_CRATE)
.iter()
- .filter_map(|&hir_id| {
+ .filter_map(|&def_id| {
// We want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
// categories:
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
- match tcx.hir().get(hir_id) {
+ match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
Node::ForeignItem(..) => {
- let def_id = tcx.hir().local_def_id(hir_id);
tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
}
..
})
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => {
- let def_id = tcx.hir().local_def_id(hir_id);
let generics = tcx.generics_of(def_id);
if !generics.requires_monomorphization(tcx)
// Functions marked with #[inline] are codegened with "internal"
}
}
- if tcx.sess.opts.cg.profile_generate.enabled() {
+ if tcx.sess.opts.debugging_opts.instrument_coverage
+ || tcx.sess.opts.cg.profile_generate.enabled()
+ {
// These are weak symbols that point to the profile version and the
// profile name, which need to be treated as exported so LTO doesn't nix
// them.
}));
}
- if tcx.sess.opts.debugging_opts.instrument_coverage {
- // Similar to PGO profiling, preserve symbols used by LLVM InstrProf coverage profiling.
- const COVERAGE_WEAK_SYMBOLS: [&str; 3] =
- ["__llvm_profile_filename", "__llvm_coverage_mapping", "__llvm_covmap"];
-
- symbols.extend(COVERAGE_WEAK_SYMBOLS.iter().map(|sym| {
- let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, sym));
- (exported_symbol, SymbolExportLevel::C)
- }));
- }
-
if tcx.sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::MEMORY) {
// Similar to profiling, preserve weak msan symbol during LTO.
const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"];
fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
if let Some(def_id) = def_id.as_local() {
- !tcx.reachable_set(LOCAL_CRATE).contains(&tcx.hir().as_local_hir_id(def_id))
+ !tcx.reachable_set(LOCAL_CRATE).contains(&def_id)
} else {
bug!("is_unreachable_local_definition called with non-local DefId: {:?}", def_id)
}
//! The backend-agnostic functions of this crate use functions defined in various traits that
//! have to be implemented by each backends.
+#[macro_use]
+extern crate rustc_macros;
#[macro_use]
extern crate log;
#[macro_use]
}
}
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
pub struct CompiledModule {
pub name: String,
pub kind: ModuleKind,
pub source: WorkProduct,
}
-#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable)]
pub enum ModuleKind {
Regular,
Metadata,
/// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
/// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
/// and the corresponding properties without referencing information outside of a `CrateInfo`.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
pub struct CrateInfo {
pub panic_runtime: Option<CrateNum>,
pub compiler_builtins: Option<CrateNum>,
pub dependency_formats: Lrc<Dependencies>,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
pub struct CodegenResults {
pub crate_name: Symbol,
pub modules: Vec<CompiledModule>,
use crate::traits::*;
use rustc_hir::def_id::CrateNum;
use rustc_index::vec::IndexVec;
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir;
use rustc_middle::ty;
use rustc_session::config::DebugInfo;
LocalRef::Operand(None) => return,
LocalRef::Operand(Some(operand)) => {
+ // Don't spill operands onto the stack in naked functions.
+ // See: https://github.com/rust-lang/rust/issues/42779
+ let attrs = bx.tcx().codegen_fn_attrs(self.instance.def_id());
+ if attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+ return;
+ }
+
// "Spill" the value onto the stack, for debuginfo,
// without forcing non-debuginfo uses of the local
// to also load from the stack every single time.
}
pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
+ fn create_pgo_func_name_var(&self, instance: Instance<'tcx>) -> Self::Value;
+
fn add_counter_region(
&mut self,
instance: Instance<'tcx>,
lazy_static = "1"
once_cell = { version = "1", features = ["parking_lot"] }
rustc_serialize = { path = "../librustc_serialize" }
+rustc_macros = { path = "../librustc_macros" }
rustc_graphviz = { path = "../librustc_graphviz" }
cfg-if = "0.1.2"
crossbeam-utils = { version = "0.7", features = ["nightly"] }
use crate::stable_hasher;
-use rustc_serialize::opaque::{Decoder, EncodeResult, Encoder};
+use rustc_serialize::{
+ opaque::{self, EncodeResult},
+ Decodable, Encodable,
+};
use std::mem;
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
format!("{:x}{:x}", self.0, self.1)
}
- pub fn encode_opaque(&self, encoder: &mut Encoder) -> EncodeResult {
+ pub fn encode_opaque(&self, encoder: &mut opaque::Encoder) -> EncodeResult {
let bytes: [u8; 16] = unsafe { mem::transmute([self.0.to_le(), self.1.to_le()]) };
encoder.emit_raw_bytes(&bytes);
Ok(())
}
- pub fn decode_opaque(decoder: &mut Decoder<'_>) -> Result<Fingerprint, String> {
+ pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
let mut bytes = [0; 16];
decoder.read_raw_bytes(&mut bytes)?;
impl_stable_hash_via_hash!(Fingerprint);
-impl rustc_serialize::UseSpecializedEncodable for Fingerprint {}
+impl<E: rustc_serialize::Encoder> Encodable<E> for Fingerprint {
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+ s.encode_fingerprint(self)
+ }
+}
-impl rustc_serialize::UseSpecializedDecodable for Fingerprint {}
+impl<D: rustc_serialize::Decoder> Decodable<D> for Fingerprint {
+ fn decode(d: &mut D) -> Result<Self, D::Error> {
+ d.decode_fingerprint()
+ }
+}
-impl rustc_serialize::SpecializedEncoder<Fingerprint> for Encoder {
- fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+pub trait FingerprintEncoder: rustc_serialize::Encoder {
+ fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error>;
+}
+
+pub trait FingerprintDecoder: rustc_serialize::Decoder {
+ fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error>;
+}
+
+impl<E: rustc_serialize::Encoder> FingerprintEncoder for E {
+ default fn encode_fingerprint(&mut self, _: &Fingerprint) -> Result<(), E::Error> {
+ panic!("Cannot encode `Fingerprint` with `{}`", std::any::type_name::<E>());
+ }
+}
+
+impl FingerprintEncoder for opaque::Encoder {
+ fn encode_fingerprint(&mut self, f: &Fingerprint) -> EncodeResult {
f.encode_opaque(self)
}
}
-impl<'a> rustc_serialize::SpecializedDecoder<Fingerprint> for Decoder<'a> {
- fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
+impl<D: rustc_serialize::Decoder> FingerprintDecoder for D {
+ default fn decode_fingerprint(&mut self) -> Result<Fingerprint, D::Error> {
+ panic!("Cannot decode `Fingerprint` with `{}`", std::any::type_name::<D>());
+ }
+}
+impl FingerprintDecoder for opaque::Decoder<'_> {
+ fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
Fingerprint::decode_opaque(self)
}
}
extern crate log;
#[macro_use]
extern crate cfg_if;
+#[macro_use]
+extern crate rustc_macros;
#[inline(never)]
#[cold]
/// stores data in a more compact way. It also supports accessing contiguous
/// ranges of elements as a slice, and slices of already sorted elements can be
/// inserted efficiently.
-#[derive(
- Clone,
- PartialEq,
- Eq,
- PartialOrd,
- Ord,
- Hash,
- Default,
- Debug,
- RustcEncodable,
- RustcDecodable
-)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
pub struct SortedMap<K: Ord, V> {
data: Vec<(K, V)>,
}
}
}
-impl Encodable for Svh {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for Svh {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u64(self.as_u64().to_le())
}
}
-impl Decodable for Svh {
- fn decode<D: Decoder>(d: &mut D) -> Result<Svh, D::Error> {
+impl<D: Decoder> Decodable<D> for Svh {
+ fn decode(d: &mut D) -> Result<Svh, D::Error> {
d.read_u64().map(u64::from_le).map(Svh::new)
}
}
/// A vector type optimized for cases where this size is usually 0 (cf. `SmallVector`).
/// The `Option<Box<..>>` wrapping allows us to represent a zero sized vector with `None`,
/// which uses only a single (null) pointer.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ThinVec<T>(Option<Box<Vec<T>>>);
impl<T> ThinVec<T> {
use crate::fx::FxIndexSet;
-use crate::stable_hasher::{HashStable, StableHasher};
use crate::sync::Lock;
use rustc_index::bit_set::BitMatrix;
-use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fmt::Debug;
use std::hash::Hash;
use std::mem;
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
struct Index(usize);
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
struct Edge {
source: Index,
target: Index,
candidates.truncate(j - dead);
}
}
-
-impl<T> Encodable for TransitiveRelation<T>
-where
- T: Clone + Encodable + Debug + Eq + Hash + Clone,
-{
- fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
- s.emit_struct("TransitiveRelation", 2, |s| {
- s.emit_struct_field("elements", 0, |s| self.elements.encode(s))?;
- s.emit_struct_field("edges", 1, |s| self.edges.encode(s))?;
- Ok(())
- })
- }
-}
-
-impl<T> Decodable for TransitiveRelation<T>
-where
- T: Clone + Decodable + Debug + Eq + Hash + Clone,
-{
- fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
- d.read_struct("TransitiveRelation", 2, |d| {
- Ok(TransitiveRelation {
- elements: d.read_struct_field("elements", 0, |d| Decodable::decode(d))?,
- edges: d.read_struct_field("edges", 1, |d| Decodable::decode(d))?,
- closure: Lock::new(None),
- })
- })
- }
-}
-
-impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
-where
- T: HashStable<CTX> + Eq + Debug + Clone + Hash,
-{
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- // We are assuming here that the relation graph has been built in a
- // deterministic way and we can just hash it the way it is.
- let TransitiveRelation {
- ref elements,
- ref edges,
- // "closure" is just a copy of the data above
- closure: _,
- } = *self;
-
- elements.hash_stable(hcx, hasher);
- edges.hash_stable(hcx, hasher);
- }
-}
-
-impl<CTX> HashStable<CTX> for Edge {
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- let Edge { ref source, ref target } = *self;
-
- source.hash_stable(hcx, hasher);
- target.hash_stable(hcx, hasher);
- }
-}
-
-impl<CTX> HashStable<CTX> for Index {
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- let Index(idx) = *self;
- idx.hash_stable(hcx, hasher);
- }
-}
[dependencies]
lazy_static = "1.0"
libc = "0.2"
-log = { package = "tracing", version = "0.1.18", features = ["release_max_level_info"] }
+tracing = { version = "0.1.18", features = ["release_max_level_info"] }
tracing-subscriber = { version = "0.2.10", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
rustc_middle = { path = "../librustc_middle" }
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
#![recursion_limit = "256"]
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate lazy_static;
queries.global_ctxt()?;
// Drop AST after creating GlobalCtxt to free memory
- let _timer = sess.prof.generic_activity("drop_ast");
- mem::drop(queries.expansion()?.take());
+ {
+ let _timer = sess.prof.generic_activity("drop_ast");
+ mem::drop(queries.expansion()?.take());
+ }
if sess.opts.debugging_opts.no_analysis || sess.opts.debugging_opts.ast_json {
return early_exit();
}
/// This allows tools to enable rust logging without having to magically match rustc's
-/// log crate version.
+/// tracing crate version.
pub fn init_rustc_env_logger() {
init_env_logger("RUSTC_LOG")
}
/// This allows tools to enable rust logging without having to magically match rustc's
-/// log crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
/// other than `RUSTC_LOG`.
pub fn init_env_logger(env: &str) {
// Don't register a dispatcher if there's no filter to print anything
fn print_string(s: Mutex<MyString<'static>>) {
- i_want_static_closure(move || { // error: this closure has lifetime 'a
- // rather than 'static
+ i_want_static_closure(move || { // ok!
println!("{}", s.lock().unwrap().data);
});
}
-`fn main()` or the specified start function is not allowed to be
-async. You might be seeing this error because your async runtime
-library is not set up correctly.
+The entry point of the program was marked as `async`.
Erroneous code example:
```compile_fail,E0752
-async fn main() -> Result<i32, ()> {
- Ok(1)
+async fn main() -> Result<(), ()> { // error!
+ Ok(())
+}
+```
+
+`fn main()` or the specified start function is not allowed to be `async`. Not
+having a correct async runtime library setup may cause this error. To fix it,
+declare the entry point without `async`:
+
+```
+fn main() -> Result<(), ()> { // ok!
+ Ok(())
}
```
doctest = false
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_serialize = { path = "../librustc_serialize" }
rustc_span = { path = "../librustc_span" }
+rustc_macros = { path = "../librustc_macros" }
rustc_data_structures = { path = "../librustc_data_structures" }
unicode-width = "0.1.4"
atty = "0.2"
use std::fmt;
#[must_use]
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub struct Diagnostic {
pub level: Level,
pub message: Vec<(String, Style)>,
pub sort_span: Span,
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
pub enum DiagnosticId {
Error(String),
Lint(String),
}
/// For example a note attached to an error.
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub struct SubDiagnostic {
pub level: Level,
pub message: Vec<(String, Style)>,
use crate::{Applicability, Handler, Level, StashKey};
use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString};
-use log::debug;
use rustc_span::{MultiSpan, Span};
use std::fmt::{self, Debug};
use std::ops::{Deref, DerefMut};
use std::thread::panicking;
+use tracing::debug;
/// Used for emitting structured error messages and other diagnostic information.
///
pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle,
};
-use log::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use rustc_span::hygiene::{ExpnKind, MacroKind};
use std::path::Path;
use termcolor::{Ansi, BufferWriter, ColorChoice, ColorSpec, StandardStream};
use termcolor::{Buffer, Color, WriteColor};
+use tracing::*;
/// Default column width, used in tests and when terminal dimensions cannot be determined.
const DEFAULT_COLUMN_WIDTH: usize = 140;
// The following data types are provided just for serialisation.
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct Diagnostic {
/// The primary error message.
message: String,
rendered: Option<String>,
}
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct DiagnosticSpan {
file_name: String,
byte_start: u32,
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
}
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct DiagnosticSpanLine {
text: String,
highlight_end: usize,
}
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct DiagnosticSpanMacroExpansion {
/// span where macro was applied to generate this code; note that
/// this may itself derive from a macro (if
def_site_span: DiagnosticSpan,
}
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct DiagnosticCode {
/// The code itself.
code: String,
explanation: Option<&'static str>,
}
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct ArtifactNotification<'a> {
/// The path of the artifact.
artifact: &'a Path,
use std::str;
-#[derive(RustcDecodable, Debug, PartialEq, Eq)]
+#[derive(Decodable, Debug, PartialEq, Eq)]
struct TestData {
spans: Vec<SpanTestData>,
}
-#[derive(RustcDecodable, Debug, PartialEq, Eq)]
+#[derive(Decodable, Debug, PartialEq, Eq)]
struct SpanTestData {
pub byte_start: u32,
pub byte_end: u32,
#![feature(crate_visibility_modifier)]
#![feature(nll)]
+#[macro_use]
+extern crate rustc_macros;
+
pub use emitter::ColorConfig;
-use log::debug;
+use tracing::debug;
use Level::*;
use emitter::{is_case_difference, Emitter, EmitterWriter};
/// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion
/// to determine whether it should be automatically applied or if the user should be consulted
/// before applying the suggestion.
-#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub enum Applicability {
/// The suggestion is definitely what the user intended. This suggestion should be
/// automatically applied.
Unspecified,
}
-#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
pub enum SuggestionStyle {
/// Hide the suggested code when displaying this suggestion inline.
HideCodeInline,
}
}
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub struct CodeSuggestion {
/// Each substitute can have multiple variants due to multiple
/// applicable suggestions
pub applicability: Applicability,
}
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
/// See the docs on `CodeSuggestion::substitutions`
pub struct Substitution {
pub parts: Vec<SubstitutionPart>,
}
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub struct SubstitutionPart {
pub span: Span,
pub snippet: String,
}
}
-#[derive(Copy, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, PartialEq, Clone, Hash, Debug, Encodable, Decodable)]
pub enum Level {
Bug,
Fatal,
// Useful type to use with `Result<>` indicate that an error has already
// been reported to the user, so no need to continue checking.
-#[derive(Clone, Copy, Debug, RustcEncodable, RustcDecodable, Hash, PartialEq, Eq)]
+#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)]
pub struct ErrorReported;
rustc_data_structures::impl_stable_hash_via_hash!(ErrorReported);
pub style: Style,
}
-#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
pub enum Style {
MainHeaderMsg,
HeaderMsg,
[dependencies]
rustc_serialize = { path = "../librustc_serialize" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_span = { path = "../librustc_span" }
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
rustc_ast_passes = { path = "../librustc_ast_passes" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
rustc_feature = { path = "../librustc_feature" }
+rustc_macros = { path = "../librustc_macros" }
rustc_lexer = { path = "../librustc_lexer" }
rustc_parse = { path = "../librustc_parse" }
rustc_session = { path = "../librustc_session" }
#![feature(proc_macro_span)]
#![feature(try_blocks)]
+#[macro_use]
+extern crate rustc_macros;
+
extern crate proc_macro as pm;
mod placeholders;
/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note
/// that the delimiter itself might be `NoDelim`.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
struct Delimited {
delim: token::DelimToken,
tts: Vec<TokenTree>,
}
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug)]
struct SequenceRepetition {
/// The sequence of token trees
tts: Vec<TokenTree>,
num_captures: usize,
}
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
struct KleeneToken {
span: Span,
op: KleeneOp,
/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
/// for token sequences.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
enum KleeneOp {
/// Kleene star (`*`) for zero or more repetitions
ZeroOrMore,
/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)`
/// are "first-class" token trees. Useful for parsing macros.
-#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Clone, PartialEq, Encodable, Decodable)]
enum TokenTree {
Token(Token),
Delimited(DelimSpan, Lrc<Delimited>),
use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent};
use rustc_span::Span;
-use log::debug;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::{mem, slice};
+use tracing::debug;
crate struct ParserAnyMacro<'a> {
parser: Parser<'a>,
rustc_serialize = { path = "../librustc_serialize" }
rustc_ast = { path = "../librustc_ast" }
lazy_static = "1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
// HIR types
- [few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>;
- [] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>;
- [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>;
- [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
- [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
- [] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>;
- [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>;
- [few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm;
- [] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>;
- [] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>;
- [] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>;
- [] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>;
- [] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>;
- [] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>;
- [] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>;
- [] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>;
- [] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>;
- [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>;
- [few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>;
- [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>;
- [] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>;
- [few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>;
- [] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>;
- [] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>;
- [] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>;
- [] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>;
- [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>;
- [] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>;
- [] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>;
- [] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>;
- [] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef;
- [] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>;
- [] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>;
- [] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>;
- [] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>;
+ [few] hir_krate: rustc_hir::Crate<$tcx>,
+ [] arm: rustc_hir::Arm<$tcx>,
+ [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
+ [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+ [] attribute: rustc_ast::ast::Attribute,
+ [] block: rustc_hir::Block<$tcx>,
+ [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
+ [few] global_asm: rustc_hir::GlobalAsm,
+ [] generic_arg: rustc_hir::GenericArg<$tcx>,
+ [] generic_args: rustc_hir::GenericArgs<$tcx>,
+ [] generic_bound: rustc_hir::GenericBound<$tcx>,
+ [] generic_param: rustc_hir::GenericParam<$tcx>,
+ [] expr: rustc_hir::Expr<$tcx>,
+ [] field: rustc_hir::Field<$tcx>,
+ [] field_pat: rustc_hir::FieldPat<$tcx>,
+ [] fn_decl: rustc_hir::FnDecl<$tcx>,
+ [] foreign_item: rustc_hir::ForeignItem<$tcx>,
+ [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+ [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
+ [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
+ [] local: rustc_hir::Local<$tcx>,
+ [few] macro_def: rustc_hir::MacroDef<$tcx>,
+ [] param: rustc_hir::Param<$tcx>,
+ [] pat: rustc_hir::Pat<$tcx>,
+ [] path: rustc_hir::Path<$tcx>,
+ [] path_segment: rustc_hir::PathSegment<$tcx>,
+ [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
+ [] qpath: rustc_hir::QPath<$tcx>,
+ [] stmt: rustc_hir::Stmt<$tcx>,
+ [] struct_field: rustc_hir::StructField<$tcx>,
+ [] trait_item_ref: rustc_hir::TraitItemRef,
+ [] ty: rustc_hir::Ty<$tcx>,
+ [] type_binding: rustc_hir::TypeBinding<$tcx>,
+ [] variant: rustc_hir::Variant<$tcx>,
+ [] where_predicate: rustc_hir::WherePredicate<$tcx>,
], $tcx);
)
}
use std::fmt::Debug;
/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum CtorOf {
/// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
Variant,
}
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum CtorKind {
/// Constructor function automatically created by a tuple struct/variant.
Fictive,
}
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum NonMacroAttrKind {
/// Single-segment attribute defined by the language (`#[inline]`)
Registered,
}
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum DefKind {
// Type namespace
}
/// The resolution of a path or export.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum Res<Id = hir::HirId> {
Def(DefKind, DefId),
use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{sym, Symbol};
-use log::debug;
use std::fmt::Write;
use std::hash::Hash;
+use tracing::debug;
/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
/// stores the `DefIndex` of its parent.
/// There is one `DefPathTable` for each crate.
-#[derive(Clone, Default, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Default, Decodable, Encodable)]
pub struct DefPathTable {
index_to_key: IndexVec<DefIndex, DefKey>,
def_path_hashes: IndexVec<DefIndex, DefPathHash>,
/// A unique identifier that we can use to lookup a definition
/// precisely. It combines the index of the definition's parent (if
/// any) with a `DisambiguatedDefPathData`.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
pub struct DefKey {
/// The parent path.
pub parent: Option<DefIndex>,
/// between them. This introduces some artificial ordering dependency
/// but means that if you have, e.g., two impls for the same type in
/// the same module, they do get distinct `DefId`s.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
pub struct DisambiguatedDefPathData {
pub data: DefPathData,
pub disambiguator: u32,
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
pub struct DefPath {
/// The path leading from the crate root to the item.
pub data: Vec<DisambiguatedDefPathData>,
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
pub enum DefPathData {
// Root: these should only be used for the root nodes, because
// they are treated specially by the `def_path` function.
})
}
- #[inline]
- pub fn as_local_hir_id(&self, def_id: LocalDefId) -> hir::HirId {
- self.local_def_id_to_hir_id(def_id)
- }
-
#[inline]
pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
self.def_id_to_hir_id[id].unwrap()
use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, HashStable_Generic)]
pub struct Lifetime {
pub hir_id: HirId,
pub span: Span,
pub name: LifetimeName,
}
-#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
#[derive(HashStable_Generic)]
pub enum ParamName {
/// Some user-given name like `T` or `'x`.
}
}
-#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
+#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
#[derive(HashStable_Generic)]
pub enum LifetimeName {
/// User-given names or fresh (synthetic) names.
/// A `Path` is essentially Rust's notion of a name; for instance,
/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
/// along with a bunch of supporting information.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Path<'hir> {
pub span: Span,
/// The resolution for the path.
/// A segment of a path: an identifier, an optional lifetime, and a set of
/// types.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct PathSegment<'hir> {
/// The identifier portion of this path segment.
#[stable_hasher(project(name))]
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
pub struct ConstArg {
pub value: AnonConst,
pub span: Span,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum GenericArg<'hir> {
Lifetime(Lifetime),
Type(Ty<'hir>),
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct GenericArgs<'hir> {
/// The generic arguments for this path segment.
pub args: &'hir [GenericArg<'hir>],
/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum TraitBoundModifier {
None,
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum GenericBound<'hir> {
Trait(PolyTraitRef<'hir>, TraitBoundModifier),
Outlives(Lifetime),
pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
pub enum LifetimeParamKind {
// Indicates that the lifetime definition was explicitly declared (e.g., in
// `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
Error,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum GenericParamKind<'hir> {
/// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
Lifetime {
},
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct GenericParam<'hir> {
pub hir_id: HirId,
pub name: ParamName,
/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Generics<'hir> {
pub params: &'hir [GenericParam<'hir>],
pub where_clause: WhereClause<'hir>,
/// Synthetic type parameters are converted to another form during lowering; this allows
/// us to track the original form they had, and is useful for error messages.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum SyntheticTyParamKind {
ImplTrait,
}
/// A where-clause in a definition.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct WhereClause<'hir> {
pub predicates: &'hir [WherePredicate<'hir>],
// Only valid if predicates aren't empty.
}
/// A single predicate in a where-clause.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum WherePredicate<'hir> {
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
BoundPredicate(WhereBoundPredicate<'hir>),
}
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct WhereBoundPredicate<'hir> {
pub span: Span,
/// Any generics from a `for` binding.
}
/// A lifetime predicate (e.g., `'a: 'b + 'c`).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct WhereRegionPredicate<'hir> {
pub span: Span,
pub lifetime: Lifetime,
}
/// An equality predicate (e.g., `T = int`); currently unsupported.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct WhereEqPredicate<'hir> {
pub hir_id: HirId,
pub span: Span,
pub rhs_ty: &'hir Ty<'hir>,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
pub struct ModuleItems {
// Use BTreeSets here so items are in the same order as in the
// list of all items in Crate
}
/// A type representing only the top-level module.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
pub struct CrateItem<'hir> {
pub module: Mod<'hir>,
pub attrs: &'hir [Attribute],
/// For more details, see the [rustc dev guide].
///
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
pub struct Crate<'hir> {
pub item: CrateItem<'hir>,
pub exported_macros: &'hir [MacroDef<'hir>],
/// A macro definition, in this crate or imported from another.
///
/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct MacroDef<'hir> {
pub ident: Ident,
pub vis: Visibility<'hir>,
/// A block of statements `{ .. }`, which may have a label (in this case the
/// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
/// the `rules` being anything but `DefaultBlock`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Block<'hir> {
/// Statements in a block.
pub stmts: &'hir [Stmt<'hir>],
pub targeted_by_break: bool,
}
-#[derive(Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Pat<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
/// are treated the same as` x: x, y: ref y, z: ref mut z`,
/// except `is_shorthand` is true.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct FieldPat<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
/// Explicit binding annotations given in the HIR for a binding. Note
/// that this is not the final binding *mode* that we infer after type
/// inference.
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum BindingAnnotation {
/// No binding annotation given: this means that the final binding mode
/// will depend on whether we have skipped through a `&` reference
RefMut,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum RangeEnd {
Included,
Excluded,
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum PatKind<'hir> {
/// Represents a wildcard pattern (i.e., `_`).
Wild,
Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]),
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum BinOpKind {
/// The `+` operator (addition).
Add,
pub type BinOp = Spanned<BinOpKind>;
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum UnOp {
/// The `*` operator (deferencing).
UnDeref,
}
/// A statement.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Stmt<'hir> {
pub hir_id: HirId,
pub kind: StmtKind<'hir>,
}
/// The contents of a statement.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum StmtKind<'hir> {
/// A local (`let`) binding.
Local(&'hir Local<'hir>),
}
/// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Local<'hir> {
pub pat: &'hir Pat<'hir>,
/// Type annotation, if any (otherwise the type will be inferred).
/// Represents a single arm of a `match` expression, e.g.
/// `<pat> (if <guard>) => <body>`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Arm<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub body: &'hir Expr<'hir>,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum Guard<'hir> {
If(&'hir Expr<'hir>),
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Field<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub is_shorthand: bool,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum BlockCheckMode {
DefaultBlock,
UnsafeBlock(UnsafeSource),
PopUnsafeBlock(UnsafeSource),
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)]
pub struct BodyId {
pub hir_id: HirId,
}
///
/// All bodies have an **owner**, which can be accessed via the HIR
/// map using `body_owner_def_id()`.
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
pub struct Body<'hir> {
pub params: &'hir [Param<'hir>],
pub value: Expr<'hir>,
}
/// The type of source expression that caused this generator to be created.
-#[derive(Clone, PartialEq, Eq, HashStable_Generic, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
pub enum GeneratorKind {
/// An explicit `async` block or the body of an async function.
Async(AsyncGeneratorKind),
///
/// This helps error messages but is also used to drive coercions in
/// type-checking (see #60424).
-#[derive(Clone, PartialEq, Eq, HashStable_Generic, RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
pub enum AsyncGeneratorKind {
/// An explicit `async` block written by the user.
Block,
/// These are usually found nested inside types (e.g., array lengths)
/// or expressions (e.g., repeat counts), and also used to define
/// explicit discriminant values for enum variants.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
pub struct AnonConst {
pub hir_id: HirId,
pub body: BodyId,
}
/// An expression.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug)]
pub struct Expr<'hir> {
pub hir_id: HirId,
pub kind: ExprKind<'hir>,
false
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum ExprKind<'hir> {
/// A `box x` expression.
Box(&'hir Expr<'hir>),
/// To resolve the path to a `DefId`, call [`qpath_res`].
///
/// [`qpath_res`]: ../rustc_middle/ty/struct.TypeckResults.html#method.qpath_res
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum QPath<'hir> {
/// Path to a definition, optionally "fully-qualified" with a `Self`
/// type, if the path points to an associated item in a trait.
}
/// Hints at the original code for a let statement.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub enum LocalSource {
/// A `match _ { .. }`.
Normal,
}
/// Hints at the original code for a `match _ { .. }`.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum MatchSource {
/// A `match _ { .. }`.
}
/// The loop type that yielded an `ExprKind::Loop`.
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum LoopSource {
/// A `loop { .. }` loop.
Loop,
}
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub enum LoopIdError {
OutsideLoopScope,
UnlabeledCfInWhileCondition,
}
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub struct Destination {
// This is `Some(_)` iff there is an explicit user-specified `label
pub label: Option<Label>,
}
/// The yield kind that caused an `ExprKind::Yield`.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum YieldSource {
/// An `<expr>.await`.
Await { expr: Option<HirId> },
// N.B., if you change this, you'll probably want to change the corresponding
// type structure in middle/ty.rs as well.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct MutTy<'hir> {
pub ty: &'hir Ty<'hir>,
pub mutbl: Mutability,
/// Represents a function's signature in a trait declaration,
/// trait implementation, or a free function.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct FnSig<'hir> {
pub header: FnHeader,
pub decl: &'hir FnDecl<'hir>,
// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the node-id of the item
// so it can fetched later.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct TraitItemId {
pub hir_id: HirId,
}
/// possibly including a default implementation. A trait item is
/// either required (meaning it doesn't have an implementation, just a
/// signature) or provided (meaning it has a default implementation).
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
pub struct TraitItem<'hir> {
pub ident: Ident,
pub hir_id: HirId,
}
/// Represents a trait method's body (or just argument names).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
pub enum TraitFn<'hir> {
/// No default body in the trait, just a signature.
Required(&'hir [Ident]),
}
/// Represents a trait method or associated constant or type
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum TraitItemKind<'hir> {
/// An associated constant with an optional value (otherwise `impl`s must contain a value).
Const(&'hir Ty<'hir>, Option<BodyId>),
// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the node-id of the item
// so it can fetched later.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
pub struct ImplItemId {
pub hir_id: HirId,
}
/// Represents anything within an `impl` block.
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
pub struct ImplItem<'hir> {
pub ident: Ident,
pub hir_id: HirId,
}
/// Represents various kinds of content within an `impl`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum ImplItemKind<'hir> {
/// An associated constant of the given type, set to the constant result
/// of the expression.
/// Binding(...),
/// }
/// ```
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct TypeBinding<'hir> {
pub hir_id: HirId,
#[stable_hasher(project(name))]
}
// Represents the two kinds of type bindings.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum TypeBindingKind<'hir> {
/// E.g., `Foo<Bar: Send>`.
Constraint { bounds: &'hir [GenericBound<'hir>] },
}
}
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug)]
pub struct Ty<'hir> {
pub hir_id: HirId,
pub kind: TyKind<'hir>,
}
/// Not represented directly in the AST; referred to by name through a `ty_path`.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum PrimTy {
Int(IntTy),
Char,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct BareFnTy<'hir> {
pub unsafety: Unsafety,
pub abi: Abi,
pub param_names: &'hir [Ident],
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct OpaqueTy<'hir> {
pub generics: Generics<'hir>,
pub bounds: GenericBounds<'hir>,
}
/// From whence the opaque type came.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum OpaqueTyOrigin {
/// `-> impl Trait`
FnReturn,
}
/// The various kinds of types recognized by the compiler.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum TyKind<'hir> {
/// A variable length slice (i.e., `[T]`).
Slice(&'hir Ty<'hir>),
Err,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum InlineAsmOperand<'hir> {
In {
reg: InlineAsmRegOrRegClass,
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct InlineAsm<'hir> {
pub template: &'hir [InlineAsmTemplatePiece],
pub operands: &'hir [InlineAsmOperand<'hir>],
pub line_spans: &'hir [Span],
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
pub struct LlvmInlineAsmOutput {
pub constraint: Symbol,
pub is_rw: bool,
}
// NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
-// it needs to be `Clone` and use plain `Vec<T>` instead of arena-allocated slice.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)]
+// it needs to be `Clone` and `Decodable` and use plain `Vec<T>` instead of
+// arena-allocated slice.
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
pub struct LlvmInlineAsmInner {
pub asm: Symbol,
pub asm_str_style: StrStyle,
pub dialect: LlvmAsmDialect,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct LlvmInlineAsm<'hir> {
pub inner: LlvmInlineAsmInner,
pub outputs_exprs: &'hir [Expr<'hir>],
}
/// Represents a parameter in a function header.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Param<'hir> {
pub attrs: &'hir [Attribute],
pub hir_id: HirId,
}
/// Represents the header (not the body) of a function declaration.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct FnDecl<'hir> {
/// The types of the function's parameters.
///
}
/// Represents what type of implicit self a function has, if any.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum ImplicitSelfKind {
/// Represents a `fn x(self);`.
Imm,
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum IsAsync {
Async,
NotAsync,
}
-#[derive(
- Copy,
- Clone,
- PartialEq,
- RustcEncodable,
- RustcDecodable,
- Debug,
- HashStable_Generic,
- Eq,
- Hash
-)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum Defaultness {
Default { has_value: bool },
Final,
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum FnRetTy<'hir> {
/// Return type is not specified.
///
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Encodable, Debug)]
pub struct Mod<'hir> {
/// A span from the first token past `{` to the last token until `}`.
/// For `mod foo;`, the inner span ranges from the first token
pub item_ids: &'hir [ItemId],
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct ForeignMod<'hir> {
pub abi: Abi,
pub items: &'hir [ForeignItem<'hir>],
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
pub struct GlobalAsm {
pub asm: Symbol,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct EnumDef<'hir> {
pub variants: &'hir [Variant<'hir>],
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct Variant<'hir> {
/// Name of the variant.
#[stable_hasher(project(name))]
pub span: Span,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum UseKind {
/// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
/// Also produced for each element of a list `use`, e.g.
/// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the
/// trait being referred to but just a unique `HirId` that serves as a key
/// within the resolution map.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct TraitRef<'hir> {
pub path: &'hir Path<'hir>,
// Don't hash the `ref_id`. It is tracked via the thing it is used to access.
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct PolyTraitRef<'hir> {
/// The `'a` in `for<'a> Foo<&'a T>`.
pub bound_generic_params: &'hir [GenericParam<'hir>],
pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
pub enum VisibilityKind<'hir> {
Public,
Crate(CrateSugar),
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct StructField<'hir> {
pub span: Span,
#[stable_hasher(project(name))]
}
/// Fields and constructor IDs of enum variants and structs.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum VariantData<'hir> {
/// A struct variant.
///
// The bodies for items are stored "out of line", in a separate
// hashmap in the `Crate`. Here we just record the node-id of the item
// so it can fetched later.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, Encodable, Debug)]
pub struct ItemId {
pub id: HirId,
}
/// An item
///
/// The name might be a dummy name in case of anonymous items
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Debug)]
pub struct Item<'hir> {
pub ident: Ident,
pub hir_id: HirId,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum Unsafety {
Unsafe,
Normal,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum Constness {
Const,
NotConst,
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
pub struct FnHeader {
pub unsafety: Unsafety,
pub constness: Constness,
}
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum ItemKind<'hir> {
/// An `extern crate` item, with optional *original* crate name if the crate was renamed.
///
/// type or method, and whether it is public). This allows other
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Encodable, Debug, HashStable_Generic)]
pub struct TraitItemRef {
pub id: TraitItemId,
#[stable_hasher(project(name))]
/// type or method, and whether it is public). This allows other
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct ImplItemRef<'hir> {
pub id: ImplItemId,
#[stable_hasher(project(name))]
pub defaultness: Defaultness,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
pub enum AssocItemKind {
Const,
Fn { has_self: bool },
Type,
}
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub struct ForeignItem<'hir> {
#[stable_hasher(project(name))]
pub ident: Ident,
}
/// An item within an `extern` block.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+#[derive(Debug, HashStable_Generic)]
pub enum ForeignItemKind<'hir> {
/// A foreign function.
Fn(&'hir FnDecl<'hir>, &'hir [Ident], Generics<'hir>),
}
/// A variable captured by a closure.
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
pub struct Upvar {
// First span where it is accessed (there can be multiple).
pub span: Span,
// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
// has length > 0 if the trait is found through an chain of imports, starting with the
// import/use statement in the scope where the trait is used.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug)]
+#[derive(Encodable, Decodable, Clone, Debug)]
pub struct TraitCandidate {
pub def_id: DefId,
pub import_ids: SmallVec<[LocalDefId; 1]>,
/// the `local_id` part of the `HirId` changing, which is a very useful property in
/// incremental compilation where we have to persist things through changes to
/// the code base.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Encodable, Decodable)]
pub struct HirId {
pub owner: LocalDefId,
pub local_id: ItemLocalId,
enum_from_u32! {
/// A representation of all the valid language items in Rust.
- #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+ #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
pub enum LangItem {
$($variant,)*
}
BoolImplItem, sym::bool, bool_impl, Target::Impl;
CharImplItem, sym::char, char_impl, Target::Impl;
StrImplItem, sym::str, str_impl, Target::Impl;
+ ArrayImplItem, sym::array, array_impl, Target::Impl;
SliceImplItem, sym::slice, slice_impl, Target::Impl;
SliceU8ImplItem, sym::slice_u8, slice_u8_impl, Target::Impl;
StrAllocImplItem, sym::str_alloc, str_alloc_impl, Target::Impl;
#![feature(const_panic)]
#![feature(in_band_lifetimes)]
#![feature(or_patterns)]
-#![feature(min_specialization)]
#![recursion_limit = "256"]
+#[macro_use]
+extern crate rustc_macros;
+
#[macro_use]
extern crate rustc_data_structures;
[dependencies]
rustc_graphviz = { path = "../librustc_graphviz" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rand = "0.7"
rustc_middle = { path = "../librustc_middle" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_hir = { path = "../librustc_hir" }
rustc_serialize = { path = "../librustc_serialize" }
rustc_ast = { path = "../librustc_ast" }
+rustc_macros = { path = "../librustc_macros" }
rustc_span = { path = "../librustc_span" }
rustc_fs_util = { path = "../librustc_fs_util" }
rustc_session = { path = "../librustc_session" }
#[macro_use]
extern crate rustc_middle;
#[macro_use]
-extern crate log;
+extern crate tracing;
mod assert_dep_graph;
pub mod assert_module_sources;
//! The data that we will serialize and deserialize.
+use rustc_macros::{Decodable, Encodable};
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
pub struct SerializedWorkProduct {
/// node that produced the work-product
pub id: WorkProductId,
doctest = false
[dependencies]
-rustc_serialize = { path = "../librustc_serialize" }
arrayvec = "0.5.1"
+rustc_serialize = { path = "../librustc_serialize" }
+rustc_macros = { path = "../librustc_macros" }
use std::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Range, Shl};
use std::slice;
+use rustc_macros::{Decodable, Encodable};
+
#[cfg(test)]
mod tests;
/// will panic if the bitsets have differing domain sizes.
///
/// [`GrowableBitSet`]: struct.GrowableBitSet.html
-#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Eq, PartialEq, Decodable, Encodable)]
pub struct BitSet<T: Idx> {
domain_size: usize,
words: Vec<Word>,
///
/// All operations that involve a row and/or column index will panic if the
/// index exceeds the relevant bound.
-#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Eq, PartialEq, Decodable, Encodable)]
pub struct BitMatrix<R: Idx, C: Idx> {
num_rows: usize,
num_columns: usize,
/// A fixed-sized bitset type represented by an integer type. Indices outwith than the range
/// representable by `T` are considered set.
-#[derive(Copy, Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)]
+#[derive(Copy, Clone, Eq, PartialEq, Decodable, Encodable)]
pub struct FiniteBitSet<T: FiniteBitSetTy>(pub T);
impl<T: FiniteBitSetTy> FiniteBitSet<T> {
derive [$($derives:ident,)+]
$($tokens:tt)*) => (
$crate::newtype_index!(
- @derives [$($derives,)+ RustcEncodable,]
+ @derives [$($derives,)+]
@attrs [$(#[$attrs])*]
@type [$type]
@max [$max]
@vis [$v]
@debug_format [$debug_format]
$($tokens)*);
- $crate::newtype_index!(@decodable $type);
+ $crate::newtype_index!(@serializable $type);
);
// The case where no derives are added, but encodable is overridden. Don't
@debug_format [$debug_format:tt]
$($tokens:tt)*) => (
$crate::newtype_index!(
- @derives [RustcEncodable,]
+ @derives []
@attrs [$(#[$attrs])*]
@type [$type]
@max [$max]
@vis [$v]
@debug_format [$debug_format]
$($tokens)*);
- $crate::newtype_index!(@decodable $type);
+ $crate::newtype_index!(@serializable $type);
);
- (@decodable $type:ident) => (
- impl ::rustc_serialize::Decodable for $type {
- fn decode<D: ::rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
+ (@serializable $type:ident) => (
+ impl<D: ::rustc_serialize::Decoder> ::rustc_serialize::Decodable<D> for $type {
+ fn decode(d: &mut D) -> Result<Self, D::Error> {
d.read_u32().map(Self::from_u32)
}
}
+ impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for $type {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ e.emit_u32(self.private)
+ }
+ }
);
// Rewrite final without comma to one that includes comma
// not the phantom data.
unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
-impl<I: Idx, T: Encodable> Encodable for IndexVec<I, T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&self.raw, s)
}
}
-impl<I: Idx, T: Decodable> Decodable for IndexVec<I, T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for &IndexVec<I, T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+ Encodable::encode(&self.raw, s)
+ }
+}
+
+impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
+ fn decode(d: &mut D) -> Result<Self, D::Error> {
Decodable::decode(d).map(|v| IndexVec { raw: v, _marker: PhantomData })
}
}
}
}
+ /// Returns mutable references to three distinct elements or panics otherwise.
+ #[inline]
+ pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
+ let (ai, bi, ci) = (a.index(), b.index(), c.index());
+ assert!(ai != bi && bi != ci && ci != ai);
+ let len = self.raw.len();
+ assert!(ai < len && bi < len && ci < len);
+ let ptr = self.raw.as_mut_ptr();
+ unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
+ }
+
pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
IndexVec { raw: self.raw, _marker: PhantomData }
}
[dependencies]
rustc_graphviz = { path = "../librustc_graphviz" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
let sm = tcx.sess.source_map();
let scope = region.free_region_binding_scope(tcx);
- let node = tcx.hir().as_local_hir_id(scope.expect_local());
+ let node = tcx.hir().local_def_id_to_hir_id(scope.expect_local());
let tag = match tcx.hir().find(node) {
Some(Node::Block(_) | Node::Expr(_)) => "body",
Some(Node::Item(it)) => item_scope_tag(&it),
.in_progress_typeck_results
.map(|typeck_results| typeck_results.borrow().hir_owner)
.map(|owner| {
- let hir_id = hir.as_local_hir_id(owner);
+ let hir_id = hir.local_def_id_to_hir_id(owner);
let parent_id = hir.get_parent_item(hir_id);
(
// Parent item could be a `mod`, so we check the HIR before calling:
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
- let id = hir.as_local_hir_id(def_id);
+ let id = hir.local_def_id_to_hir_id(def_id);
let mut has_bounds = false;
if let Node::GenericParam(param) = hir.get(id) {
has_bounds = !param.bounds.is_empty();
.and_then(|(_, g)| g.params.first())
.and_then(|param| param.def_id.as_local())
.map(|def_id| {
- (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))
+ (
+ hir.span(hir.local_def_id_to_hir_id(def_id)).shrink_to_lo(),
+ format!("{}, ", new_lt),
+ )
});
let labeled_user_string = match bound_kind {
br: &ty::BoundRegion,
) -> Option<(&hir::Ty<'tcx>, &hir::FnDecl<'tcx>)> {
if let Some(anon_reg) = self.tcx().is_suitable_region(region) {
- let hir_id = self.tcx().hir().as_local_hir_id(anon_reg.def_id);
+ let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
let fndecl = match self.tcx().hir().get(hir_id) {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. })
| Node::TraitItem(&hir::TraitItem {
match assoc_item.kind {
ty::AssocKind::Fn => {
let hir = self.tcx().hir();
- if let Some(hir_id) = assoc_item.def_id.as_local().map(|id| hir.as_local_hir_id(id))
+ if let Some(hir_id) =
+ assoc_item.def_id.as_local().map(|id| hir.local_def_id_to_hir_id(id))
{
if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
visitor.visit_fn_decl(decl);
};
let hir = &self.tcx().hir();
- let hir_id = hir.as_local_hir_id(id.as_local()?);
+ let hir_id = hir.local_def_id_to_hir_id(id.as_local()?);
let body_id = hir.maybe_body_owned_by(hir_id)?;
let body = hir.body(body_id);
let owner_id = hir.body_owner(body_id);
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, Lift, Region, TyCtxt};
-/// Combines a `region::ScopeTree` (which governs relationships between
-/// scopes) and a `FreeRegionMap` (which governs relationships between
-/// free regions) to yield a complete relation between concrete
-/// regions.
+/// Combines a `FreeRegionMap` and a `TyCtxt`.
///
/// This stuff is a bit convoluted and should be refactored, but as we
/// transition to NLL, it'll all go away anyhow.
pub struct RegionRelations<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,
- /// The context used to fetch the region maps.
+ /// The context used for debug messages
pub context: DefId,
/// Free-region relationships.
}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default, HashStable)]
+#[derive(Clone, Debug, Default)]
pub struct FreeRegionMap<'tcx> {
// Stores the relation `a < b`, where `a` and `b` are regions.
//
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_middle;
[dependencies]
libc = "0.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rayon = { version = "0.3.0", package = "rustc-rayon" }
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_ast = { path = "../librustc_ast" }
}
pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
- log::trace!("run_compiler");
+ tracing::trace!("run_compiler");
let stderr = config.stderr.take();
util::setup_callbacks_and_run_in_thread_pool_with_globals(
config.opts.edition,
use crate::proc_macro_decls;
use crate::util;
-use log::{info, warn};
use once_cell::sync::Lazy;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::{self, ast, visit};
use rustc_span::{FileName, RealFileName};
use rustc_trait_selection::traits;
use rustc_typeck as typeck;
+use tracing::{info, warn};
use rustc_serialize::json;
use tempfile::Builder as TempFileBuilder;
krate: ast::Crate,
crate_name: &str,
) -> Result<(ast::Crate, BoxedResolver)> {
- log::trace!("configure_and_expand");
+ tracing::trace!("configure_and_expand");
// Currently, we ignore the name resolution data structures for the purposes of dependency
// tracking. Instead we will run name resolution and include its output in the hash of each
// item, much like we do for macro expansion. In other words, the hash reflects not just
resolver_arenas: &'a ResolverArenas<'a>,
metadata_loader: &'a MetadataLoaderDyn,
) -> Result<(ast::Crate, Resolver<'a>)> {
- log::trace!("configure_and_expand_inner");
+ tracing::trace!("configure_and_expand_inner");
pre_expansion_lint(sess, lint_store, &krate);
let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
});
if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
- log::debug!("replacing bodies with loop {{}}");
+ tracing::debug!("replacing bodies with loop {{}}");
util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
}
pub fn expansion(
&self,
) -> Result<&Query<(ast::Crate, Steal<Rc<RefCell<BoxedResolver>>>, Lrc<LintStore>)>> {
- log::trace!("expansion");
+ tracing::trace!("expansion");
self.expansion.compute(|| {
let crate_name = self.crate_name()?.peek().clone();
let (krate, lint_store) = self.register_plugins()?.take();
-use log::info;
use rustc_ast::ast::{AttrVec, BlockCheckMode};
use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
use rustc_ast::ptr::P;
use std::sync::{Arc, Mutex, Once};
#[cfg(not(parallel_compiler))]
use std::{panic, thread};
+use tracing::info;
/// Adds `target_feature = "..."` cfgs for a variety of platform
/// specific features (SSE, NEON etc.).
path = "lib.rs"
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
unicode-security = "0.0.5"
rustc_middle = { path = "../librustc_middle" }
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
use crate::nonstandard_style::{method_context, MethodLateContext};
-use log::{debug, trace};
use std::fmt::Write;
+use tracing::{debug, trace};
// hardwired lints from librustc_middle
pub use rustc_session::lint::builtin::*;
// reported for missing docs.
let real_trait = trait_ref.path.res.def_id();
if let Some(def_id) = real_trait.as_local() {
- let hir_id = cx.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(Node::Item(item)) = cx.tcx.hir().find(hir_id) {
if let hir::VisibilityKind::Inherited = item.vis.node {
for impl_item_ref in items {
cx.tcx.for_each_impl(debug, |d| {
if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
if let Some(def_id) = ty_def.did.as_local() {
- impls.insert(cx.tcx.hir().as_local_hir_id(def_id));
+ impls.insert(cx.tcx.hir().local_def_id_to_hir_id(def_id));
}
}
});
use rustc_span::symbol::Ident;
use rustc_span::Span;
-use log::debug;
use std::slice;
+use tracing::debug;
macro_rules! run_early_pass { ($cx:expr, $f:ident, $($args:expr),*) => ({
$cx.pass.$f(&$cx.context, $($args),*);
use rustc_span::symbol::Symbol;
use rustc_span::Span;
-use log::debug;
use std::any::Any;
use std::cell::Cell;
use std::slice;
+use tracing::debug;
/// Extract the `LintStore` from the query context.
/// This function exists because we've erased `LintStore` as `dyn Any` in the context.
param_env: ty::ParamEnv::empty(),
access_levels,
lint_store: unerased_lint_store(tcx),
- last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id),
+ last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id),
generics: None,
only_module: true,
};
use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
use rustc_target::spec::abi::Abi as SpecAbi;
-use log::debug;
use std::cmp;
+use tracing::debug;
declare_lint! {
UNUSED_COMPARISONS,
use rustc_span::symbol::{kw, sym};
use rustc_span::{BytePos, Span, DUMMY_SP};
-use log::debug;
+use tracing::debug;
declare_lint! {
pub UNUSED_MUST_USE,
mod hash_stable;
mod lift;
mod query;
+mod serialize;
mod symbols;
mod type_foldable;
hash_stable::hash_stable_generic_derive
);
+decl_derive!([Decodable] => serialize::decodable_derive);
+decl_derive!([Encodable] => serialize::encodable_derive);
+decl_derive!([TyDecodable] => serialize::type_decodable_derive);
+decl_derive!([TyEncodable] => serialize::type_encodable_derive);
+decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
+decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
--- /dev/null
+use proc_macro2::TokenStream;
+use quote::quote;
+use syn::parse_quote;
+
+pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ let decoder_ty = quote! { __D };
+ if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+ s.add_impl_generic(parse_quote! { 'tcx });
+ }
+ s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_middle::ty::codec::TyDecoder<'tcx>});
+ s.add_bounds(synstructure::AddBounds::Generics);
+
+ decodable_body(s, decoder_ty)
+}
+
+pub fn meta_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+ s.add_impl_generic(parse_quote! { 'tcx });
+ }
+ s.add_impl_generic(parse_quote! { '__a });
+ let decoder_ty = quote! { DecodeContext<'__a, 'tcx> };
+ s.add_bounds(synstructure::AddBounds::Generics);
+
+ decodable_body(s, decoder_ty)
+}
+
+pub fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ let decoder_ty = quote! { __D };
+ s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_serialize::Decoder});
+ s.add_bounds(synstructure::AddBounds::Generics);
+
+ decodable_body(s, decoder_ty)
+}
+
+fn decodable_body(
+ s: synstructure::Structure<'_>,
+ decoder_ty: TokenStream,
+) -> proc_macro2::TokenStream {
+ if let syn::Data::Union(_) = s.ast().data {
+ panic!("cannot derive on union")
+ }
+ let ty_name = s.ast().ident.to_string();
+ let decode_body = match s.variants() {
+ [vi] => {
+ let construct = vi.construct(|field, index| decode_field(field, index, true));
+ let n_fields = vi.ast().fields.len();
+ quote! {
+ ::rustc_serialize::Decoder::read_struct(
+ __decoder,
+ #ty_name,
+ #n_fields,
+ |__decoder| { ::std::result::Result::Ok(#construct) },
+ )
+ }
+ }
+ variants => {
+ let match_inner: TokenStream = variants
+ .iter()
+ .enumerate()
+ .map(|(idx, vi)| {
+ let construct = vi.construct(|field, index| decode_field(field, index, false));
+ quote! { #idx => { ::std::result::Result::Ok(#construct) } }
+ })
+ .collect();
+ let names: TokenStream = variants
+ .iter()
+ .map(|vi| {
+ let variant_name = vi.ast().ident.to_string();
+ quote!(#variant_name,)
+ })
+ .collect();
+ let message = format!(
+ "invalid enum variant tag while decoding `{}`, expected 0..{}",
+ ty_name,
+ variants.len()
+ );
+ quote! {
+ ::rustc_serialize::Decoder::read_enum(
+ __decoder,
+ #ty_name,
+ |__decoder| {
+ ::rustc_serialize::Decoder::read_enum_variant(
+ __decoder,
+ &[#names],
+ |__decoder, __variant_idx| {
+ match __variant_idx {
+ #match_inner
+ _ => return ::std::result::Result::Err(
+ ::rustc_serialize::Decoder::error(__decoder, #message)),
+ }
+ })
+ }
+ )
+ }
+ }
+ };
+
+ s.bound_impl(
+ quote!(::rustc_serialize::Decodable<#decoder_ty>),
+ quote! {
+ fn decode(
+ __decoder: &mut #decoder_ty,
+ ) -> ::std::result::Result<Self, <#decoder_ty as ::rustc_serialize::Decoder>::Error> {
+ #decode_body
+ }
+ },
+ )
+}
+
+fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream {
+ let decode_inner_method = if let syn::Type::Reference(_) = field.ty {
+ quote! { ::rustc_middle::ty::codec::RefDecodable::decode }
+ } else {
+ quote! { ::rustc_serialize::Decodable::decode }
+ };
+ let (decode_method, opt_field_name) = if is_struct {
+ let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string());
+ (
+ proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()),
+ quote! { #field_name, },
+ )
+ } else {
+ (
+ proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()),
+ quote! {},
+ )
+ };
+
+ quote! {
+ match ::rustc_serialize::Decoder::#decode_method(
+ __decoder, #opt_field_name #index, #decode_inner_method) {
+ ::std::result::Result::Ok(__res) => __res,
+ ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
+ }
+ }
+}
+
+pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+ s.add_impl_generic(parse_quote! {'tcx});
+ }
+ let encoder_ty = quote! { __E };
+ s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_middle::ty::codec::TyEncoder<'tcx>});
+ s.add_bounds(synstructure::AddBounds::Generics);
+
+ encodable_body(s, encoder_ty, false)
+}
+
+pub fn meta_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
+ s.add_impl_generic(parse_quote! {'tcx});
+ }
+ s.add_impl_generic(parse_quote! { '__a });
+ let encoder_ty = quote! { EncodeContext<'__a, 'tcx> };
+ s.add_bounds(synstructure::AddBounds::Generics);
+
+ encodable_body(s, encoder_ty, true)
+}
+
+pub fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
+ let encoder_ty = quote! { __E };
+ s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder});
+ s.add_bounds(synstructure::AddBounds::Generics);
+
+ encodable_body(s, encoder_ty, false)
+}
+
+fn encodable_body(
+ mut s: synstructure::Structure<'_>,
+ encoder_ty: TokenStream,
+ allow_unreachable_code: bool,
+) -> proc_macro2::TokenStream {
+ if let syn::Data::Union(_) = s.ast().data {
+ panic!("cannot derive on union")
+ }
+
+ s.bind_with(|binding| {
+ // Handle the lack of a blanket reference impl.
+ if let syn::Type::Reference(_) = binding.ast().ty {
+ synstructure::BindStyle::Move
+ } else {
+ synstructure::BindStyle::Ref
+ }
+ });
+
+ let ty_name = s.ast().ident.to_string();
+ let encode_body = match s.variants() {
+ [_] => {
+ let mut field_idx = 0usize;
+ let encode_inner = s.each_variant(|vi| {
+ vi.bindings()
+ .iter()
+ .map(|binding| {
+ let bind_ident = &binding.binding;
+ let field_name = binding
+ .ast()
+ .ident
+ .as_ref()
+ .map_or_else(|| field_idx.to_string(), |i| i.to_string());
+ let result = quote! {
+ match ::rustc_serialize::Encoder::emit_struct_field(
+ __encoder,
+ #field_name,
+ #field_idx,
+ |__encoder|
+ ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+ ) {
+ ::std::result::Result::Ok(()) => (),
+ ::std::result::Result::Err(__err)
+ => return ::std::result::Result::Err(__err),
+ }
+ };
+ field_idx += 1;
+ result
+ })
+ .collect::<TokenStream>()
+ });
+ quote! {
+ ::rustc_serialize::Encoder::emit_struct(__encoder, #ty_name, #field_idx, |__encoder| {
+ ::std::result::Result::Ok(match *self { #encode_inner })
+ })
+ }
+ }
+ _ => {
+ let mut variant_idx = 0usize;
+ let encode_inner = s.each_variant(|vi| {
+ let variant_name = vi.ast().ident.to_string();
+ let mut field_idx = 0usize;
+
+ let encode_fields: TokenStream = vi
+ .bindings()
+ .iter()
+ .map(|binding| {
+ let bind_ident = &binding.binding;
+ let result = quote! {
+ match ::rustc_serialize::Encoder::emit_enum_variant_arg(
+ __encoder,
+ #field_idx,
+ |__encoder|
+ ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+ ) {
+ ::std::result::Result::Ok(()) => (),
+ ::std::result::Result::Err(__err)
+ => return ::std::result::Result::Err(__err),
+ }
+ };
+ field_idx += 1;
+ result
+ })
+ .collect();
+
+ let result = quote! { ::rustc_serialize::Encoder::emit_enum_variant(
+ __encoder,
+ #variant_name,
+ #variant_idx,
+ #field_idx,
+ |__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
+ ) };
+ variant_idx += 1;
+ result
+ });
+ quote! {
+ ::rustc_serialize::Encoder::emit_enum(__encoder, #ty_name, |__encoder| {
+ match *self {
+ #encode_inner
+ }
+ })
+ }
+ }
+ };
+
+ let lints = if allow_unreachable_code {
+ quote! { #![allow(unreachable_code)] }
+ } else {
+ quote! {}
+ };
+
+ s.bound_impl(
+ quote!(::rustc_serialize::Encodable<#encoder_ty>),
+ quote! {
+ fn encode(
+ &self,
+ __encoder: &mut #encoder_ty,
+ ) -> ::std::result::Result<(), <#encoder_ty as ::rustc_serialize::Encoder>::Error> {
+ #lints
+ #encode_body
+ }
+ },
+ )
+}
}
}
- macro_rules! symbols {
+ macro_rules! define_symbols {
() => {
#symbols_stream
[dependencies]
flate2 = "1.0"
libc = "0.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
memmap = "0.7"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
rustc_middle = { path = "../librustc_middle" }
rustc_hir_pretty = { path = "../librustc_hir_pretty" }
rustc_target = { path = "../librustc_target" }
rustc_index = { path = "../librustc_index" }
+rustc_macros = { path = "../librustc_macros" }
rustc_serialize = { path = "../librustc_serialize" }
stable_deref_trait = "1.0.0"
rustc_ast = { path = "../librustc_ast" }
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::{PanicStrategy, TargetTriple};
-use log::{debug, info};
use proc_macro::bridge::client::ProcMacro;
use std::path::Path;
use std::{cmp, env, fs};
+use tracing::{debug, info};
#[derive(Clone)]
pub struct CStore {
let name = tcx.crate_name(cnum);
let src = tcx.used_crate_source(cnum);
if src.dylib.is_some() {
- log::info!("adding dylib: {}", name);
+ tracing::info!("adding dylib: {}", name);
add_library(tcx, cnum, RequireDynamic, &mut formats);
let deps = tcx.dylib_dependency_formats(cnum);
for &(depnum, style) in deps.iter() {
- log::info!("adding {:?}: {}", style, tcx.crate_name(depnum));
+ tracing::info!("adding {:?}: {}", style, tcx.crate_name(depnum));
add_library(tcx, depnum, style, &mut formats);
}
}
&& tcx.dep_kind(cnum) == CrateDepKind::Explicit
{
assert!(src.rlib.is_some() || src.rmeta.is_some());
- log::info!("adding staticlib: {}", tcx.crate_name(cnum));
+ tracing::info!("adding staticlib: {}", tcx.crate_name(cnum));
add_library(tcx, cnum, RequireStatic, &mut formats);
ret[cnum.as_usize() - 1] = Linkage::Static;
}
extern crate proc_macro;
+#[macro_use]
+extern crate rustc_macros;
#[macro_use]
extern crate rustc_middle;
#[macro_use]
use rustc_target::spec::{Target, TargetTriple};
use flate2::read::DeflateDecoder;
-use log::{debug, info, warn};
use std::io::{Read, Result as IoResult, Write};
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::{cmp, fmt, fs};
+use tracing::{debug, info, warn};
#[derive(Clone)]
crate struct CrateLocator<'a> {
use rustc_ast::ast;
use rustc_attr as attr;
use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathTable;
use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc_hir::lang_items;
use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib};
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use rustc_middle::mir::{self, interpret, Body, Promoted};
+use rustc_middle::mir::{self, Body, Promoted};
use rustc_middle::ty::codec::TyDecoder;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::util::common::record_time;
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
+use rustc_serialize::{opaque, Decodable, Decoder};
use rustc_session::Session;
use rustc_span::hygiene::ExpnDataDecodeMode;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{self, hygiene::MacroKind, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
-use log::debug;
use proc_macro::bridge::client::ProcMacro;
use std::cell::Cell;
use std::io;
use std::mem;
use std::num::NonZeroUsize;
use std::path::Path;
+use tracing::debug;
pub use cstore_impl::{provide, provide_extern};
use rustc_span::hygiene::HygieneDecodeContext;
}
}
-impl<'a, 'tcx, T: Decodable> Lazy<T, ()> {
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<T> {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position);
}
}
-impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> {
+impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable<DecodeContext<'a, 'tcx>>> Lazy<[T]> {
fn decode<M: Metadata<'a, 'tcx>>(
self,
metadata: M,
}
impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
+ const CLEAR_CROSS_CRATE: bool = true;
+
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx.expect("missing TyCtxt in DecodeContext")
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] }
}
-}
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T, ()>> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
- self.read_lazy_with_meta(())
+ fn decode_alloc_id(&mut self) -> Result<rustc_middle::mir::interpret::AllocId, Self::Error> {
+ if let Some(alloc_decoding_session) = self.alloc_decoding_session {
+ alloc_decoding_session.decode_alloc_id(self)
+ } else {
+ bug!("Attempting to decode interpret::AllocId without CrateMetadata")
+ }
}
}
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T], usize>> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
- let len = self.read_usize()?;
- if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) }
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for CrateNum {
+ fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<CrateNum, String> {
+ let cnum = CrateNum::from_u32(d.read_u32()?);
+ Ok(d.map_encoded_cnum_to_current(cnum))
}
}
-impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>, usize>> for DecodeContext<'a, 'tcx>
-where
- Option<T>: FixedSizeEncoding,
-{
- fn specialized_decode(&mut self) -> Result<Lazy<Table<I, T>>, Self::Error> {
- let len = self.read_usize()?;
- self.read_lazy_with_meta(len)
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefIndex {
+ fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<DefIndex, String> {
+ Ok(DefIndex::from_u32(d.read_u32()?))
}
}
-impl<'a, 'tcx> SpecializedDecoder<DefId> for DecodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
- let krate = CrateNum::decode(self)?;
- let index = DefIndex::decode(self)?;
-
- Ok(DefId { krate, index })
+impl<'a, 'tcx> FingerprintDecoder for DecodeContext<'a, 'tcx> {
+ fn decode_fingerprint(&mut self) -> Result<Fingerprint, String> {
+ Fingerprint::decode_opaque(&mut self.opaque)
}
}
-impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
- Ok(DefIndex::from_u32(self.read_u32()?))
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for SyntaxContext {
+ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<SyntaxContext, String> {
+ let cdata = decoder.cdata();
+ let sess = decoder.sess.unwrap();
+ let cname = cdata.root.name;
+ rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| {
+ debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
+ Ok(cdata
+ .root
+ .syntax_contexts
+ .get(&cdata, id)
+ .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname))
+ .decode((&cdata, sess)))
+ })
}
}
-impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for DecodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
- Ok(DefId::decode(self)?.expect_local())
- }
-}
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for ExpnId {
+ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<ExpnId, String> {
+ let local_cdata = decoder.cdata();
+ let sess = decoder.sess.unwrap();
+ let expn_cnum = Cell::new(None);
+ let get_ctxt = |cnum| {
+ expn_cnum.set(Some(cnum));
+ if cnum == LOCAL_CRATE {
+ &local_cdata.hygiene_context
+ } else {
+ &local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context
+ }
+ };
-impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
- if let Some(alloc_decoding_session) = self.alloc_decoding_session {
- alloc_decoding_session.decode_alloc_id(self)
- } else {
- bug!("Attempting to decode interpret::AllocId without CrateMetadata")
- }
+ rustc_span::hygiene::decode_expn_id(
+ decoder,
+ ExpnDataDecodeMode::Metadata(get_ctxt),
+ |_this, index| {
+ let cnum = expn_cnum.get().unwrap();
+ // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
+ // are stored in the owning crate, to avoid duplication.
+ let crate_data = if cnum == LOCAL_CRATE {
+ local_cdata
+ } else {
+ local_cdata.cstore.get_crate_data(cnum)
+ };
+ Ok(crate_data
+ .root
+ .expn_data
+ .get(&crate_data, index)
+ .unwrap()
+ .decode((&crate_data, sess)))
+ },
+ )
}
}
-impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
- let tag = u8::decode(self)?;
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
+ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Span, String> {
+ let tag = u8::decode(decoder)?;
if tag == TAG_INVALID_SPAN {
return Ok(DUMMY_SP);
debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN);
- let lo = BytePos::decode(self)?;
- let len = BytePos::decode(self)?;
- let ctxt = SyntaxContext::decode(self)?;
+ let lo = BytePos::decode(decoder)?;
+ let len = BytePos::decode(decoder)?;
+ let ctxt = SyntaxContext::decode(decoder)?;
let hi = lo + len;
- let sess = if let Some(sess) = self.sess {
+ let sess = if let Some(sess) = decoder.sess {
sess
} else {
bug!("Cannot decode Span without Session.")
// we can call `imported_source_files` for the proper crate, and binary search
// through the returned slice using our span.
let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
- self.cdata().imported_source_files(sess)
+ decoder.cdata().imported_source_files(sess)
} else {
// When we encode a proc-macro crate, all `Span`s should be encoded
// with `TAG_VALID_SPAN_LOCAL`
- if self.cdata().root.is_proc_macro_crate() {
+ if decoder.cdata().root.is_proc_macro_crate() {
// Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE
// since we don't have `cnum_map` populated.
- let cnum = u32::decode(self)?;
+ let cnum = u32::decode(decoder)?;
panic!(
"Decoding of crate {:?} tried to access proc-macro dep {:?}",
- self.cdata().root.name,
+ decoder.cdata().root.name,
cnum
);
}
// tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above
- let cnum = CrateNum::decode(self)?;
+ let cnum = CrateNum::decode(decoder)?;
debug!(
"SpecializedDecoder<Span>::specialized_decode: loading source files from cnum {:?}",
cnum
// not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
// We just set it to 0, to ensure that we don't try to access something out
// of bounds for our initial 'guess'
- self.last_source_file_index = 0;
+ decoder.last_source_file_index = 0;
- let foreign_data = self.cdata().cstore.get_crate_data(cnum);
+ let foreign_data = decoder.cdata().cstore.get_crate_data(cnum);
foreign_data.imported_source_files(sess)
};
let source_file = {
// Optimize for the case that most spans within a translated item
// originate from the same source_file.
- let last_source_file = &imported_source_files[self.last_source_file_index];
+ let last_source_file = &imported_source_files[decoder.last_source_file_index];
if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos
{
// Don't try to cache the index for foreign spans,
// as this would require a map from CrateNums to indices
if tag == TAG_VALID_SPAN_LOCAL {
- self.last_source_file_index = index;
+ decoder.last_source_file_index = index;
}
&imported_source_files[index]
}
}
}
-impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
- Fingerprint::decode_opaque(&mut self.opaque)
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+ fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+ ty::codec::RefDecodable::decode(d)
+ }
+}
+
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
+ for Lazy<T>
+{
+ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+ decoder.read_lazy_with_meta(())
}
}
-impl<'a, 'tcx, T> SpecializedDecoder<mir::ClearCrossCrate<T>> for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
+ for Lazy<[T]>
+{
+ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+ let len = decoder.read_usize()?;
+ if len == 0 { Ok(Lazy::empty()) } else { decoder.read_lazy_with_meta(len) }
+ }
+}
+
+impl<'a, 'tcx, I: Idx, T: Decodable<DecodeContext<'a, 'tcx>>> Decodable<DecodeContext<'a, 'tcx>>
+ for Lazy<Table<I, T>>
where
- mir::ClearCrossCrate<T>: UseSpecializedDecodable,
+ Option<T>: FixedSizeEncoding,
{
- #[inline]
- fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
- Ok(mir::ClearCrossCrate::Clear)
+ fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
+ let len = decoder.read_usize()?;
+ decoder.read_lazy_with_meta(len)
}
}
ProcMacro::Bang { .. } => MacroKind::Bang,
}
}
-
-impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
- let cdata = self.cdata();
- let sess = self.sess.unwrap();
- let cname = cdata.root.name;
- rustc_span::hygiene::decode_syntax_context(self, &cdata.hygiene_context, |_, id| {
- debug!("SpecializedDecoder<SyntaxContext>: decoding {}", id);
- Ok(cdata
- .root
- .syntax_contexts
- .get(&cdata, id)
- .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname))
- .decode((&cdata, sess)))
- })
- }
-}
-
-impl<'a, 'tcx> SpecializedDecoder<ExpnId> for DecodeContext<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<ExpnId, Self::Error> {
- let local_cdata = self.cdata();
- let sess = self.sess.unwrap();
- let expn_cnum = Cell::new(None);
- let get_ctxt = |cnum| {
- expn_cnum.set(Some(cnum));
- if cnum == LOCAL_CRATE {
- &local_cdata.hygiene_context
- } else {
- &local_cdata.cstore.get_crate_data(cnum).cdata.hygiene_context
- }
- };
-
- rustc_span::hygiene::decode_expn_id(
- self,
- ExpnDataDecodeMode::Metadata(get_ctxt),
- |_this, index| {
- let cnum = expn_cnum.get().unwrap();
- // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s
- // are stored in the owning crate, to avoid duplication.
- let crate_data = if cnum == LOCAL_CRATE {
- local_cdata
- } else {
- local_cdata.cstore.get_crate_data(cnum)
- };
- Ok(crate_data
- .root
- .expn_data
- .get(&crate_data, index)
- .unwrap()
- .decode((&crate_data, sess)))
- },
- )
- }
-}
use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
use crate::rmeta::*;
-use log::{debug, trace};
use rustc_ast::ast;
-use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fingerprint::{Fingerprint, FingerprintEncoder};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_data_structures::sync::{join, Lrc};
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
};
-use rustc_middle::mir::{self, interpret};
+use rustc_middle::mir::interpret;
use rustc_middle::traits::specialization_graph;
-use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
+use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
-use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
+use rustc_serialize::{opaque, Encodable, Encoder};
use rustc_session::config::CrateType;
use rustc_span::hygiene::{ExpnDataEncodeMode, HygieneEncodeContext};
use rustc_span::source_map::Spanned;
use std::hash::Hash;
use std::num::NonZeroUsize;
use std::path::Path;
+use tracing::{debug, trace};
-struct EncodeContext<'a, 'tcx> {
+pub(super) struct EncodeContext<'a, 'tcx> {
opaque: opaque::Encoder,
tcx: TyCtxt<'tcx>,
}
}
-impl<'a, 'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
- self.emit_lazy_distance(*lazy)
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
+ for Lazy<T>
+{
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ e.emit_lazy_distance(*self)
}
}
-impl<'a, 'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
- self.emit_usize(lazy.meta)?;
- if lazy.meta == 0 {
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
+ for Lazy<[T]>
+{
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ e.emit_usize(self.meta)?;
+ if self.meta == 0 {
return Ok(());
}
- self.emit_lazy_distance(*lazy)
+ e.emit_lazy_distance(*self)
}
}
-impl<'a, 'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'a, 'tcx>
+impl<'a, 'tcx, I: Idx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
+ for Lazy<Table<I, T>>
where
Option<T>: FixedSizeEncoding,
{
- fn specialized_encode(&mut self, lazy: &Lazy<Table<I, T>>) -> Result<(), Self::Error> {
- self.emit_usize(lazy.meta)?;
- self.emit_lazy_distance(*lazy)
- }
-}
-
-impl<'a, 'tcx> SpecializedEncoder<CrateNum> for EncodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
- self.emit_u32(cnum.as_u32())
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ e.emit_usize(self.meta)?;
+ e.emit_lazy_distance(*self)
}
}
-impl<'a, 'tcx> SpecializedEncoder<DefId> for EncodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_encode(&mut self, def_id: &DefId) -> Result<(), Self::Error> {
- let DefId { krate, index } = *def_id;
-
- krate.encode(self)?;
- index.encode(self)
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ s.emit_u32(self.as_u32())
}
}
-impl<'a, 'tcx> SpecializedEncoder<SyntaxContext> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, ctxt: &SyntaxContext) -> Result<(), Self::Error> {
- rustc_span::hygiene::raw_encode_syntax_context(*ctxt, &self.hygiene_ctxt, self)
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
}
}
-impl<'a, 'tcx> SpecializedEncoder<ExpnId> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
rustc_span::hygiene::raw_encode_expn_id(
- *expn,
- &self.hygiene_ctxt,
+ *self,
+ &s.hygiene_ctxt,
ExpnDataEncodeMode::Metadata,
- self,
+ s,
)
}
}
-impl<'a, 'tcx> SpecializedEncoder<DefIndex> for EncodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> {
- self.emit_u32(def_index.as_u32())
- }
-}
-
-impl<'a, 'tcx> SpecializedEncoder<Span> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
- if span.is_dummy() {
- return TAG_INVALID_SPAN.encode(self);
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ if self.is_dummy() {
+ return TAG_INVALID_SPAN.encode(s);
}
- let span = span.data();
+ let span = self.data();
// The Span infrastructure should make sure that this invariant holds:
debug_assert!(span.lo <= span.hi);
- if !self.source_file_cache.0.contains(span.lo) {
- let source_map = self.tcx.sess.source_map();
+ if !s.source_file_cache.0.contains(span.lo) {
+ let source_map = s.tcx.sess.source_map();
let source_file_index = source_map.lookup_source_file_idx(span.lo);
- self.source_file_cache =
+ s.source_file_cache =
(source_map.files()[source_file_index].clone(), source_file_index);
}
- if !self.source_file_cache.0.contains(span.hi) {
+ if !s.source_file_cache.0.contains(span.hi) {
// Unfortunately, macro expansion still sometimes generates Spans
// that malformed in this way.
- return TAG_INVALID_SPAN.encode(self);
+ return TAG_INVALID_SPAN.encode(s);
}
- let source_files = self.required_source_files.as_mut().expect("Already encoded SourceMap!");
+ let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!");
// Record the fact that we need to encode the data for this `SourceFile`
- source_files.insert(self.source_file_cache.1);
+ source_files.insert(s.source_file_cache.1);
// There are two possible cases here:
// 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
// if we're a proc-macro crate.
// This allows us to avoid loading the dependencies of proc-macro crates: all of
// the information we need to decode `Span`s is stored in the proc-macro crate.
- let (tag, lo, hi) = if self.source_file_cache.0.is_imported() && !self.is_proc_macro {
+ let (tag, lo, hi) = if s.source_file_cache.0.is_imported() && !s.is_proc_macro {
// To simplify deserialization, we 'rebase' this span onto the crate it originally came from
// (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
// are relative to the source map information for the 'foreign' crate whose CrateNum
// Span that can be used without any additional trouble.
let external_start_pos = {
// Introduce a new scope so that we drop the 'lock()' temporary
- match &*self.source_file_cache.0.external_src.lock() {
+ match &*s.source_file_cache.0.external_src.lock() {
ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
src => panic!("Unexpected external source {:?}", src),
}
};
- let lo = (span.lo - self.source_file_cache.0.start_pos) + external_start_pos;
- let hi = (span.hi - self.source_file_cache.0.start_pos) + external_start_pos;
+ let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos;
+ let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos;
(TAG_VALID_SPAN_FOREIGN, lo, hi)
} else {
(TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
};
- tag.encode(self)?;
- lo.encode(self)?;
+ tag.encode(s)?;
+ lo.encode(s)?;
// Encode length which is usually less than span.hi and profits more
// from the variable-length integer encoding that we use.
let len = hi - lo;
- len.encode(self)?;
+ len.encode(s)?;
// Don't serialize any `SyntaxContext`s from a proc-macro crate,
// since we don't load proc-macro dependencies during serialization.
// IMPORTANT: If this is ever changed, be sure to update
// `rustc_span::hygiene::raw_encode_expn_id` to handle
// encoding `ExpnData` for proc-macro crates.
- if self.is_proc_macro {
- SyntaxContext::root().encode(self)?;
+ if s.is_proc_macro {
+ SyntaxContext::root().encode(s)?;
} else {
- span.ctxt.encode(self)?;
+ span.ctxt.encode(s)?;
}
if tag == TAG_VALID_SPAN_FOREIGN {
- // This needs to be two lines to avoid holding the `self.source_file_cache`
- // while calling `cnum.encode(self)`
- let cnum = self.source_file_cache.0.cnum;
- cnum.encode(self)?;
+ // This needs to be two lines to avoid holding the `s.source_file_cache`
+ // while calling `cnum.encode(s)`
+ let cnum = s.source_file_cache.0.cnum;
+ cnum.encode(s)?;
}
Ok(())
}
}
-impl<'a, 'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'a, 'tcx> {
- #[inline]
- fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
- self.specialized_encode(&def_id.to_def_id())
+impl<'a, 'tcx> FingerprintEncoder for EncodeContext<'a, 'tcx> {
+ fn encode_fingerprint(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
+ f.encode_opaque(&mut self.opaque)
}
}
-impl<'a, 'b, 'c, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'c, 'tcx>
-where
- &'a ty::TyS<'b>: UseSpecializedEncodable,
-{
- fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
- debug_assert!(self.tcx.lift(ty).is_some());
- let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
- ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
+impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
+ const CLEAR_CROSS_CRATE: bool = true;
+
+ fn position(&self) -> usize {
+ self.opaque.position()
}
-}
-impl<'a, 'b, 'tcx> SpecializedEncoder<ty::Predicate<'b>> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> {
- debug_assert!(self.tcx.lift(predicate).is_some());
- let predicate =
- unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) };
- ty_codec::encode_with_shorthand(self, predicate, |encoder| {
- &mut encoder.predicate_shorthands
- })
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
}
-}
-impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
- let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
- index.encode(self)
+ fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
+ &mut self.type_shorthands
}
-}
-impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'a, 'tcx> {
- fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
- f.encode_opaque(&mut self.opaque)
+ fn predicate_shorthands(&mut self) -> &mut FxHashMap<rustc_middle::ty::Predicate<'tcx>, usize> {
+ &mut self.predicate_shorthands
}
-}
-impl<'a, 'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'a, 'tcx>
-where
- mir::ClearCrossCrate<T>: UseSpecializedEncodable,
-{
- fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
- Ok(())
+ fn encode_alloc_id(
+ &mut self,
+ alloc_id: &rustc_middle::mir::interpret::AllocId,
+ ) -> Result<(), Self::Error> {
+ let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
+
+ index.encode(self)
}
}
-impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
- fn position(&self) -> usize {
- self.opaque.position()
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ (**self).encode(s)
}
}
/// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
-trait EncodeContentsForLazy<T: ?Sized + LazyMeta> {
+trait EncodeContentsForLazy<'a, 'tcx, T: ?Sized + LazyMeta> {
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> T::Meta;
}
-impl<T: Encodable> EncodeContentsForLazy<T> for &T {
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for &T {
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
self.encode(ecx).unwrap()
}
}
-impl<T: Encodable> EncodeContentsForLazy<T> for T {
+impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for T {
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
self.encode(ecx).unwrap()
}
}
-impl<I, T: Encodable> EncodeContentsForLazy<[T]> for I
+impl<'a, 'tcx, I, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, [T]> for I
where
I: IntoIterator,
- I::Item: EncodeContentsForLazy<T>,
+ I::Item: EncodeContentsForLazy<'a, 'tcx, T>,
{
fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> usize {
self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
self.emit_usize(distance)
}
- fn lazy<T: ?Sized + LazyMeta>(&mut self, value: impl EncodeContentsForLazy<T>) -> Lazy<T> {
+ fn lazy<T: ?Sized + LazyMeta>(
+ &mut self,
+ value: impl EncodeContentsForLazy<'a, 'tcx, T>,
+ ) -> Lazy<T> {
let pos = NonZeroUsize::new(self.position()).unwrap();
assert_eq!(self.lazy_state, LazyState::NoNode);
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
};
- let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
+ let enum_id = tcx.hir().local_def_id_to_hir_id(def.did.expect_local());
let enum_vis = &tcx.hir().expect_item(enum_id).vis;
record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
// Variant constructors have the same visibility as the parent enums, unless marked as
// non-exhaustive, in which case they are lowered to `pub(crate)`.
- let enum_id = tcx.hir().as_local_hir_id(def.did.expect_local());
+ let enum_id = tcx.hir().local_def_id_to_hir_id(def.did.expect_local());
let enum_vis = &tcx.hir().expect_item(enum_id).vis;
let mut ctor_vis = ty::Visibility::from_hir(enum_vis, enum_id, tcx);
if variant.is_field_list_non_exhaustive() && ctor_vis == ty::Visibility::Public {
let data = ModData {
reexports: match tcx.module_exports(local_def_id) {
Some(exports) => {
- let hir_map = self.tcx.hir();
+ let hir = self.tcx.hir();
self.lazy(
exports
.iter()
- .map(|export| export.map_id(|id| hir_map.as_local_hir_id(id))),
+ .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))),
)
}
_ => Lazy::empty(),
let def_id = field.did;
debug!("EncodeContext::encode_field({:?})", def_id);
- let variant_id = tcx.hir().as_local_hir_id(variant.def_id.expect_local());
+ let variant_id = tcx.hir().local_def_id_to_hir_id(variant.def_id.expect_local());
let variant_data = tcx.hir().expect_variant_data(variant_id);
record!(self.tables.kind[def_id] <- EntryKind::Field);
is_non_exhaustive: variant.is_field_list_non_exhaustive(),
};
- let struct_id = tcx.hir().as_local_hir_id(adt_def.did.expect_local());
+ let struct_id = tcx.hir().local_def_id_to_hir_id(adt_def.did.expect_local());
let struct_vis = &tcx.hir().expect_item(struct_id).vis;
let mut ctor_vis = ty::Visibility::from_hir(struct_vis, struct_id, tcx);
for field in &variant.fields {
debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let ast_item = tcx.hir().expect_trait_item(hir_id);
let trait_item = tcx.associated_item(def_id);
debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
let tcx = self.tcx;
- let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let ast_item = self.tcx.hir().expect_impl_item(hir_id);
let impl_item = self.tcx.associated_item(def_id);
// NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
// including on the signature, which is inferred in `typeck.
- let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let ty = self.tcx.typeck(def_id).node_type(hir_id);
record!(self.tables.kind[def_id.to_def_id()] <- match ty.kind {
fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
- let id = self.tcx.hir().as_local_hir_id(def_id);
+ let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let body_id = self.tcx.hir().body_owned_by(id);
let const_data = self.encode_rendered_const_for_body(body_id);
let qualifs = self.tcx.mir_const_qualif(def_id);
use std::marker::PhantomData;
use std::num::NonZeroUsize;
+use decoder::DecodeContext;
pub use decoder::{provide, provide_extern};
crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
+use encoder::EncodeContext;
use rustc_span::hygiene::SyntaxContextData;
mod decoder;
}
}
-impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedEncodable for Lazy<T> {}
-impl<T: ?Sized + LazyMeta> rustc_serialize::UseSpecializedDecodable for Lazy<T> {}
-
/// Encoding / decoding state for `Lazy`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum LazyState {
type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
crate struct CrateRoot<'tcx> {
name: Symbol,
triple: TargetTriple,
symbol_mangling_version: SymbolManglingVersion,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
crate struct CrateDep {
pub name: Symbol,
pub hash: Svh,
pub extra_filename: String,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
crate struct TraitImpls {
trait_id: (u32, DefIndex),
impls: Lazy<[(DefIndex, Option<ty::fast_reject::SimplifiedType>)]>,
/// Define `LazyTables` and `TableBuilders` at the same time.
macro_rules! define_tables {
($($name:ident: Table<DefIndex, $T:ty>),+ $(,)?) => {
- #[derive(RustcEncodable, RustcDecodable)]
+ #[derive(MetadataEncodable, MetadataDecodable)]
crate struct LazyTables<'tcx> {
$($name: Lazy!(Table<DefIndex, $T>)),+
}
unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
}
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)]
enum EntryKind {
AnonConst(mir::ConstQualifs, Lazy<RenderedConst>),
Const(mir::ConstQualifs, Lazy<RenderedConst>),
/// Contains a constant which has been rendered to a String.
/// Used by rustdoc.
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
struct RenderedConst(String);
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
struct ModData {
reexports: Lazy<[Export<hir::HirId>]>,
expansion: ExpnId,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
struct FnData {
asyncness: hir::IsAsync,
constness: hir::Constness,
param_names: Lazy<[Ident]>,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
struct VariantData {
ctor_kind: CtorKind,
discr: ty::VariantDiscr,
is_non_exhaustive: bool,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
struct TraitData {
unsafety: hir::Unsafety,
paren_sugar: bool,
specialization_kind: ty::trait_def::TraitSpecializationKind,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
struct ImplData {
polarity: ty::ImplPolarity,
defaultness: hir::Defaultness,
/// Describes whether the container of an associated item
/// is a trait or an impl and whether, in a trait, it has
/// a default, or an in impl, whether it's marked "default".
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable)]
enum AssocContainer {
TraitRequired,
TraitWithDefault,
}
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(MetadataEncodable, MetadataDecodable)]
struct AssocFnData {
fn_data: FnData,
container: AssocContainer,
has_self: bool,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(TyEncodable, TyDecodable)]
struct GeneratorData<'tcx> {
layout: mir::GeneratorLayout<'tcx>,
}
use crate::rmeta::*;
-use log::debug;
use rustc_index::vec::Idx;
-use rustc_serialize::{opaque::Encoder, Encodable};
+use rustc_serialize::opaque::Encoder;
use std::convert::TryInto;
use std::marker::PhantomData;
use std::num::NonZeroUsize;
+use tracing::debug;
/// Helper trait, for encoding to, and decoding from, a fixed number of bytes.
/// Used mainly for Lazy positions and lengths.
// NOTE(eddyb) there could be an impl for `usize`, which would enable a more
// generic `Lazy<T>` impl, but in the general case we might not need / want to
// fit every `usize` in `u32`.
-impl<T: Encodable> FixedSizeEncoding for Option<Lazy<T>> {
+impl<T> FixedSizeEncoding for Option<Lazy<T>> {
fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN);
fn from_bytes(b: &[u8]) -> Self {
}
}
-impl<T: Encodable> FixedSizeEncoding for Option<Lazy<[T]>> {
+impl<T> FixedSizeEncoding for Option<Lazy<[T]>> {
fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2);
fn from_bytes(b: &[u8]) -> Self {
[dependencies]
rustc_arena = { path = "../librustc_arena" }
bitflags = "1.2.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc-rayon-core = "0.3.0"
polonius-engine = "0.12.0"
rustc_apfloat = { path = "../librustc_apfloat" }
macro_rules! arena_types {
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
- [] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout;
+ [] layouts: rustc_target::abi::Layout,
// AdtDef are interned and compared by address
- [] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef;
- [] steal_mir:
- rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>,
- rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>;
- [decode] mir: rustc_middle::mir::Body<$tcx>, rustc_middle::mir::Body<'_x>;
+ [] adt_def: rustc_middle::ty::AdtDef,
+ [] steal_mir: rustc_middle::ty::steal::Steal<rustc_middle::mir::Body<$tcx>>,
+ [decode] mir: rustc_middle::mir::Body<$tcx>,
[] steal_promoted:
rustc_middle::ty::steal::Steal<
rustc_index::vec::IndexVec<
rustc_middle::mir::Body<$tcx>
>
>,
- rustc_middle::ty::steal::Steal<
- rustc_index::vec::IndexVec<
- rustc_middle::mir::Promoted,
- rustc_middle::mir::Body<$tcx>
- >
- >;
[decode] promoted:
rustc_index::vec::IndexVec<
rustc_middle::mir::Promoted,
rustc_middle::mir::Body<$tcx>
>,
- rustc_index::vec::IndexVec<
- rustc_middle::mir::Promoted,
- rustc_middle::mir::Body<'_x>
- >;
- [decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>, rustc_middle::ty::TypeckResults<'_x>;
+ [decode] typeck_results: rustc_middle::ty::TypeckResults<$tcx>,
[decode] borrowck_result:
rustc_middle::mir::BorrowCheckResult<$tcx>,
- rustc_middle::mir::BorrowCheckResult<'_x>;
- [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult, rustc_middle::mir::UnsafetyCheckResult;
- [] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation;
+ [decode] unsafety_check_result: rustc_middle::mir::UnsafetyCheckResult,
+ [] const_allocs: rustc_middle::mir::interpret::Allocation,
// Required for the incremental on-disk cache
- [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet;
- [] region_scope_tree: rustc_middle::middle::region::ScopeTree, rustc_middle::middle::region::ScopeTree;
+ [few] mir_keys: rustc_hir::def_id::DefIdSet,
+ [] region_scope_tree: rustc_middle::middle::region::ScopeTree,
[] dropck_outlives:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx,
rustc_middle::traits::query::DropckOutlivesResult<'tcx>
>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y,
- rustc_middle::traits::query::DropckOutlivesResult<'_z>
- >
- >;
[] normalize_projection_ty:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx,
rustc_middle::traits::query::NormalizationResult<'tcx>
>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y,
- rustc_middle::traits::query::NormalizationResult<'_z>
- >
- >;
[] implied_outlives_bounds:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx,
Vec<rustc_middle::traits::query::OutlivesBound<'tcx>>
>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y,
- Vec<rustc_middle::traits::query::OutlivesBound<'_z>>
- >
- >;
[] type_op_subtype:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, ()>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y, ()>
- >;
[] type_op_normalize_poly_fn_sig:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::PolyFnSig<'_z>>
- >;
[] type_op_normalize_fn_sig:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::FnSig<'_z>>
- >;
[] type_op_normalize_predicate:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::Predicate<'_z>>
- >;
[] type_op_normalize_ty:
rustc_middle::infer::canonical::Canonical<'tcx,
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
>,
- rustc_middle::infer::canonical::Canonical<'_x,
- rustc_middle::infer::canonical::QueryResponse<'_y, &'_z rustc_middle::ty::TyS<'_w>>
- >;
- [few] all_traits: Vec<rustc_hir::def_id::DefId>, Vec<rustc_hir::def_id::DefId>;
- [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, rustc_middle::middle::privacy::AccessLevels;
- [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, rustc_middle::middle::cstore::ForeignModule;
- [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>, Vec<rustc_middle::middle::cstore::ForeignModule>;
- [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>;
- [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation;
- [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>;
- [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
- [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>;
- [] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet;
+ [few] all_traits: Vec<rustc_hir::def_id::DefId>,
+ [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
+ [few] foreign_module: rustc_middle::middle::cstore::ForeignModule,
+ [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>,
+ [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
+ [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
+ [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
+ [] attribute: rustc_ast::ast::Attribute,
+ [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
+ [] hir_id_set: rustc_hir::HirIdSet,
// Interned types
- [] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>;
- [] predicates: rustc_middle::ty::PredicateInner<$tcx>, rustc_middle::ty::PredicateInner<'_x>;
+ [] tys: rustc_middle::ty::TyS<$tcx>,
+ [] predicates: rustc_middle::ty::PredicateInner<$tcx>,
// HIR query types
- [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>;
- [few] hir_definitions: rustc_hir::definitions::Definitions, rustc_hir::definitions::Definitions;
- [] hir_owner: rustc_middle::hir::Owner<$tcx>, rustc_middle::hir::Owner<'_x>;
- [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, rustc_middle::hir::OwnerNodes<'_x>;
+ [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>,
+ [few] hir_definitions: rustc_hir::definitions::Definitions,
+ [] hir_owner: rustc_middle::hir::Owner<$tcx>,
+ [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
// since we need to allocate this type on both the `rustc_hir` arena
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
- [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
+ [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
// This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
- [decode] span: rustc_span::Span, rustc_span::Span;
- [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>, rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>;
+ [decode] span: rustc_span::Span,
+ [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>,
], $tcx);
)
}
$variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
,)*
) => (
- #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash,
- RustcEncodable, RustcDecodable)]
+ #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
#[allow(non_camel_case_types)]
pub enum DepKind {
$($variant),*
}
fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
def_id == hir_id.owner
}
/// within.
pub type ExportMap<Id> = FxHashMap<LocalDefId, Vec<Export<Id>>>;
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct Export<Id> {
/// The name of the target.
pub ident: Ident,
self.tcx.definitions.opt_hir_id_to_local_def_id(hir_id)
}
- #[inline]
- pub fn as_local_hir_id(&self, def_id: LocalDefId) -> HirId {
- self.tcx.definitions.as_local_hir_id(def_id)
- }
-
#[inline]
pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
self.tcx.definitions.local_def_id_to_hir_id(def_id)
}
pub fn get_module(&self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
- let hir_id = self.as_local_hir_id(module);
+ let hir_id = self.local_def_id_to_hir_id(module);
match self.get_entry(hir_id).node {
Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id),
Node::Crate(item) => (&item.module, item.span, hir_id),
}
pub fn get_if_local(&self, id: DefId) -> Option<Node<'hir>> {
- id.as_local().map(|id| self.get(self.as_local_hir_id(id)))
+ id.as_local().map(|id| self.get(self.local_def_id_to_hir_id(id)))
}
pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
}
pub fn span_if_local(&self, id: DefId) -> Option<Span> {
- id.as_local().map(|id| self.span(self.as_local_hir_id(id)))
+ id.as_local().map(|id| self.span(self.local_def_id_to_hir_id(id)))
}
pub fn res_span(&self, res: Res) -> Option<Span> {
pub fn provide(providers: &mut Providers) {
providers.parent_module_from_def_id = |tcx, id| {
let hir = tcx.hir();
- hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id)))
+ hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)))
};
providers.hir_crate = |tcx, _| tcx.untracked_crate;
providers.index_hir = map::index_hir;
providers.hir_module_items = |tcx, id| {
let hir = tcx.hir();
- let module = hir.as_local_hir_id(id);
+ let module = hir.local_def_id_to_hir_id(id);
&tcx.untracked_crate.modules[&module]
};
providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
providers.fn_arg_names = |tcx, id| {
let hir = tcx.hir();
- let hir_id = hir.as_local_hir_id(id.expect_local());
+ let hir_id = hir.local_def_id_to_hir_id(id.expect_local());
if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
} else if let Node::TraitItem(&TraitItem {
use rustc_hir::HirId;
use rustc_target::abi::VariantIdx;
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub enum PlaceBase {
/// A temporary variable
Rvalue,
Upvar(ty::UpvarId),
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub enum ProjectionKind {
/// A dereference of a pointer, reference or `Box<T>` of the given type
Deref,
Subslice,
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub struct Projection<'tcx> {
/// Type after the projection is being applied.
pub ty: Ty<'tcx>,
/// A `Place` represents how a value is located in memory.
///
/// This is an HIR version of `mir::Place`
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub struct Place<'tcx> {
/// The type of the `PlaceBase`
pub base_ty: Ty<'tcx>,
/// A `PlaceWithHirId` represents how a value is located in memory.
///
/// This is an HIR version of `mir::Place`
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub struct PlaceWithHirId<'tcx> {
/// `HirId` of the expression or pattern producing this value.
pub hir_id: HirId,
use crate::ty::{self, BoundVar, List, Region, TyCtxt};
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable;
-use rustc_serialize::UseSpecializedDecodable;
use smallvec::SmallVec;
use std::ops::Index;
/// A "canonicalized" type `V` is one where all free inference
/// variables have been rewritten to "canonical vars". These are
/// numbered starting from 0 in order of first appearance.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, Lift)]
pub struct Canonical<'tcx, V> {
pub max_universe: ty::UniverseIndex,
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo>;
-impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {}
-
/// A set of values corresponding to the canonical variables from some
/// `Canonical`. You can give these values to
/// `canonical_value.substitute` to substitute them into the canonical
/// vectors with the original values that were replaced by canonical
/// variables. You will need to supply it later to instantiate the
/// canonicalized query response.
-#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, Lift)]
pub struct CanonicalVarValues<'tcx> {
pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
/// canonical value. This is sufficient information for code to create
/// a copy of the canonical value in some other inference context,
/// with fresh inference variables replacing the canonical values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
pub struct CanonicalVarInfo {
pub kind: CanonicalVarKind,
}
/// Describes the "kind" of the canonical variable. This is a "kind"
/// in the type-theory sense of the term -- i.e., a "meta" type system
/// that analyzes type-like values.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
pub enum CanonicalVarKind {
/// Some kind of type inference variable.
Ty(CanonicalTyVarKind),
/// 22.) can only be instantiated with integral/float types (e.g.,
/// usize or f32). In order to faithfully reproduce a type, we need to
/// know what set of types a given type variable can be unified with.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
pub enum CanonicalTyVarKind {
/// General type variable `?T` that can be unified with arbitrary types.
General(ty::UniverseIndex),
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate smallvec;
use rustc_session::config::SanitizerSet;
use rustc_span::symbol::Symbol;
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
pub struct CodegenFnAttrs {
pub flags: CodegenFnAttrFlags,
/// Parsed representation of the `#[inline]` attribute
}
bitflags! {
- #[derive(RustcEncodable, RustcDecodable, HashStable)]
+ #[derive(TyEncodable, TyDecodable, HashStable)]
pub struct CodegenFnAttrFlags: u32 {
/// `#[cold]`: a hint to LLVM that this function, when called, is never on
/// the hot path.
/// Where a crate came from on the local filesystem. One of these three options
/// must be non-None.
-#[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, HashStable, Encodable, Decodable)]
pub struct CrateSource {
pub dylib: Option<(PathBuf, PathKind)>,
pub rlib: Option<(PathBuf, PathKind)>,
}
}
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
+#[derive(Encodable, Decodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
#[derive(HashStable)]
pub enum CrateDepKind {
/// A dependency that is only used for its macros.
}
}
-#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
pub enum LibSource {
Some(PathBuf),
MetadataOnly,
}
}
-#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)]
pub enum LinkagePreference {
RequireDynamic,
RequireStatic,
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
pub struct NativeLib {
pub kind: NativeLibKind,
pub name: Option<Symbol>,
pub wasm_import_module: Option<Symbol>,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
pub struct ForeignModule {
pub foreign_items: Vec<DefId>,
pub def_id: DefId,
Path,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
pub struct EncodedMetadata {
pub raw_data: Vec<u8>,
}
/// This is local to the tcx, and is generally relevant to one session.
pub type Dependencies = Vec<(CrateType, DependencyList)>;
-#[derive(Copy, Clone, PartialEq, Debug, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, Encodable, Decodable)]
pub enum Linkage {
NotLinked,
IncludedFromDylib,
/// kind of crate, including cdylibs which export very few things.
/// `Rust` will only be exported if the crate produced is a Rust
/// dylib.
-#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
pub enum SymbolExportLevel {
C,
Rust,
}
}
-#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
pub enum ExportedSymbol<'tcx> {
NonGeneric(DefId),
Generic(DefId, SubstsRef<'tcx>),
// placate the same deriving in `ty::FreeRegion`, but we may want to
// actually attach a more meaningful ordering to scopes than the one
// generated via deriving here.
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Copy, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct Scope {
pub id: hir::ItemLocalId,
}
}
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum ScopeData {
Node,
pub body_expr_count: FxHashMap<hir::BodyId, usize>,
}
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
pub struct YieldData {
/// The `Span` of the yield.
pub span: Span,
/// The origin of a named lifetime definition.
///
/// This is used to prevent the usage of in-band lifetimes in `Fn`/`fn` syntax.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum LifetimeDefOrigin {
// Explicit binders like `fn foo<'a>(x: &'a u8)` or elided like `impl Foo<&u32>`
ExplicitOrElided,
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum Region {
Static,
EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin),
/// A set containing, at most, one known element.
/// If two distinct values are inserted into a set, then it
/// becomes `Many`, which can be used to detect ambiguities.
-#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum Set1<T> {
Empty,
One(T),
UninitBytesAccess,
};
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct Allocation<Tag = (), Extra = ()> {
/// The actual bytes of the allocation.
}
}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Allocation {}
-
/// Byte accessors.
impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
/// Just a small local helper function to avoid a bit of code repetition.
}
/// Relocations.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
pub struct Relocations<Tag = (), Id = AllocId>(SortedMap<Size, (Tag, Id)>);
impl<Tag, Id> Relocations<Tag, Id> {
/// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte
/// is initialized. If it is `false` the byte is uninitialized.
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct InitMask {
blocks: Vec<Block>,
use rustc_target::abi::{Align, Size};
use std::{any::Any, backtrace::Backtrace, fmt, mem};
-#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
pub enum ErrorHandled {
/// Already reported an error for this evaluation, and the compilation is
/// *guaranteed* to fail. Warnings/lints *must not* produce `Reported`.
}
/// Details of why a pointer had to be in-bounds.
-#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
pub enum CheckInAllocMsg {
MemoryAccessTest,
NullPointerTest,
use rustc_data_structures::tiny_list::TinyList;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
-use rustc_serialize::{Decodable, Encodable, Encoder};
+use rustc_serialize::{Decodable, Encodable};
use rustc_target::abi::{Endian, Size};
use crate::mir;
-use crate::ty::codec::TyDecoder;
+use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::subst::GenericArgKind;
use crate::ty::{self, Instance, Ty, TyCtxt};
/// - A constant
/// - A static
/// - A const fn where all arguments (if any) are zero-sized types
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, Lift)]
pub struct GlobalId<'tcx> {
/// For a constant or static, the `Instance` of the item itself.
}
}
-impl rustc_serialize::UseSpecializedEncodable for AllocId {}
-impl rustc_serialize::UseSpecializedDecodable for AllocId {}
-
-#[derive(RustcDecodable, RustcEncodable)]
+#[derive(TyDecodable, TyEncodable)]
enum AllocDiscriminant {
Alloc,
Fn,
Static,
}
-pub fn specialized_encode_alloc_id<'tcx, E: Encoder>(
+pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>(
encoder: &mut E,
tcx: TyCtxt<'tcx>,
alloc_id: AllocId,
let alloc_id = decoder.with_position(pos, |decoder| {
match alloc_kind {
AllocDiscriminant::Alloc => {
- let alloc = <&'tcx Allocation as Decodable>::decode(decoder)?;
+ let alloc = <&'tcx Allocation as Decodable<_>>::decode(decoder)?;
// We already have a reserved `AllocId`.
let alloc_id = alloc_id.unwrap();
trace!("decoded alloc {:?}: {:#?}", alloc_id, alloc);
AllocDiscriminant::Static => {
assert!(alloc_id.is_none());
trace!("creating extern static alloc ID");
- let did = DefId::decode(decoder)?;
+ let did = <DefId as Decodable<D>>::decode(decoder)?;
trace!("decoded static def-ID: {:?}", did);
let alloc_id = decoder.tcx().create_static_alloc(did);
Ok(alloc_id)
/// An allocation in the global (tcx-managed) memory can be either a function pointer,
/// a static, or a "real" allocation with some data in it.
-#[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash, TyDecodable, TyEncodable, HashStable)]
pub enum GlobalAlloc<'tcx> {
/// The alloc ID is used as a function pointer.
Function(Instance<'tcx>),
///
/// `Pointer` is generic over the `Tag` associated with each pointer,
/// which is used to do provenance tracking during execution.
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
pub struct Pointer<Tag = ()> {
pub alloc_id: AllocId,
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
/// array length computations, enum discriminants and the pattern matching logic.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
pub enum ConstValue<'tcx> {
/// Used only for types with `layout::abi::Scalar` ABI and ZSTs.
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
/// of a simple value or a pointer into another `Allocation`
-#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
pub enum Scalar<Tag = ()> {
/// The raw bytes of a simple value.
}
}
-#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, TyEncodable, TyDecodable, HashStable, Hash)]
pub enum ScalarMaybeUninit<Tag = ()> {
Scalar(Scalar<Tag>),
Uninit,
use crate::mir::interpret::{Allocation, ConstValue, GlobalAlloc, Scalar};
use crate::mir::visit::MirVisitable;
use crate::ty::adjustment::PointerCast;
+use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::subst::{Subst, SubstsRef};
/// The various "big phases" that MIR goes through.
///
/// Warning: ordering of variants is significant.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(HashStable)]
pub enum MirPhase {
Build = 0,
}
/// The lowered representation of a single function.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
pub struct Body<'tcx> {
/// A list of basic blocks. References to basic block use a newtyped index type `BasicBlock`
/// that indexes into this vector.
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum Safety {
Safe,
/// Unsafe because of a PushUnsafeBlock
const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
-impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {
+impl<'tcx, E: TyEncoder<'tcx>, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> {
#[inline]
- fn default_encode<E: rustc_serialize::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ if E::CLEAR_CROSS_CRATE {
+ return Ok(());
+ }
+
match *self {
ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
ClearCrossCrate::Set(ref val) => {
}
}
}
-impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {
+impl<'tcx, D: TyDecoder<'tcx>, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> {
#[inline]
- fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
- where
- D: rustc_serialize::Decoder,
- {
+ fn decode(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error> {
+ if D::CLEAR_CROSS_CRATE {
+ return Ok(ClearCrossCrate::Clear);
+ }
+
let discr = u8::decode(d)?;
match discr {
let val = T::decode(d)?;
Ok(ClearCrossCrate::Set(val))
}
- _ => unreachable!(),
+ tag => Err(d.error(&format!("Invalid tag for ClearCrossCrate: {:?}", tag))),
}
}
}
/// Most passes can work with it as a whole, within a single function.
// The unofficial Cranelift backend, at least as of #65828, needs `SourceInfo` to implement `Eq` and
// `Hash`. Please ping @bjorn3 if removing them.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
pub struct SourceInfo {
/// The source span for the AST pertaining to this MIR entity.
pub span: Span,
///////////////////////////////////////////////////////////////////////////
// Borrow kinds
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
ReturnPointer,
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct VarBindingForm<'tcx> {
/// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`?
pub binding_mode: ty::BindingMode,
pub pat_span: Span,
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable)]
pub enum BindingForm<'tcx> {
/// This is a binding for a non-`self` binding, or a `self` that has an explicit type.
Var(VarBindingForm<'tcx>),
}
/// Represents what type of implicit self a function has, if any.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum ImplicitSelfKind {
/// Represents a `fn x(self);`.
Imm,
/// involved in borrow_check errors, e.g., explanations of where the
/// temporaries come from, when their destructors are run, and/or how
/// one might revise the code to satisfy the borrow checker's rules.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct BlockTailInfo {
/// If `true`, then the value resulting from evaluating this tail
/// expression is ignored by the block's expression context.
///
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
/// argument, or the return place.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct LocalDecl<'tcx> {
/// Whether this is a mutable minding (i.e., `let x` or `let mut x`).
///
#[cfg(target_arch = "x86_64")]
static_assert_size!(LocalDecl<'_>, 56);
-/// Extra information about a some locals that's used for diagnostics. (Not
-/// used for non-StaticRef temporaries, the return place, or anonymous function
-/// parameters.)
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+/// Extra information about a some locals that's used for diagnostics and for
+/// classifying variables into local variables, statics, etc, which is needed e.g.
+/// for unsafety checking.
+///
+/// Not used for non-StaticRef temporaries, the return place, or anonymous
+/// function parameters.
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum LocalInfo<'tcx> {
/// A user-defined local variable or function parameter
///
}
/// Debug information pertaining to a user variable.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct VarDebugInfo<'tcx> {
pub name: Symbol,
///////////////////////////////////////////////////////////////////////////
// BasicBlockData and Terminator
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct BasicBlockData<'tcx> {
/// List of statements in this block.
pub statements: Vec<Statement<'tcx>>,
}
/// Information about an assertion failure.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
pub enum AssertKind<O> {
BoundsCheck { len: O, index: O },
Overflow(BinOp, O, O),
ResumedAfterPanic(GeneratorKind),
}
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum InlineAsmOperand<'tcx> {
In {
reg: InlineAsmRegOrRegClass,
///////////////////////////////////////////////////////////////////////////
// Statements
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct Statement<'tcx> {
pub source_info: SourceInfo,
pub kind: StatementKind<'tcx>,
}
}
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum StatementKind<'tcx> {
/// Write the RHS Rvalue to the LHS Place.
Assign(Box<(Place<'tcx>, Rvalue<'tcx>)>),
}
/// Describes what kind of retag is to be performed.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, HashStable)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, HashStable)]
pub enum RetagKind {
/// The initial retag when entering a function.
FnEntry,
}
/// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable, PartialEq)]
+#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, HashStable, PartialEq)]
pub enum FakeReadCause {
/// Inject a fake read of the borrowed input at the end of each guards
/// code.
ForIndex,
}
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct LlvmInlineAsm<'tcx> {
pub asm: hir::LlvmInlineAsmInner,
pub outputs: Box<[Place<'tcx>]>,
/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
pub struct Place<'tcx> {
pub local: Local,
pub projection: &'tcx List<PlaceElem<'tcx>>,
}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}
-
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
pub enum ProjectionElem<V, T> {
Deref,
Field(Field, T),
}
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct SourceScopeData {
pub span: Span,
pub parent_scope: Option<SourceScope>,
pub local_data: ClearCrossCrate<SourceScopeLocalData>,
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct SourceScopeLocalData {
/// An `HirId` with lint levels equivalent to this scope's lint levels.
pub lint_root: hir::HirId,
/// These are values that can appear inside an rvalue. They are intentionally
/// limited to prevent rvalues from being nested in one another.
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub enum Operand<'tcx> {
/// Copy: The value must be available for use afterwards.
///
///////////////////////////////////////////////////////////////////////////
/// Rvalues
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
pub enum Rvalue<'tcx> {
/// x (either a move or copy, depending on type of x)
Use(Operand<'tcx>),
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
}
-#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum CastKind {
Misc,
Pointer(PointerCast),
}
-#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum AggregateKind<'tcx> {
/// The type is of the element
Array(Ty<'tcx>),
Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum BinOp {
/// The `+` operator (addition)
Add,
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum NullOp {
/// Returns the size of a value of that type
SizeOf,
Box,
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum UnOp {
/// The `!` operator for logical inversion
Not,
AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
if let Some(def_id) = def_id.as_local() {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let name = if tcx.sess.opts.debugging_opts.span_free_formats {
let substs = tcx.lift(&substs).unwrap();
format!(
AggregateKind::Generator(def_id, _, _) => ty::tls::with(|tcx| {
if let Some(def_id) = def_id.as_local() {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let name = format!("[generator@{:?}]", tcx.hir().span(hir_id));
let mut struct_fmt = fmt.debug_struct(&name);
/// this does not necessarily mean that they are "==" in Rust -- in
/// particular one must be wary of `NaN`!
-#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub struct Constant<'tcx> {
pub span: Span,
/// The first will lead to the constraint `w: &'1 str` (for some
/// inferred region `'1`). The second will lead to the constraint `w:
/// &'static str`.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct UserTypeProjections {
pub contents: Vec<(UserTypeProjection, Span)>,
}
/// * `let (x, _): T = ...` -- here, the `projs` vector would contain
/// `field[0]` (aka `.0`), indicating that the type of `s` is
/// determined by finding the type of the `.0` field from `T`.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, PartialEq)]
pub struct UserTypeProjection {
pub base: UserTypeAnnotationIndex,
pub projs: Vec<ProjectionKind>,
pub fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option<Span> {
match *self {
MonoItem::Fn(Instance { def, .. }) => {
- def.def_id().as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+ def.def_id().as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}
MonoItem::Static(def_id) => {
- def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+ def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}
MonoItem::GlobalAsm(hir_id) => Some(hir_id),
}
/// Specifies the linkage type for a `MonoItem`.
///
/// See https://llvm.org/docs/LangRef.html#linkage-types for more details about these variants.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum Linkage {
External,
AvailableExternally,
// instances into account. The others don't matter for
// the codegen tests and can even make item order
// unstable.
- InstanceDef::Item(def) => {
- def.did.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
- }
+ InstanceDef::Item(def) => def
+ .did
+ .as_local()
+ .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)),
InstanceDef::VtableShim(..)
| InstanceDef::ReifyShim(..)
| InstanceDef::Intrinsic(..)
}
}
MonoItem::Static(def_id) => {
- def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+ def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}
MonoItem::GlobalAsm(hir_id) => Some(hir_id),
},
}
}
-impl serialize::Encodable for PredecessorCache {
+impl<S: serialize::Encoder> serialize::Encodable<S> for PredecessorCache {
#[inline]
- fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
serialize::Encodable::encode(&(), s)
}
}
-impl serialize::Decodable for PredecessorCache {
+impl<D: serialize::Decoder> serialize::Decodable<D> for PredecessorCache {
#[inline]
- fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
+ fn decode(d: &mut D) -> Result<Self, D::Error> {
serialize::Decodable::decode(d).map(|_v: ()| Self::new())
}
}
use super::{Field, SourceInfo};
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub enum UnsafetyViolationKind {
/// Only permitted in regular `fn`s, prohibited in `const fn`s.
General,
UnsafeFnBorrowPacked,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub enum UnsafetyViolationDetails {
CallToUnsafeFunction,
UseOfInlineAssembly,
}
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub struct UnsafetyViolation {
pub source_info: SourceInfo,
pub lint_root: hir::HirId,
pub details: UnsafetyViolationDetails,
}
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable)]
pub struct UnsafetyCheckResult {
/// Violations that are propagated *upwards* from this function.
pub violations: Lrc<[UnsafetyViolation]>,
}
/// The layout of generator state.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct GeneratorLayout<'tcx> {
/// The type of every local stored inside the generator.
pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
}
}
-#[derive(Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Debug, TyEncodable, TyDecodable, HashStable)]
pub struct BorrowCheckResult<'tcx> {
/// All the opaque types that are restricted to concrete types
/// by this function. Unlike the value in `TypeckResults`, this has
/// Each field corresponds to an implementer of the `Qualif` trait in
/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
/// `Qualif`.
-#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
pub struct ConstQualifs {
pub has_mut_interior: bool,
pub needs_drop: bool,
/// `ReEarlyBound`, `ReFree`). We use these because in a query response we
/// cannot use `ReVar` (which is what we use internally within the rest of the
/// NLL code).
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ClosureRegionRequirements<'tcx> {
/// The number of external regions defined on the closure. In our
/// example above, it would be 3 -- one for `'static`, then `'1`
/// Indicates an outlives-constraint between a type or between two
/// free regions declared on the closure.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct ClosureOutlivesRequirement<'tcx> {
// This region or type ...
pub subject: ClosureOutlivesSubject<'tcx>,
///
/// See also `rustc_mir::borrow_check::constraints`.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
pub enum ConstraintCategory {
Return(ReturnConstraint),
Yield,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
pub enum ReturnConstraint {
Normal,
ClosureUpvar(hir::HirId),
/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
/// that must outlive some region.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum ClosureOutlivesSubject<'tcx> {
/// Subject is a type, typically a type parameter, but could also
/// be a projection. Indicates a requirement like `T: 'a` being
/// Coverage information summarized from a MIR if instrumented for source code coverage (see
/// compiler option `-Zinstrument-coverage`). This information is generated by the
/// `InstrumentCoverage` MIR pass and can be retrieved via the `coverageinfo` query.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable)]
pub struct CoverageInfo {
/// The total number of coverage region counters added to the MIR `Body`.
pub num_counters: u32,
pub use super::query::*;
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, PartialEq)]
pub enum TerminatorKind<'tcx> {
/// Block should have one successor in the graph; we jump there.
Goto { target: BasicBlock },
destination: Option<BasicBlock>,
},
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct Terminator<'tcx> {
pub source_info: SourceInfo,
pub kind: TerminatorKind<'tcx>,
/// per-type-parameter predicates for resolving `T::AssocTy`.
query type_param_predicates(key: (DefId, LocalDefId)) -> ty::GenericPredicates<'tcx> {
desc { |tcx| "computing the bounds for type parameter `{}`", {
- let id = tcx.hir().as_local_hir_id(key.1);
+ let id = tcx.hir().local_def_id_to_hir_id(key.1);
tcx.hir().ty_param_name(id)
}}
}
}
Other {
- query reachable_set(_: CrateNum) -> &'tcx HirIdSet {
+ query reachable_set(_: CrateNum) -> FxHashSet<LocalDefId> {
+ storage(ArenaCacheSelector<'tcx>)
desc { "reachability" }
}
/// ### The type parameter `N`
///
/// See explanation on `ImplSourceUserDefinedData`.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub enum ImplSource<'tcx, N> {
/// ImplSource identifying a particular impl.
ImplSourceUserDefined(ImplSourceUserDefinedData<'tcx, N>),
/// is `Obligation`, as one might expect. During codegen, however, this
/// is `()`, because codegen only requires a shallow resolution of an
/// impl, and nested obligations are satisfied later.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceUserDefinedData<'tcx, N> {
pub impl_def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceGeneratorData<'tcx, N> {
pub generator_def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceClosureData<'tcx, N> {
pub closure_def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceAutoImplData<N> {
pub trait_def_id: DefId,
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceBuiltinData<N> {
pub nested: Vec<N>,
}
-#[derive(PartialEq, Eq, Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceObjectData<'tcx, N> {
/// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
pub nested: Vec<N>,
}
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceFnPointerData<'tcx, N> {
pub fn_ty: Ty<'tcx>,
pub nested: Vec<N>,
}
// FIXME(@lcnr): This should be refactored and merged with other builtin vtables.
-#[derive(Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub struct ImplSourceDiscriminantKindData;
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct ImplSourceTraitAliasData<'tcx, N> {
pub alias_def_id: DefId,
pub substs: SubstsRef<'tcx>,
/// parents of a given specializing impl, which is needed for extracting
/// default items amongst other things. In the simple "chain" rule, every impl
/// has at most one parent.
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
pub struct Graph {
/// All impls have a parent; the "root" impls have as their parent the `def_id`
/// of the trait.
/// Children of a given impl, grouped into blanket/non-blanket varieties as is
/// done in `TraitDef`.
-#[derive(Default, RustcEncodable, RustcDecodable)]
+#[derive(Default, TyEncodable, TyDecodable)]
pub struct Children {
// Impls of a trait (or specializations of a given impl). To allow for
// quicker lookup, the impls are indexed by a simplified version of their
use rustc_hir::lang_items::{DerefMutTraitLangItem, DerefTraitLangItem};
use rustc_macros::HashStable;
-#[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum PointerCast {
/// Go from a fn-item type to a fn-pointer type.
ReifyFnPointer,
/// At some point, of course, `Box` should move out of the compiler, in which
/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct Adjustment<'tcx> {
pub kind: Adjust<'tcx>,
pub target: Ty<'tcx>,
}
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum Adjust<'tcx> {
/// Go from ! to any type.
NeverToAny,
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
/// The target type is `U` in both cases, with the region and mutability
/// being those shared by both the receiver and the returned reference.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub struct OverloadedDeref<'tcx> {
pub region: ty::Region<'tcx>,
pub mutbl: hir::Mutability,
/// new code via two-phase borrows, so we try to limit where we create two-phase
/// capable mutable borrows.
/// See #49434 for tracking.
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AllowTwoPhase {
Yes,
No,
}
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum AutoBorrowMutability {
Mut { allow_two_phase_borrow: AllowTwoPhase },
Not,
}
}
-#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
pub enum AutoBorrow<'tcx> {
/// Converts from T to &T.
Ref(ty::Region<'tcx>, AutoBorrowMutability),
/// This struct can be obtained via the `coerce_impl_info` query.
/// Demanding this struct also has the side-effect of reporting errors
/// for inappropriate impls.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub struct CoerceUnsizedInfo {
/// If this is a "custom coerce" impl, then what kind of custom
/// coercion is it? This applies to impls of `CoerceUnsized` for
pub custom_kind: Option<CustomCoerceUnsized>,
}
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, HashStable)]
pub enum CustomCoerceUnsized {
/// Records the index of the field being coerced.
Struct(usize),
use rustc_hir::BindingAnnotation::*;
use rustc_hir::Mutability;
-#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
+#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Debug, Copy, HashStable)]
pub enum BindingMode {
BindByReference(Mutability),
BindByValue(Mutability),
}
/// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum CastKind {
CoercionCast,
PtrPtrCast,
use crate::arena::ArenaAllocatable;
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
-use crate::mir::{self, interpret::Allocation};
+use crate::mir::{
+ self,
+ interpret::{AllocId, Allocation},
+};
use crate::ty::subst::SubstsRef;
use crate::ty::{self, List, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use rustc_span::Span;
use std::convert::{TryFrom, TryInto};
use std::hash::Hash;
/// This offset is also chosen so that the first byte is never < 0x80.
pub const SHORTHAND_OFFSET: usize = 0x80;
-pub trait EncodableWithShorthand: Clone + Eq + Hash {
- type Variant: Encodable;
+pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
+ type Variant: Encodable<E>;
fn variant(&self) -> &Self::Variant;
}
#[allow(rustc::usage_of_ty_tykind)]
-impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
+impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
type Variant = ty::TyKind<'tcx>;
fn variant(&self) -> &Self::Variant {
&self.kind
}
}
-impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
+impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::Predicate<'tcx> {
type Variant = ty::PredicateKind<'tcx>;
fn variant(&self) -> &Self::Variant {
self.kind()
}
}
-pub trait TyEncoder: Encoder {
- fn position(&self) -> usize;
+pub trait OpaqueEncoder: Encoder {
+ fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder;
+ fn encoder_position(&self) -> usize;
}
-impl TyEncoder for opaque::Encoder {
+impl OpaqueEncoder for rustc_serialize::opaque::Encoder {
+ #[inline]
+ fn opaque(&mut self) -> &mut rustc_serialize::opaque::Encoder {
+ self
+ }
#[inline]
- fn position(&self) -> usize {
+ fn encoder_position(&self) -> usize {
self.position()
}
}
+pub trait TyEncoder<'tcx>: Encoder {
+ const CLEAR_CROSS_CRATE: bool;
+
+ fn tcx(&self) -> TyCtxt<'tcx>;
+ fn position(&self) -> usize;
+ fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
+ fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize>;
+ fn encode_alloc_id(&mut self, alloc_id: &AllocId) -> Result<(), Self::Error>;
+}
+
+/// Trait for decoding to a reference.
+///
+/// This is a separate trait from `Decodable` so that we can implement it for
+/// upstream types, such as `FxHashSet`.
+///
+/// The `TyDecodable` derive macro will use this trait for fields that are
+/// references (and don't use a type alias to hide that).
+///
+/// `Decodable` can still be implemented in cases where `Decodable` is required
+/// by a trait bound.
+pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>> {
+ fn decode(d: &mut D) -> Result<&'tcx Self, D::Error>;
+}
+
/// Encode the given value or a previously cached shorthand.
pub fn encode_with_shorthand<E, T, M>(encoder: &mut E, value: &T, cache: M) -> Result<(), E::Error>
where
- E: TyEncoder,
+ E: TyEncoder<'tcx>,
M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
- T: EncodableWithShorthand,
+ T: EncodableWithShorthand<'tcx, E>,
<T::Variant as DiscriminantKind>::Discriminant: Ord + TryFrom<usize>,
{
- let existing_shorthand = cache(encoder).get(value).cloned();
+ let existing_shorthand = cache(encoder).get(value).copied();
if let Some(shorthand) = existing_shorthand {
return encoder.emit_usize(shorthand);
}
// Check that the shorthand is a not longer than the
// full encoding itself, i.e., it's an obvious win.
if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
- cache(encoder).insert(value.clone(), shorthand);
+ cache(encoder).insert(*value, shorthand);
}
Ok(())
}
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ encode_with_shorthand(e, self, TyEncoder::type_shorthands)
+ }
+}
+
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ encode_with_shorthand(e, self, TyEncoder::predicate_shorthands)
+ }
+}
+
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ e.encode_alloc_id(self)
+ }
+}
+
+macro_rules! encodable_via_deref {
+ ($($t:ty),+) => {
+ $(impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for $t {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
+ (**self).encode(e)
+ }
+ })*
+ }
+}
+
+encodable_via_deref! {
+ &'tcx ty::TypeckResults<'tcx>,
+ ty::Region<'tcx>,
+ &'tcx mir::Body<'tcx>,
+ &'tcx mir::UnsafetyCheckResult,
+ &'tcx mir::BorrowCheckResult<'tcx>
+}
+
pub trait TyDecoder<'tcx>: Decoder {
+ const CLEAR_CROSS_CRATE: bool;
+
fn tcx(&self) -> TyCtxt<'tcx>;
fn peek_byte(&self) -> u8;
fn positioned_at_shorthand(&self) -> bool {
(self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
}
+
+ fn decode_alloc_id(&mut self) -> Result<AllocId, Self::Error>;
}
#[inline]
-pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
+pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>(
decoder: &mut D,
) -> Result<&'tcx T, D::Error>
where
}
#[inline]
-pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
+pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable<D>>(
decoder: &mut D,
) -> Result<&'tcx [T], D::Error>
where
D: TyDecoder<'tcx>,
{
- Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
+ Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder)?))
}
-#[inline]
-pub fn decode_cnum<D>(decoder: &mut D) -> Result<CrateNum, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let cnum = CrateNum::from_u32(u32::decode(decoder)?);
- Ok(decoder.map_encoded_cnum_to_current(cnum))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
+ #[allow(rustc::usage_of_ty_tykind)]
+ fn decode(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> {
+ // Handle shorthands first, if we have an usize > 0x80.
+ if decoder.positioned_at_shorthand() {
+ let pos = decoder.read_usize()?;
+ assert!(pos >= SHORTHAND_OFFSET);
+ let shorthand = pos - SHORTHAND_OFFSET;
+
+ decoder.cached_ty_for_shorthand(shorthand, |decoder| {
+ decoder.with_position(shorthand, Ty::decode)
+ })
+ } else {
+ let tcx = decoder.tcx();
+ Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
+ }
+ }
}
-#[allow(rustc::usage_of_ty_tykind)]
-#[inline]
-pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- // Handle shorthands first, if we have an usize > 0x80.
- if decoder.positioned_at_shorthand() {
- let pos = decoder.read_usize()?;
- assert!(pos >= SHORTHAND_OFFSET);
- let shorthand = pos - SHORTHAND_OFFSET;
-
- decoder.cached_ty_for_shorthand(shorthand, |decoder| {
- decoder.with_position(shorthand, Ty::decode)
- })
- } else {
- let tcx = decoder.tcx();
- Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
+ fn decode(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error> {
+ // Handle shorthands first, if we have an usize > 0x80.
+ let predicate_kind = if decoder.positioned_at_shorthand() {
+ let pos = decoder.read_usize()?;
+ assert!(pos >= SHORTHAND_OFFSET);
+ let shorthand = pos - SHORTHAND_OFFSET;
+
+ decoder.with_position(shorthand, ty::PredicateKind::decode)
+ } else {
+ ty::PredicateKind::decode(decoder)
+ }?;
+ let predicate = decoder.tcx().mk_predicate(predicate_kind);
+ Ok(predicate)
}
}
-#[inline]
-pub fn decode_predicate<D>(decoder: &mut D) -> Result<ty::Predicate<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- // Handle shorthands first, if we have an usize > 0x80.
- if decoder.positioned_at_shorthand() {
- let pos = decoder.read_usize()?;
- assert!(pos >= SHORTHAND_OFFSET);
- let shorthand = pos - SHORTHAND_OFFSET;
-
- decoder.cached_predicate_for_shorthand(shorthand, |decoder| {
- decoder.with_position(shorthand, ty::Predicate::decode)
- })
- } else {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for SubstsRef<'tcx> {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ let len = decoder.read_usize()?;
let tcx = decoder.tcx();
- Ok(tcx.mk_predicate(ty::PredicateKind::decode(decoder)?))
+ Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
}
}
-#[inline]
-pub fn decode_spanned_predicates<D>(
- decoder: &mut D,
-) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let tcx = decoder.tcx();
- Ok(tcx.arena.alloc_from_iter(
- (0..decoder.read_usize()?)
- .map(|_| Decodable::decode(decoder))
- .collect::<Result<Vec<_>, _>>()?,
- ))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ let local: mir::Local = Decodable::decode(decoder)?;
+ let len = decoder.read_usize()?;
+ let projection: &'tcx List<mir::PlaceElem<'tcx>> =
+ decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
+ Ok(mir::Place { local, projection })
+ }
}
-#[inline]
-pub fn decode_substs<D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let len = decoder.read_usize()?;
- let tcx = decoder.tcx();
- Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
+ }
}
-#[inline]
-pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let local: mir::Local = Decodable::decode(decoder)?;
- let len = decoder.read_usize()?;
- let projection: &'tcx List<mir::PlaceElem<'tcx>> =
- decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
- Ok(mir::Place { local, projection })
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ let len = decoder.read_usize()?;
+ let interned: Result<Vec<CanonicalVarInfo>, _> =
+ (0..len).map(|_| Decodable::decode(decoder)).collect();
+ Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice()))
+ }
}
-#[inline]
-pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ decoder.decode_alloc_id()
+ }
}
-#[inline]
-pub fn decode_ty_slice<D>(decoder: &mut D) -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let len = decoder.read_usize()?;
- Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ Ok(ty::SymbolName::new(decoder.tcx(), &decoder.read_str()?))
+ }
}
-#[inline]
-pub fn decode_adt_def<D>(decoder: &mut D) -> Result<&'tcx ty::AdtDef, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let def_id = DefId::decode(decoder)?;
- Ok(decoder.tcx().adt_def(def_id))
+macro_rules! impl_decodable_via_ref {
+ ($($t:ty),+) => {
+ $(impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for $t {
+ fn decode(decoder: &mut D) -> Result<Self, D::Error> {
+ RefDecodable::decode(decoder)
+ }
+ })*
+ }
}
-#[inline]
-pub fn decode_symbol_name<D>(decoder: &mut D) -> Result<ty::SymbolName<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- Ok(ty::SymbolName::new(decoder.tcx(), &decoder.read_str()?))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::AdtDef {
+ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+ let def_id = <DefId as Decodable<D>>::decode(decoder)?;
+ Ok(decoder.tcx().adt_def(def_id))
+ }
}
-#[inline]
-pub fn decode_existential_predicate_slice<D>(
- decoder: &mut D,
-) -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let len = decoder.read_usize()?;
- Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
+ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+ let len = decoder.read_usize()?;
+ Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
+ }
}
-#[inline]
-pub fn decode_canonical_var_infos<D>(decoder: &mut D) -> Result<CanonicalVarInfos<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- let len = decoder.read_usize()?;
- let interned: Result<Vec<CanonicalVarInfo>, _> =
- (0..len).map(|_| Decodable::decode(decoder)).collect();
- Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice()))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::ExistentialPredicate<'tcx>> {
+ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+ let len = decoder.read_usize()?;
+ Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
+ }
}
-#[inline]
-pub fn decode_const<D>(decoder: &mut D) -> Result<&'tcx ty::Const<'tcx>, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::Const<'tcx> {
+ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+ Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
+ }
}
-#[inline]
-pub fn decode_allocation<D>(decoder: &mut D) -> Result<&'tcx Allocation, D::Error>
-where
- D: TyDecoder<'tcx>,
-{
- Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for Allocation {
+ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+ Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
+ }
+}
+
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>, Span)] {
+ fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
+ Ok(decoder.tcx().arena.alloc_from_iter(
+ (0..decoder.read_usize()?)
+ .map(|_| Decodable::decode(decoder))
+ .collect::<Result<Vec<_>, _>>()?,
+ ))
+ }
+}
+
+impl_decodable_via_ref! {
+ &'tcx ty::TypeckResults<'tcx>,
+ &'tcx ty::List<Ty<'tcx>>,
+ &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+ &'tcx Allocation,
+ &'tcx mir::Body<'tcx>,
+ &'tcx mir::UnsafetyCheckResult,
+ &'tcx mir::BorrowCheckResult<'tcx>
}
#[macro_export]
}
}
-#[macro_export]
macro_rules! impl_arena_allocatable_decoder {
([]$args:tt) => {};
([decode $(, $attrs:ident)*]
- [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty, $gen_ty:ty], $tcx:lifetime]) => {
- // FIXME(#36588): These impls are horribly unsound as they allow
- // the caller to pick any lifetime for `'tcx`, including `'static`.
- #[allow(unused_lifetimes)]
- impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a $gen_ty>
- for $DecoderName<$($typaram),*>
- where &'_a $gen_ty: UseSpecializedDecodable
- {
+ [[$name:ident: $ty:ty], $tcx:lifetime]) => {
+ impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for $ty {
#[inline]
- fn specialized_decode(&mut self) -> Result<&'_a $gen_ty, Self::Error> {
- unsafe {
- std::mem::transmute::<
- Result<&$tcx $ty, Self::Error>,
- Result<&'_a $gen_ty, Self::Error>,
- >(decode_arena_allocable(self))
- }
+ fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
+ decode_arena_allocable(decoder)
}
}
- #[allow(unused_lifetimes)]
- impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a [$gen_ty]>
- for $DecoderName<$($typaram),*>
- where &'_a [$gen_ty]: UseSpecializedDecodable
- {
+ impl<$tcx, D: TyDecoder<$tcx>> RefDecodable<$tcx, D> for [$ty] {
#[inline]
- fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> {
- unsafe {
- std::mem::transmute::<
- Result<&$tcx [$ty], Self::Error>,
- Result<&'_a [$gen_ty], Self::Error>,
- >(decode_arena_allocable_slice(self))
- }
+ fn decode(decoder: &mut D) -> Result<&$tcx Self, D::Error> {
+ decode_arena_allocable_slice(decoder)
}
}
};
};
}
-#[macro_export]
macro_rules! impl_arena_allocatable_decoders {
- ($args:tt, [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
+ ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
$(
- impl_arena_allocatable_decoder!($a [$args, [$name: $ty, $gen_ty], $tcx]);
+ impl_arena_allocatable_decoder!($a [[$name: $ty], $tcx]);
)*
}
}
+rustc_hir::arena_types!(impl_arena_allocatable_decoders, [], 'tcx);
+arena_types!(impl_arena_allocatable_decoders, [], 'tcx);
+
#[macro_export]
macro_rules! implement_ty_decoder {
($DecoderName:ident <$($typaram:tt),*>) => {
mod __ty_decoder_impl {
use std::borrow::Cow;
- use std::mem::transmute;
-
- use rustc_serialize::{Decoder, SpecializedDecoder, UseSpecializedDecodable};
-
- use $crate::infer::canonical::CanonicalVarInfos;
- use $crate::ty;
- use $crate::ty::codec::*;
- use $crate::ty::subst::InternalSubsts;
- use rustc_hir::def_id::CrateNum;
-
- use rustc_span::Span;
+ use rustc_serialize::Decoder;
use super::$DecoderName;
impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
type Error = String;
- __impl_decoder_methods! {
+ $crate::__impl_decoder_methods! {
read_nil -> ();
read_u128 -> u128;
self.opaque.error(err)
}
}
-
- // FIXME(#36588): These impls are horribly unsound as they allow
- // the caller to pick any lifetime for `'tcx`, including `'static`.
-
- arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
-
- impl<$($typaram),*> SpecializedDecoder<CrateNum>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
- decode_cnum(self)
- }
- }
-
- impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::TyS<'_y>>
- for $DecoderName<$($typaram),*>
- where &'_x ty::TyS<'_y>: UseSpecializedDecodable
- {
- fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> {
- unsafe {
- transmute::<
- Result<ty::Ty<'tcx>, Self::Error>,
- Result<&'_x ty::TyS<'_y>, Self::Error>,
- >(decode_ty(self))
- }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<ty::Predicate<'_x>>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self) -> Result<ty::Predicate<'_x>, Self::Error> {
- unsafe {
- transmute::<
- Result<ty::Predicate<'tcx>, Self::Error>,
- Result<ty::Predicate<'_x>, Self::Error>,
- >(decode_predicate(self))
- }
- }
- }
-
- impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x [(ty::Predicate<'_y>, Span)]>
- for $DecoderName<$($typaram),*>
- where &'_x [(ty::Predicate<'_y>, Span)]: UseSpecializedDecodable {
- fn specialized_decode(&mut self)
- -> Result<&'_x [(ty::Predicate<'_y>, Span)], Self::Error>
- {
- unsafe { transmute(decode_spanned_predicates(self)) }
- }
- }
-
- impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x InternalSubsts<'_y>>
- for $DecoderName<$($typaram),*>
- where &'_x InternalSubsts<'_y>: UseSpecializedDecodable {
- fn specialized_decode(&mut self) -> Result<&'_x InternalSubsts<'_y>, Self::Error> {
- unsafe { transmute(decode_substs(self)) }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<$crate::mir::Place<'_x>>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(
- &mut self
- ) -> Result<$crate::mir::Place<'_x>, Self::Error> {
- unsafe { transmute(decode_place(self)) }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<ty::Region<'_x>>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self) -> Result<ty::Region<'_x>, Self::Error> {
- unsafe { transmute(decode_region(self)) }
- }
- }
-
- impl<'_x, '_y, '_z, $($typaram),*> SpecializedDecoder<&'_x ty::List<&'_y ty::TyS<'_z>>>
- for $DecoderName<$($typaram),*>
- where &'_x ty::List<&'_y ty::TyS<'_z>>: UseSpecializedDecodable {
- fn specialized_decode(&mut self)
- -> Result<&'_x ty::List<&'_y ty::TyS<'_z>>, Self::Error> {
- unsafe { transmute(decode_ty_slice(self)) }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<&'_x ty::AdtDef>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self) -> Result<&'_x ty::AdtDef, Self::Error> {
- unsafe { transmute(decode_adt_def(self)) }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<ty::SymbolName<'_x>>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self) -> Result<ty::SymbolName<'_x>, Self::Error> {
- unsafe { transmute(decode_symbol_name(self)) }
- }
- }
-
- impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::List<ty::ExistentialPredicate<'_y>>>
- for $DecoderName<$($typaram),*>
- where &'_x ty::List<ty::ExistentialPredicate<'_y>>: UseSpecializedDecodable {
- fn specialized_decode(&mut self)
- -> Result<&'_x ty::List<ty::ExistentialPredicate<'_y>>, Self::Error> {
- unsafe { transmute(decode_existential_predicate_slice(self)) }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<CanonicalVarInfos<'_x>>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(&mut self)
- -> Result<CanonicalVarInfos<'_x>, Self::Error> {
- unsafe { transmute(decode_canonical_var_infos(self)) }
- }
- }
-
- impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x $crate::ty::Const<'_y>>
- for $DecoderName<$($typaram),*>
- where &'_x $crate::ty::Const<'_y>: UseSpecializedDecodable {
- fn specialized_decode(&mut self) -> Result<&'_x ty::Const<'_y>, Self::Error> {
- unsafe { transmute(decode_const(self)) }
- }
- }
-
- impl<'_x, $($typaram),*> SpecializedDecoder<&'_x $crate::mir::interpret::Allocation>
- for $DecoderName<$($typaram),*> {
- fn specialized_decode(
- &mut self
- ) -> Result<&'_x $crate::mir::interpret::Allocation, Self::Error> {
- unsafe { transmute(decode_allocation(self)) }
- }
- }
}
- };
+ }
}
pub use kind::*;
/// Typed constant value.
-#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
#[derive(HashStable)]
pub struct Const<'tcx> {
pub ty: Ty<'tcx>,
ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => {
// Find the name and index of the const parameter by indexing the generics of
// the parent item and construct a `ParamConst`.
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item_id = tcx.hir().get_parent_node(hir_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id.to_def_id());
use rustc_target::abi::Size;
/// Represents a constant in Rust.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
pub enum ConstKind<'tcx> {
/// A const generic parameter.
/// A placeholder for a const which could not be computed; this is
/// propagated to avoid useless error messages.
- Error(ty::sty::DelaySpanBugEmitted),
+ Error(ty::DelaySpanBugEmitted),
}
#[cfg(target_arch = "x86_64")]
}
/// An inference variable for a const, for use in const generics.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
pub enum InferConst<'tcx> {
/// Infer the value of the const.
use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::traits;
+use crate::ty::query::{self, TyCtxtAt};
use crate::ty::steal::Steal;
use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
use crate::ty::TyKind::*;
use crate::ty::{
- self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
- DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
- IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
+ self, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid, DefIdTree,
+ ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntVar,
+ IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateInner, PredicateKind,
ProjectionTy, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar,
TyVid, TypeAndMut,
};
use std::ops::{Bound, Deref};
use std::sync::Arc;
+/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
+/// except through `tcx.err*()`, which are in this module.
+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
+#[derive(TyEncodable, TyDecodable, HashStable)]
+pub struct DelaySpanBugEmitted(());
+
type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
pub struct CtxtInterners<'tcx> {
}
/// All information necessary to validate and reveal an `impl Trait`.
-#[derive(RustcEncodable, RustcDecodable, Debug, HashStable)]
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
pub struct ResolvedOpaqueTy<'tcx> {
/// The revealed type as seen by this function.
pub concrete_type: Ty<'tcx>,
///
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
+#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
pub struct GeneratorInteriorTypeCause<'tcx> {
/// Type of the captured binding.
pub ty: Ty<'tcx>,
pub expr: Option<hir::HirId>,
}
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(TyEncodable, TyDecodable, Debug)]
pub struct TypeckResults<'tcx> {
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
pub hir_owner: LocalDefId,
pub type CanonicalUserTypeAnnotations<'tcx> =
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable, Lift)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
pub user_ty: CanonicalUserType<'tcx>,
pub span: Span,
/// A user-given type annotation attached to a constant. These arise
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
-#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
pub enum UserType<'tcx> {
Ty(Ty<'tcx>),
#[track_caller]
pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
self.sess.delay_span_bug(span, msg);
- self.mk_ty(Error(super::sty::DelaySpanBugEmitted(())))
+ self.mk_ty(Error(DelaySpanBugEmitted(())))
}
/// Like `err` but for constants.
pub fn const_error(self, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
self.sess
.delay_span_bug(DUMMY_SP, "ty::ConstKind::Error constructed but no error reported.");
- self.mk_const(ty::Const {
- val: ty::ConstKind::Error(super::sty::DelaySpanBugEmitted(())),
- ty,
- })
+ self.mk_const(ty::Const { val: ty::ConstKind::Error(DelaySpanBugEmitted(())), ty })
}
pub fn consider_optimizing<T: Fn() -> String>(&self, msg: T) -> bool {
pub fn serialize_query_result_cache<E>(self, encoder: &mut E) -> Result<(), E::Error>
where
- E: ty::codec::TyEncoder,
+ E: ty::codec::OpaqueEncoder,
{
self.queries.on_disk_cache.serialize(self, encoder)
}
_ => return None, // not a free region
};
- let hir_id = self.hir().as_local_hir_id(suitable_region_binding_scope);
+ let hir_id = self.hir().local_def_id_to_hir_id(suitable_region_binding_scope);
let is_impl_item = match self.hir().find(hir_id) {
Some(Node::Item(..) | Node::TraitItem(..)) => false,
Some(Node::ImplItem(..)) => {
&self,
scope_def_id: LocalDefId,
) -> Vec<&'tcx hir::Ty<'tcx>> {
- let hir_id = self.hir().as_local_hir_id(scope_def_id);
+ let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let hir_output = match self.hir().get(hir_id) {
Node::Item(hir::Item {
kind:
pub fn return_type_impl_trait(&self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
// HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
- let hir_id = self.hir().as_local_hir_id(scope_def_id);
+ let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
match self.hir().get(hir_id) {
Node::Item(item) => {
match item.kind {
}
}
+impl TyCtxtAt<'tcx> {
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
+ #[track_caller]
+ pub fn ty_error(self) -> Ty<'tcx> {
+ self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
+ }
+
+ /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+ /// ensure it gets used.
+ #[track_caller]
+ pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
+ self.tcx.ty_error_with_message(self.span, msg)
+ }
+}
+
pub trait InternAs<T: ?Sized, R> {
type Output;
fn intern_with<F>(self, f: F) -> Self::Output
.type_param(p, self)
.def_id
.as_local()
- .map(|id| hir.as_local_hir_id(id))
+ .map(|id| hir.local_def_id_to_hir_id(id))
.and_then(|id| self.hir().find(self.hir().get_parent_node(id)))
.as_ref()
.and_then(|node| node.generics())
body_owner_def_id: DefId,
found: Ty<'tcx>,
) -> bool {
- let hir_id = match body_owner_def_id.as_local().map(|id| self.hir().as_local_hir_id(id)) {
- Some(hir_id) => hir_id,
- None => return false,
- };
+ let hir_id =
+ match body_owner_def_id.as_local().map(|id| self.hir().local_def_id_to_hir_id(id)) {
+ Some(hir_id) => hir_id,
+ None => return false,
+ };
// When `body_owner` is an `impl` or `trait` item, look in its associated types for
// `expected` and point at it.
let parent_id = self.hir().get_parent_item(hir_id);
/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
/// keys (in which case we use a DefPathHash as id-type) but in the general case
/// the non-stable but fast to construct DefId-version is the better choice.
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
pub enum SimplifiedTypeGen<D>
where
D: Copy + Debug + Ord + Eq,
/// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
/// simply couples a potentially generic `InstanceDef` with some substs, and codegen and const eval
/// will do all required substitution as they run.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, Lift)]
pub struct Instance<'tcx> {
pub def: InstanceDef<'tcx>,
pub substs: SubstsRef<'tcx>,
}
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum InstanceDef<'tcx> {
/// A user-defined callable item.
///
/// - For a slice, this is the length.
pub const FAT_PTR_EXTRA: usize = 1;
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)]
pub enum LayoutError<'tcx> {
Unknown(Ty<'tcx>),
SizeOverflow(Ty<'tcx>),
}
}
-impl<T: Encodable> Encodable for List<T> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
#[inline]
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+ (**self).encode(s)
+ }
+}
+
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for &List<T> {
+ #[inline]
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::{CanonicalPolyFnSig, FnSig, GenSig, PolyFnSig, PolyGenSig};
pub use self::sty::{ClosureSubsts, GeneratorSubsts, TypeAndMut, UpvarSubsts};
+pub use self::sty::{ClosureSubstsParts, GeneratorSubstsParts};
pub use self::sty::{ConstVid, FloatVid, IntVid, RegionVid, TyVid};
pub use self::sty::{ExistentialPredicate, InferTy, ParamConst, ParamTy, ProjectionTy};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
pub use self::context::{tls, FreeRegionInfo, TyCtxt};
pub use self::context::{
- CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
- UserType, UserTypeAnnotationIndex,
+ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
+ DelaySpanBugEmitted, ResolvedOpaqueTy, UserType, UserTypeAnnotationIndex,
};
pub use self::context::{
CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckResults,
pub use self::consts::{Const, ConstInt, ConstKind, InferConst};
+pub mod _match;
pub mod adjustment;
pub mod binding;
pub mod cast;
-#[macro_use]
pub mod codec;
-pub mod _match;
mod erase_regions;
pub mod error;
pub mod fast_reject;
pub predicates: Vec<Predicate<'tcx>>,
}
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
pub enum Visibility {
/// Visible everywhere (including in other crates).
Public,
}
}
-#[derive(Copy, Clone, PartialEq, RustcDecodable, RustcEncodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, TyDecodable, TyEncodable, HashStable)]
pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
#[rustc_diagnostic_item = "Ty"]
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
-impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for Ty<'tcx> {}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<Ty<'tcx>> {}
-
pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>;
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub struct UpvarPath {
pub hir_id: hir::HirId,
}
/// Upvars do not get their own `NodeId`. Instead, we use the pair of
/// the original var ID (that is, the root variable that is referenced
/// by the upvar) and the ID of the closure expression.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
pub struct UpvarId {
pub var_path: UpvarPath,
pub closure_expr_id: LocalDefId,
}
-#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, HashStable)]
+#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
ImmBorrow,
/// Information describing the capture of an upvar. This is computed
/// during `typeck`, specifically by `regionck`.
-#[derive(PartialEq, Clone, Debug, Copy, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
pub enum UpvarCapture<'tcx> {
/// Upvar is captured by value. This is always true when the
/// closure is labeled `move`, but can also be true in other cases
ByRef(UpvarBorrow<'tcx>),
}
-#[derive(PartialEq, Clone, Copy, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)]
pub struct UpvarBorrow<'tcx> {
/// The kind of borrow: by-ref upvars have access to shared
/// immutable borrows, which are not part of the normal language
}
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum GenericParamDefKind {
Lifetime,
Type {
}
}
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct GenericParamDef {
pub name: Symbol,
pub def_id: DefId,
///
/// The ordering of parameters is the same as in `Subst` (excluding child generics):
/// `Self` (optionally), `Lifetime` params..., `Type` params...
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct Generics {
pub parent: Option<DefId>,
pub parent_count: usize,
}
/// Bounds on generics.
-#[derive(Copy, Clone, Default, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
pub predicates: &'tcx [(Predicate<'tcx>, Span)],
inner: &'tcx PredicateInner<'tcx>,
}
-impl rustc_serialize::UseSpecializedEncodable for Predicate<'_> {}
-impl rustc_serialize::UseSpecializedDecodable for Predicate<'_> {}
-
impl<'tcx> PartialEq for Predicate<'tcx> {
fn eq(&self, other: &Self) -> bool {
// `self.kind` is always interned.
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub enum PredicateKind<'tcx> {
/// `for<'a>: ...`
Atom(PredicateAtom<'tcx>),
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub enum PredicateAtom<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,
}
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B`
pub type PolyOutlivesPredicate<A, B> = ty::Binder<OutlivesPredicate<A, B>>;
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<RegionOutlivesPredicate<'tcx>>;
pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<TypeOutlivesPredicate<'tcx>>;
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct SubtypePredicate<'tcx> {
pub a_is_expected: bool,
/// equality between arbitrary types. Processing an instance of
/// Form #2 eventually yields one of these `ProjectionPredicate`
/// instances to normalize the LHS.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct ProjectionPredicate<'tcx> {
pub projection_ty: ProjectionTy<'tcx>,
/// basically a name -- distinct bound regions within the same
/// universe are just two regions with an unknown relationship to one
/// another.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
pub struct Placeholder<T> {
pub universe: UniverseIndex,
pub name: T,
/// a.foo::<7>();
/// }
/// ```
-#[derive(Copy, Clone, Debug, TypeFoldable, Lift, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(Hash, HashStable)]
pub struct WithOptConstParam<T> {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub enum VariantDiscr {
/// Explicit value for this variant, i.e., `X = 123`.
/// The `DefId` corresponds to the embedded constant.
}
}
-impl<'tcx> rustc_serialize::UseSpecializedEncodable for &'tcx AdtDef {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for AdtDef {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
self.did.encode(s)
}
}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx AdtDef {}
-
impl<'a> HashStable<StableHashingContext<'a>> for AdtDef {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
thread_local! {
}
bitflags! {
- #[derive(RustcEncodable, RustcDecodable, Default, HashStable)]
+ #[derive(TyEncodable, TyDecodable, Default, HashStable)]
pub struct ReprFlags: u8 {
const IS_C = 1 << 0;
const IS_SIMD = 1 << 1;
}
/// Represents the repr options provided by the user,
-#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Default, HashStable)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Default, HashStable)]
pub struct ReprOptions {
pub int: Option<attr::IntType>,
pub align: Option<Align>,
///
/// You can get the environment type of a closure using
/// `tcx.closure_env_ty()`.
-#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum ClosureKind {
// Warning: Ordering is significant here! The ordering is chosen
pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
def_id
.as_local()
- .and_then(|def_id| self.hir().get(self.hir().as_local_hir_id(def_id)).ident())
+ .and_then(|def_id| self.hir().get(self.hir().local_def_id_to_hir_id(def_id)).ident())
}
pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
let is_associated_item = if let Some(def_id) = def_id.as_local() {
- match self.hir().get(self.hir().as_local_hir_id(def_id)) {
+ match self.hir().get(self.hir().local_def_id_to_hir_id(def_id)) {
Node::TraitItem(_) | Node::ImplItem(_) => true,
_ => false,
}
/// Gets the attributes of a definition.
pub fn get_attrs(self, did: DefId) -> Attributes<'tcx> {
if let Some(did) = did.as_local() {
- self.hir().attrs(self.hir().as_local_hir_id(did))
+ self.hir().attrs(self.hir().local_def_id_to_hir_id(did))
} else {
self.item_attrs(did)
}
/// with the name of the crate containing the impl.
pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
if let Some(impl_did) = impl_did.as_local() {
- let hir_id = self.hir().as_local_hir_id(impl_did);
+ let hir_id = self.hir().local_def_id_to_hir_id(impl_did);
Ok(self.hir().span(hir_id))
} else {
Err(self.crate_name(impl_did.krate))
/// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
pub fn is_impl_trait_defn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
if let Some(def_id) = def_id.as_local() {
- if let Node::Item(item) = tcx.hir().get(tcx.hir().as_local_hir_id(def_id)) {
+ if let Node::Item(item) = tcx.hir().get(tcx.hir().local_def_id_to_hir_id(def_id)) {
if let hir::ItemKind::OpaqueTy(ref opaque_ty) = item.kind {
return opaque_ty.impl_trait_fn;
}
pub inherent_impls: DefIdMap<Vec<DefId>>,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)]
pub struct SymbolName<'tcx> {
/// `&str` gives a consistent ordering, which ensures reproducible builds.
pub name: &'tcx str,
fmt::Display::fmt(&self.name, fmt)
}
}
-
-impl<'tcx> rustc_serialize::UseSpecializedEncodable for SymbolName<'tcx> {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_str(self.name)
- }
-}
-
-// The decoding takes place in `decode_symbol_name()`.
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for SymbolName<'tcx> {}
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
- let hir_id = self.tcx().hir().as_local_hir_id(did);
+ let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
let span = self.tcx().hir().span(hir_id);
p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
- let hir_id = self.tcx().hir().as_local_hir_id(did);
+ let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
if self.tcx().sess.opts.debugging_opts.span_free_formats {
p!(write("@"), print_def_path(did.to_def_id(), substs));
} else {
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::lang_items::{LangItem, LanguageItems};
-use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate};
+use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::utils::NativeLibKind;
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
-use crate::mir::interpret;
use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
+use crate::mir::{self, interpret};
+use crate::ty::codec::{OpaqueEncoder, RefDecodable, TyDecoder, TyEncoder};
use crate::ty::context::TyCtxt;
use crate::ty::{self, Ty};
-use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, FingerprintEncoder};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_index::vec::{Idx, IndexVec};
-use rustc_serialize::{
- opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder,
- UseSpecializedDecodable, UseSpecializedEncodable,
-};
+use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
use rustc_session::{CrateDisambiguator, Session};
use rustc_span::hygiene::{
ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
SyntaxContext, SyntaxContextData,
};
use rustc_span::source_map::{SourceMap, StableSourceFileId};
-use rustc_span::symbol::Ident;
use rustc_span::CachingSourceMapView;
use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP};
use std::mem;
}
// This type is used only for serialization and deserialization.
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
struct Footer {
file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
type EncodedDiagnosticsIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
type EncodedDiagnostics = Vec<Diagnostic>;
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
struct SourceFileIndex(u32);
-#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
struct AbsoluteBytePos(u32);
impl AbsoluteBytePos {
pub fn serialize<'tcx, E>(&self, tcx: TyCtxt<'tcx>, encoder: &mut E) -> Result<(), E::Error>
where
- E: TyEncoder,
+ E: OpaqueEncoder,
{
// Serializing the `DepGraph` should not modify it.
tcx.dep_graph.with_ignore(|| {
// Encode the position of the footer as the last 8 bytes of the
// file so we know where to look for it.
- IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?;
+ IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder.opaque())?;
// DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address
// of the footer must be the last thing in the data stream.
/// Returns the cached query result if there is something in the cache for
/// the given `SerializedDepNodeIndex`; otherwise returns `None`.
- pub fn try_load_query_result<T>(
+ crate fn try_load_query_result<'tcx, T>(
&self,
- tcx: TyCtxt<'_>,
+ tcx: TyCtxt<'tcx>,
dep_node_index: SerializedDepNodeIndex,
) -> Option<T>
where
- T: Decodable,
+ T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
self.load_indexed(tcx, dep_node_index, &self.query_result_index, "query result")
}
debug_tag: &'static str,
) -> Option<T>
where
- T: Decodable,
+ T: for<'a> Decodable<CacheDecoder<'a, 'tcx>>,
{
let pos = index.get(&dep_node_index).cloned()?;
})
}
- fn with_decoder<'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
+ fn with_decoder<'a, 'tcx, T, F: FnOnce(&mut CacheDecoder<'sess, 'tcx>) -> T>(
&'sess self,
tcx: TyCtxt<'tcx>,
pos: AbsoluteBytePos,
f: F,
) -> T
where
- T: Decodable,
+ T: Decodable<CacheDecoder<'a, 'tcx>>,
{
let cnum_map =
self.cnum_map.get_or_init(|| Self::compute_cnum_map(tcx, &self.prev_cnums[..]));
/// A decoder that can read from the incr. comp. cache. It is similar to the one
/// we use for crate metadata decoding in that it can rebase spans and eventually
/// will also handle things that contain `Ty` instances.
-struct CacheDecoder<'a, 'tcx> {
+crate struct CacheDecoder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
opaque: opaque::Decoder<'a>,
source_map: &'a SourceMap,
// tag matches and the correct amount of bytes was read.
fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> Result<V, D::Error>
where
- T: Decodable + Eq + ::std::fmt::Debug,
- V: Decodable,
+ T: Decodable<D> + Eq + ::std::fmt::Debug,
+ V: Decodable<D>,
D: DecoderWithPosition,
{
let start_pos = decoder.position();
}
impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
+ const CLEAR_CROSS_CRATE: bool = false;
+
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
self.cnum_map[cnum].unwrap_or_else(|| bug!("could not find new `CrateNum` for {:?}", cnum))
}
+
+ fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
+ let alloc_decoding_session = self.alloc_decoding_session;
+ alloc_decoding_session.decode_alloc_id(self)
+ }
}
-implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
+crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
-impl<'a, 'tcx> SpecializedDecoder<SyntaxContext> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<SyntaxContext, Self::Error> {
- let syntax_contexts = self.syntax_contexts;
- rustc_span::hygiene::decode_syntax_context(self, self.hygiene_context, |this, id| {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
+ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ let syntax_contexts = decoder.syntax_contexts;
+ rustc_span::hygiene::decode_syntax_context(decoder, decoder.hygiene_context, |this, id| {
// This closure is invoked if we haven't already decoded the data for the `SyntaxContext` we are deserializing.
// We look up the position of the associated `SyntaxData` and decode it.
let pos = syntax_contexts.get(&id).unwrap();
}
}
-impl<'a, 'tcx> SpecializedDecoder<ExpnId> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<ExpnId, Self::Error> {
- let expn_data = self.expn_data;
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
+ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ let expn_data = decoder.expn_data;
rustc_span::hygiene::decode_expn_id(
- self,
- ExpnDataDecodeMode::incr_comp(self.hygiene_context),
+ decoder,
+ ExpnDataDecodeMode::incr_comp(decoder.hygiene_context),
|this, index| {
// This closure is invoked if we haven't already decoded the data for the `ExpnId` we are deserializing.
// We look up the position of the associated `ExpnData` and decode it.
}
}
-impl<'a, 'tcx> SpecializedDecoder<interpret::AllocId> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<interpret::AllocId, Self::Error> {
- let alloc_decoding_session = self.alloc_decoding_session;
- alloc_decoding_session.decode_alloc_id(self)
- }
-}
-
-impl<'a, 'tcx> SpecializedDecoder<Span> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
- let tag: u8 = Decodable::decode(self)?;
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
+ fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ let tag: u8 = Decodable::decode(decoder)?;
if tag == TAG_INVALID_SPAN {
return Ok(DUMMY_SP);
debug_assert_eq!(tag, TAG_VALID_SPAN);
}
- let file_lo_index = SourceFileIndex::decode(self)?;
- let line_lo = usize::decode(self)?;
- let col_lo = BytePos::decode(self)?;
- let len = BytePos::decode(self)?;
- let ctxt = SyntaxContext::decode(self)?;
+ let file_lo_index = SourceFileIndex::decode(decoder)?;
+ let line_lo = usize::decode(decoder)?;
+ let col_lo = BytePos::decode(decoder)?;
+ let len = BytePos::decode(decoder)?;
+ let ctxt = SyntaxContext::decode(decoder)?;
- let file_lo = self.file_index_to_file(file_lo_index);
+ let file_lo = decoder.file_index_to_file(file_lo_index);
let lo = file_lo.lines[line_lo - 1] + col_lo;
let hi = lo + len;
}
}
-impl<'a, 'tcx> SpecializedDecoder<Ident> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Ident, Self::Error> {
- // FIXME: Handle hygiene in incremental
- bug!("Trying to decode Ident for incremental");
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ let cnum = CrateNum::from_u32(u32::decode(d)?);
+ Ok(d.map_encoded_cnum_to_current(cnum))
}
}
// `DefIndex` that is not contained in a `DefId`. Such a case would be problematic
// because we would not know how to transform the `DefIndex` to the current
// context.
-impl<'a, 'tcx> SpecializedDecoder<DefIndex> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<DefIndex, Self::Error> {
- bug!("trying to decode `DefIndex` outside the context of a `DefId`")
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefIndex {
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<DefIndex, String> {
+ Err(d.error("trying to decode `DefIndex` outside the context of a `DefId`"))
}
}
// Both the `CrateNum` and the `DefIndex` of a `DefId` can change in between two
// compilation sessions. We use the `DefPathHash`, which is stable across
// sessions, to map the old `DefId` to the new one.
-impl<'a, 'tcx> SpecializedDecoder<DefId> for CacheDecoder<'a, 'tcx> {
- #[inline]
- fn specialized_decode(&mut self) -> Result<DefId, Self::Error> {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
// Load the `DefPathHash` which is was we encoded the `DefId` as.
- let def_path_hash = DefPathHash::decode(self)?;
+ let def_path_hash = DefPathHash::decode(d)?;
// Using the `DefPathHash`, we can lookup the new `DefId`.
- Ok(self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
+ Ok(d.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash])
}
}
-impl<'a, 'tcx> SpecializedDecoder<LocalDefId> for CacheDecoder<'a, 'tcx> {
- #[inline]
- fn specialized_decode(&mut self) -> Result<LocalDefId, Self::Error> {
- Ok(DefId::decode(self)?.expect_local())
+impl<'a, 'tcx> FingerprintDecoder for CacheDecoder<'a, 'tcx> {
+ fn decode_fingerprint(&mut self) -> Result<Fingerprint, Self::Error> {
+ Fingerprint::decode_opaque(&mut self.opaque)
}
}
-impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx> {
- fn specialized_decode(&mut self) -> Result<Fingerprint, Self::Error> {
- Fingerprint::decode_opaque(&mut self.opaque)
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ RefDecodable::decode(d)
+ }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+ for &'tcx IndexVec<mir::Promoted, mir::Body<'tcx>>
+{
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ RefDecodable::decode(d)
+ }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ RefDecodable::decode(d)
+ }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+ for &'tcx [rustc_ast::ast::InlineAsmTemplatePiece]
+{
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ RefDecodable::decode(d)
+ }
+}
+
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Span] {
+ fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+ RefDecodable::decode(d)
}
}
//- ENCODING -------------------------------------------------------------------
/// An encoder that can write the incr. comp. cache.
-struct CacheEncoder<'a, 'tcx, E: ty_codec::TyEncoder> {
+struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
tcx: TyCtxt<'tcx>,
encoder: &'a mut E,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
self.file_to_file_index[&(&*source_file as *const SourceFile)]
/// encode the specified tag, then the given value, then the number of
/// bytes taken up by tag and value. On decoding, we can then verify that
/// we get the expected tag and read the expected number of bytes.
- fn encode_tagged<T: Encodable, V: Encodable>(
+ fn encode_tagged<T: Encodable<Self>, V: Encodable<Self>>(
&mut self,
tag: T,
value: &V,
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<interpret::AllocId> for CacheEncoder<'a, 'tcx, E>
-where
- E: 'a + TyEncoder,
-{
- fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
- let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
- index.encode(self)
+impl<'a, 'tcx> FingerprintEncoder for CacheEncoder<'a, 'tcx, rustc_serialize::opaque::Encoder> {
+ fn encode_fingerprint(&mut self, f: &Fingerprint) -> opaque::EncodeResult {
+ f.encode_opaque(self.encoder)
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<SyntaxContext> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
- fn specialized_encode(&mut self, ctxt: &SyntaxContext) -> Result<(), Self::Error> {
- rustc_span::hygiene::raw_encode_syntax_context(*ctxt, self.hygiene_context, self)
+ fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+ rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s)
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<ExpnId> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
- fn specialized_encode(&mut self, expn: &ExpnId) -> Result<(), Self::Error> {
+ fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
rustc_span::hygiene::raw_encode_expn_id(
- *expn,
- self.hygiene_context,
+ *self,
+ s.hygiene_context,
ExpnDataEncodeMode::IncrComp,
- self,
+ s,
)
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<Span> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
- fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
- if *span == DUMMY_SP {
- return TAG_INVALID_SPAN.encode(self);
+ fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+ if *self == DUMMY_SP {
+ return TAG_INVALID_SPAN.encode(s);
}
- let span_data = span.data();
- let (file_lo, line_lo, col_lo) =
- match self.source_map.byte_pos_to_line_and_col(span_data.lo) {
- Some(pos) => pos,
- None => return TAG_INVALID_SPAN.encode(self),
- };
+ let span_data = self.data();
+ let (file_lo, line_lo, col_lo) = match s.source_map.byte_pos_to_line_and_col(span_data.lo) {
+ Some(pos) => pos,
+ None => return TAG_INVALID_SPAN.encode(s),
+ };
if !file_lo.contains(span_data.hi) {
- return TAG_INVALID_SPAN.encode(self);
+ return TAG_INVALID_SPAN.encode(s);
}
let len = span_data.hi - span_data.lo;
- let source_file_index = self.source_file_index(file_lo);
+ let source_file_index = s.source_file_index(file_lo);
- TAG_VALID_SPAN.encode(self)?;
- source_file_index.encode(self)?;
- line_lo.encode(self)?;
- col_lo.encode(self)?;
- len.encode(self)?;
- span_data.ctxt.encode(self)?;
- Ok(())
+ TAG_VALID_SPAN.encode(s)?;
+ source_file_index.encode(s)?;
+ line_lo.encode(s)?;
+ col_lo.encode(s)?;
+ len.encode(s)?;
+ span_data.ctxt.encode(s)
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<Ident> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx, E>
where
- E: 'a + ty_codec::TyEncoder,
+ E: 'a + OpaqueEncoder,
{
- fn specialized_encode(&mut self, _: &Ident) -> Result<(), Self::Error> {
- // We don't currently encode enough information to ensure hygiene works
- // with incremental, so panic rather than risk incremental bugs.
+ const CLEAR_CROSS_CRATE: bool = false;
- // FIXME: handle hygiene in incremental.
- bug!("trying to encode `Ident` for incremental");
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
}
-}
-
-impl<'a, 'tcx, E> ty_codec::TyEncoder for CacheEncoder<'a, 'tcx, E>
-where
- E: 'a + TyEncoder,
-{
- #[inline]
fn position(&self) -> usize {
- self.encoder.position()
+ self.encoder.encoder_position()
}
-}
-
-impl<'a, 'tcx, E> SpecializedEncoder<CrateNum> for CacheEncoder<'a, 'tcx, E>
-where
- E: 'a + TyEncoder,
-{
- #[inline]
- fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> {
- self.emit_u32(cnum.as_u32())
+ fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize> {
+ &mut self.type_shorthands
}
-}
-
-impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b ty::TyS<'c>> for CacheEncoder<'a, 'tcx, E>
-where
- E: 'a + TyEncoder,
- &'b ty::TyS<'c>: UseSpecializedEncodable,
-{
- #[inline]
- fn specialized_encode(&mut self, ty: &&'b ty::TyS<'c>) -> Result<(), Self::Error> {
- debug_assert!(self.tcx.lift(ty).is_some());
- let ty = unsafe { std::mem::transmute::<&&'b ty::TyS<'c>, &&'tcx ty::TyS<'tcx>>(ty) };
- ty_codec::encode_with_shorthand(self, ty, |encoder| &mut encoder.type_shorthands)
- }
-}
-
-impl<'a, 'b, 'tcx, E> SpecializedEncoder<ty::Predicate<'b>> for CacheEncoder<'a, 'tcx, E>
-where
- E: 'a + TyEncoder,
-{
- #[inline]
- fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> {
- debug_assert!(self.tcx.lift(predicate).is_some());
- let predicate =
- unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) };
- ty_codec::encode_with_shorthand(self, predicate, |encoder| {
- &mut encoder.predicate_shorthands
- })
+ fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::Predicate<'tcx>, usize> {
+ &mut self.predicate_shorthands
}
-}
+ fn encode_alloc_id(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
+ let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
-impl<'a, 'tcx, E> SpecializedEncoder<DefId> for CacheEncoder<'a, 'tcx, E>
-where
- E: 'a + TyEncoder,
-{
- #[inline]
- fn specialized_encode(&mut self, id: &DefId) -> Result<(), Self::Error> {
- let def_path_hash = self.tcx.def_path_hash(*id);
- def_path_hash.encode(self)
+ index.encode(self)
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<LocalDefId> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
- #[inline]
- fn specialized_encode(&mut self, id: &LocalDefId) -> Result<(), Self::Error> {
- id.to_def_id().encode(self)
+ fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
+ let def_path_hash = s.tcx.def_path_hash(*self);
+ def_path_hash.encode(s)
}
}
-impl<'a, 'tcx, E> SpecializedEncoder<DefIndex> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
- fn specialized_encode(&mut self, _: &DefIndex) -> Result<(), Self::Error> {
+ fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
bug!("encoding `DefIndex` without context");
}
}
-impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for CacheEncoder<'a, 'tcx, opaque::Encoder> {
- fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
- f.encode_opaque(&mut self.encoder)
- }
-}
-
macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => {
#[inline]
impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E>
where
- E: 'a + TyEncoder,
+ E: 'a + OpaqueEncoder,
{
type Error = E::Error;
pub const ENCODED_SIZE: usize = 8;
}
-impl UseSpecializedEncodable for IntEncodedWithFixedSize {}
-impl UseSpecializedDecodable for IntEncodedWithFixedSize {}
-
-impl SpecializedEncoder<IntEncodedWithFixedSize> for opaque::Encoder {
- fn specialized_encode(&mut self, x: &IntEncodedWithFixedSize) -> Result<(), Self::Error> {
- let start_pos = self.position();
+impl Encodable<opaque::Encoder> for IntEncodedWithFixedSize {
+ fn encode(&self, e: &mut opaque::Encoder) -> Result<(), !> {
+ let start_pos = e.position();
for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
- ((x.0 >> (i * 8)) as u8).encode(self)?;
+ ((self.0 >> (i * 8)) as u8).encode(e)?;
}
- let end_pos = self.position();
+ let end_pos = e.position();
assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(())
}
}
-impl<'a> SpecializedDecoder<IntEncodedWithFixedSize> for opaque::Decoder<'a> {
- fn specialized_decode(&mut self) -> Result<IntEncodedWithFixedSize, Self::Error> {
+impl<'a> Decodable<opaque::Decoder<'a>> for IntEncodedWithFixedSize {
+ fn decode(decoder: &mut opaque::Decoder<'a>) -> Result<IntEncodedWithFixedSize, String> {
let mut value: u64 = 0;
- let start_pos = self.position();
+ let start_pos = decoder.position();
for i in 0..IntEncodedWithFixedSize::ENCODED_SIZE {
- let byte: u8 = Decodable::decode(self)?;
+ let byte: u8 = Decodable::decode(decoder)?;
value |= (byte as u64) << (i * 8);
}
- let end_pos = self.position();
+ let end_pos = decoder.position();
assert_eq!((end_pos - start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
Ok(IntEncodedWithFixedSize(value))
) -> Result<(), E::Error>
where
Q: super::QueryDescription<TyCtxt<'tcx>> + super::QueryAccessors<TyCtxt<'tcx>>,
- Q::Value: Encodable,
- E: 'a + TyEncoder,
+ Q::Value: Encodable<CacheEncoder<'a, 'tcx, E>>,
+ E: 'a + OpaqueEncoder,
{
let _timer = tcx
.sess
state.iter_results(|results| {
for (key, value, dep_node) in results {
- if Q::cache_on_disk(tcx, &key, Some(&value)) {
+ if Q::cache_on_disk(tcx, &key, Some(value)) {
let dep_node = SerializedDepNodeIndex::new(dep_node.index());
// Record position of the cache entry.
- query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position())));
+ query_result_index
+ .push((dep_node, AbsoluteBytePos::new(encoder.encoder.opaque().position())));
// Encode the type check tables with the `SerializedDepNodeIndex`
// as tag.
- encoder.encode_tagged(dep_node, &value)?;
+ encoder.encode_tagged(dep_node, value)?;
}
}
Ok(())
use crate::ty::context::TyCtxt;
+use crate::ty::WithOptConstParam;
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::DefPathData;
use rustc_query_system::query::QueryCache;
use rustc_query_system::query::QueryState;
}
}
+impl SpecIntoSelfProfilingString for LocalDefId {
+ fn spec_to_self_profile_string(
+ &self,
+ builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+ ) -> StringId {
+ builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: self.local_def_index })
+ }
+}
+
+impl<T: SpecIntoSelfProfilingString> SpecIntoSelfProfilingString for WithOptConstParam<T> {
+ fn spec_to_self_profile_string(
+ &self,
+ builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+ ) -> StringId {
+ // We print `WithOptConstParam` values as tuples to make them shorter
+ // and more readable, without losing information:
+ //
+ // "WithOptConstParam { did: foo::bar, const_param_did: Some(foo::baz) }"
+ // becomes "(foo::bar, foo::baz)" and
+ // "WithOptConstParam { did: foo::bar, const_param_did: None }"
+ // becomes "(foo::bar, _)".
+
+ let did = StringComponent::Ref(self.did.to_self_profile_string(builder));
+
+ let const_param_did = if let Some(const_param_did) = self.const_param_did {
+ let const_param_did = builder.def_id_to_string_id(const_param_did);
+ StringComponent::Ref(const_param_did)
+ } else {
+ StringComponent::Value("_")
+ };
+
+ let components = [
+ StringComponent::Value("("),
+ did,
+ StringComponent::Value(", "),
+ const_param_did,
+ StringComponent::Value(")"),
+ ];
+
+ builder.profiler.alloc_string(&components[..])
+ }
+}
+
impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
where
T0: SpecIntoSelfProfilingString,
use crate::ty::{
self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
};
-use crate::ty::{List, ParamEnv, TyS};
+use crate::ty::{DelaySpanBugEmitted, List, ParamEnv, TyS};
use polonius_engine::Atom;
use rustc_ast::ast;
use rustc_data_structures::captures::Captures;
use std::ops::Range;
use ty::util::IntTypeExt;
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
pub struct TypeAndMut<'tcx> {
pub ty: Ty<'tcx>,
pub mutbl: hir::Mutability,
}
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
#[derive(HashStable)]
/// A "free" region `fr` can be interpreted as "some region
/// at least as big as the scope `fr.scope`".
pub bound_region: BoundRegion,
}
-#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, TyEncodable, TyDecodable, Copy)]
#[derive(HashStable)]
pub enum BoundRegion {
/// An anonymous region parameter for a given fn (&T)
/// N.B., if you change this, you'll probably want to change the corresponding
/// AST structure in `librustc_ast/ast.rs` as well.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable, Debug)]
#[derive(HashStable)]
#[rustc_diagnostic_item = "TyKind"]
pub enum TyKind<'tcx> {
}
}
-/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
-/// except through `tcx.err*()`.
-#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
-#[derive(RustcEncodable, RustcDecodable, HashStable)]
-pub struct DelaySpanBugEmitted(pub(super) ());
-
// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
static_assert_size!(TyKind<'_>, 24);
pub substs: SubstsRef<'tcx>,
}
-/// Struct returned by `split()`. Note that these are subslices of the
-/// parent slice and not canonical substs themselves.
-struct SplitClosureSubsts<'tcx> {
- parent: &'tcx [GenericArg<'tcx>],
- closure_kind_ty: GenericArg<'tcx>,
- closure_sig_as_fn_ptr_ty: GenericArg<'tcx>,
- tupled_upvars_ty: GenericArg<'tcx>,
+/// Struct returned by `split()`.
+pub struct ClosureSubstsParts<'tcx, T> {
+ pub parent_substs: &'tcx [GenericArg<'tcx>],
+ pub closure_kind_ty: T,
+ pub closure_sig_as_fn_ptr_ty: T,
+ pub tupled_upvars_ty: T,
}
impl<'tcx> ClosureSubsts<'tcx> {
- /// Divides the closure substs into their respective
- /// components. Single source of truth with respect to the
- /// ordering.
- fn split(self) -> SplitClosureSubsts<'tcx> {
+ /// Construct `ClosureSubsts` from `ClosureSubstsParts`, containing `Substs`
+ /// for the closure parent, alongside additional closure-specific components.
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ parts: ClosureSubstsParts<'tcx, Ty<'tcx>>,
+ ) -> ClosureSubsts<'tcx> {
+ ClosureSubsts {
+ substs: tcx.mk_substs(
+ parts.parent_substs.iter().copied().chain(
+ [parts.closure_kind_ty, parts.closure_sig_as_fn_ptr_ty, parts.tupled_upvars_ty]
+ .iter()
+ .map(|&ty| ty.into()),
+ ),
+ ),
+ }
+ }
+
+ /// Divides the closure substs into their respective components.
+ /// The ordering assumed here must match that used by `ClosureSubsts::new` above.
+ fn split(self) -> ClosureSubstsParts<'tcx, GenericArg<'tcx>> {
match self.substs[..] {
- [ref parent @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
- SplitClosureSubsts {
- parent,
+ [ref parent_substs @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
+ ClosureSubstsParts {
+ parent_substs,
closure_kind_ty,
closure_sig_as_fn_ptr_ty,
tupled_upvars_ty,
/// Returns the substitutions of the closure's parent.
pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
- self.split().parent
+ self.split().parent_substs
}
#[inline]
pub substs: SubstsRef<'tcx>,
}
-struct SplitGeneratorSubsts<'tcx> {
- parent: &'tcx [GenericArg<'tcx>],
- resume_ty: GenericArg<'tcx>,
- yield_ty: GenericArg<'tcx>,
- return_ty: GenericArg<'tcx>,
- witness: GenericArg<'tcx>,
- tupled_upvars_ty: GenericArg<'tcx>,
+pub struct GeneratorSubstsParts<'tcx, T> {
+ pub parent_substs: &'tcx [GenericArg<'tcx>],
+ pub resume_ty: T,
+ pub yield_ty: T,
+ pub return_ty: T,
+ pub witness: T,
+ pub tupled_upvars_ty: T,
}
impl<'tcx> GeneratorSubsts<'tcx> {
- fn split(self) -> SplitGeneratorSubsts<'tcx> {
+ /// Construct `GeneratorSubsts` from `GeneratorSubstsParts`, containing `Substs`
+ /// for the generator parent, alongside additional generator-specific components.
+ pub fn new(
+ tcx: TyCtxt<'tcx>,
+ parts: GeneratorSubstsParts<'tcx, Ty<'tcx>>,
+ ) -> GeneratorSubsts<'tcx> {
+ GeneratorSubsts {
+ substs: tcx.mk_substs(
+ parts.parent_substs.iter().copied().chain(
+ [
+ parts.resume_ty,
+ parts.yield_ty,
+ parts.return_ty,
+ parts.witness,
+ parts.tupled_upvars_ty,
+ ]
+ .iter()
+ .map(|&ty| ty.into()),
+ ),
+ ),
+ }
+ }
+
+ /// Divides the generator substs into their respective components.
+ /// The ordering assumed here must match that used by `GeneratorSubsts::new` above.
+ fn split(self) -> GeneratorSubstsParts<'tcx, GenericArg<'tcx>> {
match self.substs[..] {
- [ref parent @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
- SplitGeneratorSubsts {
- parent,
+ [ref parent_substs @ .., resume_ty, yield_ty, return_ty, witness, tupled_upvars_ty] => {
+ GeneratorSubstsParts {
+ parent_substs,
resume_ty,
yield_ty,
return_ty,
/// Returns the substitutions of the generator's parent.
pub fn parent_substs(self) -> &'tcx [GenericArg<'tcx>] {
- self.split().parent
+ self.split().parent_substs
}
/// This describes the types that can be contained in a generator.
}
}
-#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub enum ExistentialPredicate<'tcx> {
/// E.g., `Iterator`.
}
}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
-
impl<'tcx> List<ExistentialPredicate<'tcx>> {
/// Returns the "principal `DefId`" of this set of existential predicates.
///
///
/// Trait references also appear in object types like `Foo<U>`, but in
/// that case the `Self` parameter is absent from the substitutions.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct TraitRef<'tcx> {
pub def_id: DefId,
///
/// The substitutions don't include the erased `Self`, only trait
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct ExistentialTraitRef<'tcx> {
pub def_id: DefId,
/// erase, or otherwise "discharge" these bound vars, we change the
/// type from `Binder<T>` to just `T` (see
/// e.g., `liberate_late_bound_regions`).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
pub struct Binder<T>(T);
impl<T> Binder<T> {
/// Represents the projection of an associated type. In explicit UFCS
/// form this would be written `<T as Trait<..>>::N`.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct ProjectionTy<'tcx> {
/// The parameters of the associated item.
/// - `inputs`: is the list of arguments and their modes.
/// - `output`: is the return type.
/// - `c_variadic`: indicates whether this is a C-variadic function.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct FnSig<'tcx> {
pub inputs_and_output: &'tcx List<Ty<'tcx>>,
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<FnSig<'tcx>>>;
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct ParamTy {
pub index: u32,
}
}
-#[derive(Copy, Clone, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
#[derive(HashStable)]
pub struct ParamConst {
pub index: u32,
/// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
/// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
-#[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
+#[derive(Clone, PartialEq, Eq, Hash, Copy, TyEncodable, TyDecodable, PartialOrd, Ord)]
pub enum RegionKind {
/// Region bound in a type or fn declaration which will be
/// substituted 'early' -- that is, at the same time when type
ReErased,
}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for Region<'tcx> {}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, PartialOrd, Ord)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Debug, PartialOrd, Ord)]
pub struct EarlyBoundRegion {
pub def_id: DefId,
pub index: u32,
pub name: Symbol,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
pub struct TyVid {
pub index: u32,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
pub struct ConstVid<'tcx> {
pub index: u32,
pub phantom: PhantomData<&'tcx ()>,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
pub struct IntVid {
pub index: u32,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
pub struct FloatVid {
pub index: u32,
}
}
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum InferTy {
TyVar(TyVid),
pub struct BoundVar { .. }
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub struct BoundTy {
pub var: BoundVar,
pub kind: BoundTyKind,
}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundTyKind {
Anon,
}
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct ExistentialProjection<'tcx> {
pub item_def_id: DefId,
// Type substitutions.
use crate::infer::canonical::Canonical;
+use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
-use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder};
+use rustc_serialize::{self, Decodable, Encodable};
use rustc_span::{Span, DUMMY_SP};
use smallvec::SmallVec;
const REGION_TAG: usize = 0b01;
const CONST_TAG: usize = 0b10;
-#[derive(Debug, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
+#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)]
pub enum GenericArgKind<'tcx> {
Lifetime(ty::Region<'tcx>),
Type(Ty<'tcx>),
}
}
-impl<'tcx> Encodable for GenericArg<'tcx> {
- fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for GenericArg<'tcx> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
self.unpack().encode(e)
}
}
-impl<'tcx> Decodable for GenericArg<'tcx> {
- fn decode<D: Decoder>(d: &mut D) -> Result<GenericArg<'tcx>, D::Error> {
+impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArg<'tcx> {
+ fn decode(d: &mut D) -> Result<GenericArg<'tcx>, D::Error> {
Ok(GenericArgKind::decode(d)?.pack())
}
}
}
}
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for SubstsRef<'tcx> {}
-
///////////////////////////////////////////////////////////////////////////
// Public trait `Subst`
//
/// Stores the user-given substs to reach some fully qualified path
/// (e.g., `<T>::Item` or `<T as Trait>::Item`).
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
pub struct UserSubsts<'tcx> {
/// The substitutions for the item as given by the user.
/// the impl (with the substs from `UserSubsts`) and apply those to
/// the self type, giving `Foo<?A>`. Finally, we unify that with
/// the self type here, which contains `?A` to be `&'static u32`
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
pub struct UserSelfTy<'tcx> {
pub impl_def_id: DefId,
/// Whether this trait is treated specially by the standard library
/// specialization lint.
-#[derive(HashStable, PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)]
+#[derive(HashStable, PartialEq, Clone, Copy, TyEncodable, TyDecodable)]
pub enum TraitSpecializationKind {
/// The default. Specializing on this trait is not allowed.
None,
let span = match field
.did
.as_local()
- .map(|id| tcx.hir().as_local_hir_id(id))
+ .map(|id| tcx.hir().local_def_id_to_hir_id(id))
.and_then(|id| tcx.hir().find(id))
{
Some(hir::Node::Field(field)) => field.ty.span,
}
}
-#[derive(Copy, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
pub struct AlwaysRequiresDrop;
/// Normalizes all opaque types in the given value, replacing them
either = "1.5.0"
rustc_graphviz = { path = "../librustc_graphviz" }
itertools = "0.8"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
log_settings = "0.1.1"
polonius-engine = "0.12.0"
rustc_middle = { path = "../librustc_middle" }
let needs_note = match ty.kind {
ty::Closure(id, _) => {
let tables = self.infcx.tcx.typeck(id.expect_local());
- let hir_id = self.infcx.tcx.hir().as_local_hir_id(id.expect_local());
+ let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(id.expect_local());
tables.closure_kind_origins().get(hir_id).is_none()
}
format!("`{}` would have to be valid for `{}`...", name, region_name),
);
- let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+ let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
err.span_label(
drop_span,
format!(
) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
let is_closure = self.infcx.tcx.is_closure(did);
- let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(did.as_local()?);
+ let fn_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did.as_local()?);
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
// We need to work out which arguments to highlight. We do this by looking
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind {
let did = did.expect_local();
- let hir_id = self.infcx.tcx.hir().as_local_hir_id(did);
+ let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
if let Some((span, name)) =
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
if let Some(target) = target {
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind {
let did = did.expect_local();
- let hir_id = self.infcx.tcx.hir().as_local_hir_id(did);
+ let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
if let Some((span, name)) =
self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
"closure_span: def_id={:?} target_place={:?} places={:?}",
def_id, target_place, places
);
- let hir_id = self.infcx.tcx.hir().as_local_hir_id(def_id.as_local()?);
+ let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(def_id.as_local()?);
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
err.span_label(sp, format!("cannot {}", act));
let hir = self.infcx.tcx.hir();
- let closure_id = hir.as_local_hir_id(self.mir_def_id);
+ let closure_id = hir.local_def_id_to_hir_id(self.mir_def_id);
let fn_call_id = hir.get_parent_node(closure_id);
let node = hir.get(fn_call_id);
let item_id = hir.enclosing_body_owner(fn_call_id);
if let ty::Adt(def, _) = ty.kind {
let field = def.all_fields().nth(field.index())?;
// Use the HIR types to construct the diagnostic message.
- let hir_id = tcx.hir().as_local_hir_id(field.did.as_local()?);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(field.did.as_local()?);
let node = tcx.hir().find(hir_id)?;
// Now we're dealing with the actual struct that we're going to suggest a change to,
// we can expect a field that is an immutable reference to a type.
use std::collections::BTreeMap;
-use log::debug;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::DiagnosticBuilder;
use rustc_middle::ty::RegionVid;
+use tracing::debug;
use smallvec::SmallVec;
}
ty::BoundRegion::BrEnv => {
- let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+ let mir_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
let def_ty = self.regioncx.universal_regions().defining_ty;
if let DefiningTy::Closure(_, substs) = def_ty {
&self,
argument_index: usize,
) -> Option<&hir::Ty<'tcx>> {
- let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+ let mir_hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
match argument_hir_ty.kind {
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
- let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id);
+ let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
hir::Node::Expr(hir::Expr {
highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
- let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id);
+ let mir_hir_id = tcx.hir().local_def_id_to_hir_id(self.mir_def_id);
let yield_span = match tcx.hir().get(mir_hir_id) {
hir::Node::Expr(hir::Expr {
let tcx = infcx.tcx;
let param_env = tcx.param_env(def.did);
- let id = tcx.hir().as_local_hir_id(def.did);
+ let id = tcx.hir().local_def_id_to_hir_id(def.did);
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
for var_debug_info in &input_body.var_debug_info {
param_env: ty::ParamEnv<'tcx>,
) -> Self {
let tcx = infcx.tcx;
- let mir_hir_id = tcx.hir().as_local_hir_id(mir_def.did);
+ let mir_hir_id = tcx.hir().local_def_id_to_hir_id(mir_def.did);
UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
}
ecx.run()?;
// Intern the result
+ // FIXME: since the DefId of a promoted is the DefId of its owner, this
+ // means that promoteds in statics are actually interned like statics!
+ // However, this is also currently crucial because we promote mutable
+ // non-empty slices in statics to extend their lifetime, and this
+ // ensures that they are put into a mutable allocation.
+ // For other kinds of promoteds in statics (like array initializers), this is rather silly.
let intern_kind = match tcx.static_mutability(cid.instance.def_id()) {
Some(m) => InternKind::Static(m),
None if cid.promoted.is_some() => InternKind::Promoted,
// validation thus preventing such a hard error from being a backwards
// compatibility hazard
DefKind::Const | DefKind::AssocConst => {
- let hir_id = tcx.hir().as_local_hir_id(def.did);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
err.report_as_lint(
tcx.at(tcx.def_span(def.did)),
"any use of this value will cause an error",
err.report_as_lint(
tcx.at(span),
"reaching this expression at runtime will panic or abort",
- tcx.hir().as_local_hir_id(def.did),
+ tcx.hir().local_def_id_to_hir_id(def.did),
Some(err.span),
)
}
/// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
/// said intrinsic has a `rustc_const_{un,}stable` attribute.
fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
let tcx = ecx.tcx;
let base_intern_mode = match intern_kind {
InternKind::Static(mutbl) => InternMode::Static(mutbl),
- // FIXME: what about array lengths, array initializers?
+ // `Constant` includes array lengths.
+ // `Promoted` includes non-`Copy` array initializers and `rustc_args_required_const` arguments.
InternKind::Constant | InternKind::Promoted => InternMode::ConstBase,
};
#![recursion_limit = "256"]
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_middle;
// Visit MIR and accumululate used generic parameters.
let body = tcx.optimized_mir(def_id);
- let mut vis =
- UsedGenericParametersVisitor { tcx, def_id, unused_parameters: &mut unused_parameters };
+ let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters };
vis.visit_body(body);
debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters);
def_id: DefId,
unused_parameters: &mut FiniteBitSet<u32>,
) {
- let def_id = tcx.closure_base_def_id(def_id);
-
- let is_self_ty_used = |unused_parameters: &mut FiniteBitSet<u32>, self_ty: Ty<'tcx>| {
- debug!("unused_generic_params: self_ty={:?}", self_ty);
- if let ty::Param(param) = self_ty.kind {
- !unused_parameters.contains(param.index).unwrap_or(false)
- } else {
- false
- }
+ let is_ty_used = |unused_parameters: &FiniteBitSet<u32>, ty: Ty<'tcx>| -> bool {
+ let mut vis = IsUsedGenericParams { unused_parameters };
+ ty.visit_with(&mut vis)
};
let mark_ty = |unused_parameters: &mut FiniteBitSet<u32>, ty: Ty<'tcx>| {
- let mut vis = UsedGenericParametersVisitor { tcx, def_id, unused_parameters };
+ let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters };
ty.visit_with(&mut vis);
};
+ let def_id = tcx.closure_base_def_id(def_id);
let predicates = tcx.explicit_predicates_of(def_id);
- debug!("mark_parameters_used_in_predicates: predicates_of={:?}", predicates);
- for (predicate, _) in predicates.predicates {
- match predicate.skip_binders() {
- ty::PredicateAtom::Trait(predicate, ..) => {
- let trait_ref = predicate.trait_ref;
- if is_self_ty_used(unused_parameters, trait_ref.self_ty()) {
+ debug!("mark_used_by_predicates: predicates_of={:?}", predicates);
+
+ let mut current_unused_parameters = FiniteBitSet::new_empty();
+ // Run to a fixed point to support `where T: Trait<U>, U: Trait<V>`, starting with an empty
+ // bit set so that this is skipped if all parameters are already used.
+ while current_unused_parameters != *unused_parameters {
+ debug!(
+ "mark_used_by_predicates: current_unused_parameters={:?} = unused_parameters={:?}",
+ current_unused_parameters, unused_parameters
+ );
+ current_unused_parameters = *unused_parameters;
+
+ for (predicate, _) in predicates.predicates {
+ match predicate.skip_binders() {
+ ty::PredicateAtom::Trait(predicate, ..) => {
+ let trait_ref = predicate.trait_ref;
+ debug!("mark_used_by_predicates: (trait) trait_ref={:?}", trait_ref);
+
+ // Consider `T` used if `I` is used in predicates of the form
+ // `I: Iterator<Item = T>`
+ debug!("mark_used_by_predicates: checking self");
+ if is_ty_used(unused_parameters, trait_ref.self_ty()) {
+ debug!("mark_used_by_predicates: used!");
+ for ty in trait_ref.substs.types() {
+ mark_ty(unused_parameters, ty);
+ }
+
+ // No need to check for a type being used in the substs if `self_ty` was
+ // used.
+ continue;
+ }
+
+ // Consider `I` used if `T` is used in predicates of the form
+ // `I: Iterator<Item = &'a (T, E)>` (see rust-lang/rust#75326)
+ debug!("mark_used_by_predicates: checking substs");
for ty in trait_ref.substs.types() {
- debug!("unused_generic_params: (trait) ty={:?}", ty);
- mark_ty(unused_parameters, ty);
+ if is_ty_used(unused_parameters, ty) {
+ debug!("mark_used_by_predicates: used!");
+ mark_ty(unused_parameters, trait_ref.self_ty());
+ }
}
}
- }
- ty::PredicateAtom::Projection(proj, ..) => {
- let self_ty = proj.projection_ty.self_ty();
- if is_self_ty_used(unused_parameters, self_ty) {
- debug!("unused_generic_params: (projection ty={:?}", proj.ty);
- mark_ty(unused_parameters, proj.ty);
+ ty::PredicateAtom::Projection(proj, ..) => {
+ let self_ty = proj.projection_ty.self_ty();
+ debug!(
+ "mark_used_by_predicates: (projection) self_ty={:?} proj.ty={:?}",
+ self_ty, proj.ty
+ );
+
+ // Consider `T` used if `I` is used in predicates of the form
+ // `<I as Iterator>::Item = T`
+ debug!("mark_used_by_predicates: checking self");
+ if is_ty_used(unused_parameters, self_ty) {
+ debug!("mark_used_by_predicates: used!");
+ mark_ty(unused_parameters, proj.ty);
+
+ // No need to check for projection type being used if `self_ty` was used.
+ continue;
+ }
+
+ // Consider `I` used if `T` is used in predicates of the form
+ // `<I as Iterator>::Item = &'a (T, E)` (see rust-lang/rust#75326)
+ debug!("mark_used_by_predicates: checking projection ty");
+ if is_ty_used(unused_parameters, proj.ty) {
+ debug!("mark_used_by_predicates: used!");
+ mark_ty(unused_parameters, self_ty);
+ }
}
+ ty::PredicateAtom::RegionOutlives(..)
+ | ty::PredicateAtom::TypeOutlives(..)
+ | ty::PredicateAtom::WellFormed(..)
+ | ty::PredicateAtom::ObjectSafe(..)
+ | ty::PredicateAtom::ClosureKind(..)
+ | ty::PredicateAtom::Subtype(..)
+ | ty::PredicateAtom::ConstEvaluatable(..)
+ | ty::PredicateAtom::ConstEquate(..) => (),
}
- _ => (),
}
}
+
+ if let Some(parent) = predicates.parent {
+ mark_used_by_predicates(tcx, parent, unused_parameters);
+ }
}
/// Emit errors for the function annotated by `#[rustc_polymorphize_error]`, labelling each generic
}
/// Visitor used to aggregate generic parameter uses.
-struct UsedGenericParametersVisitor<'a, 'tcx> {
+struct MarkUsedGenericParams<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
def_id: DefId,
unused_parameters: &'a mut FiniteBitSet<u32>,
}
-impl<'a, 'tcx> UsedGenericParametersVisitor<'a, 'tcx> {
+impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
/// Invoke `unused_generic_params` on a body contained within the current item (e.g.
/// a closure, generator or constant).
fn visit_child_body(&mut self, def_id: DefId, substs: SubstsRef<'tcx>) {
}
}
-impl<'a, 'tcx> Visitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
debug!("visit_local_decl: local_decl={:?}", local_decl);
if local == Local::from_usize(1) {
}
}
-impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> {
+impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool {
debug!("visit_const: c={:?}", c);
if !c.has_param_types_or_consts() {
}
}
}
+
+/// Visitor used to check if a generic parameter is used.
+struct IsUsedGenericParams<'a> {
+ unused_parameters: &'a FiniteBitSet<u32>,
+}
+
+impl<'a, 'tcx> TypeVisitor<'tcx> for IsUsedGenericParams<'a> {
+ fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> bool {
+ debug!("visit_const: c={:?}", c);
+ if !c.has_param_types_or_consts() {
+ return false;
+ }
+
+ match c.val {
+ ty::ConstKind::Param(param) => {
+ !self.unused_parameters.contains(param.index).unwrap_or(false)
+ }
+ _ => c.super_visit_with(self),
+ }
+ }
+
+ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
+ debug!("visit_ty: ty={:?}", ty);
+ if !ty.has_param_types_or_consts() {
+ return false;
+ }
+
+ match ty.kind {
+ ty::Param(param) => !self.unused_parameters.contains(param.index).unwrap_or(false),
+ _ => ty.super_visit_with(self),
+ }
+ }
+}
.skip(1)
.take(arg_count)
.map(|(local, _)| Place::from(local))
- .filter(needs_retag)
- .collect::<Vec<_>>();
+ .filter(needs_retag);
// Emit their retags.
basic_blocks[START_BLOCK].statements.splice(
0..0,
- places.into_iter().map(|place| Statement {
+ places.map(|place| Statement {
source_info,
kind: StatementKind::Retag(RetagKind::FnEntry, box (place)),
}),
// PART 2
// Retag return values of functions. Also escape-to-raw the argument of `drop`.
// We collect the return destinations because we cannot mutate while iterating.
- let mut returns: Vec<(SourceInfo, Place<'tcx>, BasicBlock)> = Vec::new();
- for block_data in basic_blocks.iter_mut() {
- match block_data.terminator().kind {
- TerminatorKind::Call { ref destination, .. } => {
- // Remember the return destination for later
- if let Some(ref destination) = destination {
- if needs_retag(&destination.0) {
- returns.push((
- block_data.terminator().source_info,
- destination.0,
- destination.1,
- ));
- }
+ let returns = basic_blocks
+ .iter_mut()
+ .filter_map(|block_data| {
+ match block_data.terminator().kind {
+ TerminatorKind::Call { destination: Some(ref destination), .. }
+ if needs_retag(&destination.0) =>
+ {
+ // Remember the return destination for later
+ Some((block_data.terminator().source_info, destination.0, destination.1))
}
- }
- TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
+
// `Drop` is also a call, but it doesn't return anything so we are good.
- }
- _ => {
+ TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None,
// Not a block ending in a Call -> ignore.
+ _ => None,
}
- }
- }
+ })
+ .collect::<Vec<_>>();
// Now we go over the returns we collected to retag the return values.
for (source_info, dest_place, dest_block) in returns {
basic_blocks[dest_block].statements.insert(
&& !tcx.is_thread_local_static(def_id.to_def_id());
if should_check_for_sync {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
check_return_ty_is_sync(tcx, &body, hir_id);
}
}
used_unsafe: &FxHashSet<hir::HirId>,
unsafe_blocks: &mut Vec<(hir::HirId, bool)>,
) {
- let body_id = tcx.hir().maybe_body_owned_by(tcx.hir().as_local_hir_id(def_id));
+ let body_id = tcx.hir().maybe_body_owned_by(tcx.hir().local_def_id_to_hir_id(def_id));
let body_id = match body_id {
Some(body) => body,
let param_env = tcx.param_env(def.did);
- let id = tcx.hir().as_local_hir_id(def.did);
+ let id = tcx.hir().local_def_id_to_hir_id(def.did);
let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
hir::BodyOwnerKind::Closure => (false, false),
hir::BodyOwnerKind::Fn => {
}
fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let lint_hir_id = tcx.hir().as_local_hir_id(def_id);
+ let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| {
// FIXME: when we make this a hard error, this should have its
}
use rustc_middle::hir::map::blocks::FnLikeNode;
- let hir_id = tcx.hir().as_local_hir_id(source.def_id().expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(source.def_id().expect_local());
let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some();
let is_assoc_const = tcx.def_kind(source.def_id()) == DefKind::AssocConst;
for bb in basic_blocks {
bb.expand_statements(|stmt| {
// FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
- if let StatementKind::Assign(box (_, ref rhs)) = stmt.kind {
- if let Rvalue::Aggregate(ref kind, _) = *rhs {
- // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
- if let AggregateKind::Array(_) = **kind {
- return None;
- }
- } else {
+ match stmt.kind {
+ // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
+ StatementKind::Assign(box (
+ _,
+ Rvalue::Aggregate(box AggregateKind::Array(_), _),
+ )) => {
return None;
}
- } else {
- return None;
+ StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {}
+ _ => return None,
}
let stmt = stmt.replace_nop();
let source_info = stmt.source_info;
let (lhs, kind, operands) = match stmt.kind {
- StatementKind::Assign(box (lhs, rvalue)) => match rvalue {
- Rvalue::Aggregate(kind, operands) => (lhs, kind, operands),
- _ => bug!(),
- },
+ StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) => {
+ (lhs, kind, operands)
+ }
_ => bug!(),
};
let param_env = self.tcx.param_env_reveal_all_normalized(self.source.def_id());
// Only do inlining into fn bodies.
- let id = self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());
+ let id = self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local());
if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() {
for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() {
if let Some(callsite) =
}
let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() {
- let callee_hir_id = self.tcx.hir().as_local_hir_id(callee_def_id);
+ let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id);
let self_hir_id =
- self.tcx.hir().as_local_hir_id(self.source.def_id().expect_local());
+ self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local());
// Avoid a cycle here by only using `optimized_mir` only if we have
// a lower `HirId` than the callee. This ensures that the callee will
// not inline us. This trick only works without incremental compilation.
let (file_name, start_line, start_col, end_line, end_col) = self.code_region(&span);
+ // FIXME(richkadel): Note that `const_str()` results in the creation of an `Allocation` to
+ // hold one copy of each unique filename. It looks like that `Allocation` may translate into
+ // the creation of an `@alloc` in LLVM IR that is never actually used by runtime code.
+ //
+ // Example LLVM IR:
+ //
+ // @alloc4 = private unnamed_addr constant <{ [43 x i8] }> \
+ // <{ [43 x i8] c"C:\\msys64\\home\\richkadel\\rust\\rust_basic.rs" }>, align 1
+ //
+ // Can I flag the alloc as something not to be added to codegen? Or somehow remove it before
+ // it gets added to the LLVM IR? Do we need some kind of reference counting to know it's
+ // not used by any runtime code?
+ //
+ // This question is moot if I convert the Call Terminators to Statements, I believe:
+ // https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Implement.20LLVM-compatible.20source-based.20cod.20compiler-team.23278/near/206731748
args.push(self.const_str(&file_name, inject_at));
args.push(self.const_u32(start_line, inject_at));
args.push(self.const_u32(start_col, inject_at));
--- /dev/null
+use crate::transform::{MirPass, MirSource};
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct MatchBranchSimplification;
+
+/// If a source block is found that switches between two blocks that are exactly
+/// the same modulo const bool assignments (e.g., one assigns true another false
+/// to the same place), merge a target block statements into the source block,
+/// using Eq / Ne comparison with switch value where const bools value differ.
+///
+/// For example:
+///
+/// ```rust
+/// bb0: {
+/// switchInt(move _3) -> [42_isize: bb1, otherwise: bb2];
+/// }
+///
+/// bb1: {
+/// _2 = const true;
+/// goto -> bb3;
+/// }
+///
+/// bb2: {
+/// _2 = const false;
+/// goto -> bb3;
+/// }
+/// ```
+///
+/// into:
+///
+/// ```rust
+/// bb0: {
+/// _2 = Eq(move _3, const 42_isize);
+/// goto -> bb3;
+/// }
+/// ```
+
+impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
+ let param_env = tcx.param_env(src.def_id());
+ let bbs = body.basic_blocks_mut();
+ 'outer: for bb_idx in bbs.indices() {
+ let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
+ TerminatorKind::SwitchInt {
+ discr: Operand::Copy(ref place) | Operand::Move(ref place),
+ switch_ty,
+ ref targets,
+ ref values,
+ ..
+ } if targets.len() == 2 && values.len() == 1 && targets[0] != targets[1] => {
+ (place, values[0], switch_ty, targets[0], targets[1])
+ }
+ // Only optimize switch int statements
+ _ => continue,
+ };
+
+ // Check that destinations are identical, and if not, then don't optimize this block
+ if &bbs[first].terminator().kind != &bbs[second].terminator().kind {
+ continue;
+ }
+
+ // Check that blocks are assignments of consts to the same place or same statement,
+ // and match up 1-1, if not don't optimize this block.
+ let first_stmts = &bbs[first].statements;
+ let scnd_stmts = &bbs[second].statements;
+ if first_stmts.len() != scnd_stmts.len() {
+ continue;
+ }
+ for (f, s) in first_stmts.iter().zip(scnd_stmts.iter()) {
+ match (&f.kind, &s.kind) {
+ // If two statements are exactly the same, we can optimize.
+ (f_s, s_s) if f_s == s_s => {}
+
+ // If two statements are const bool assignments to the same place, we can optimize.
+ (
+ StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
+ StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
+ ) if lhs_f == lhs_s
+ && f_c.literal.ty.is_bool()
+ && s_c.literal.ty.is_bool()
+ && f_c.literal.try_eval_bool(tcx, param_env).is_some()
+ && s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
+
+ // Otherwise we cannot optimize. Try another block.
+ _ => continue 'outer,
+ }
+ }
+ // Take ownership of items now that we know we can optimize.
+ let discr = discr.clone();
+
+ // We already checked that first and second are different blocks,
+ // and bb_idx has a different terminator from both of them.
+ let (from, first, second) = bbs.pick3_mut(bb_idx, first, second);
+
+ let new_stmts = first.statements.iter().zip(second.statements.iter()).map(|(f, s)| {
+ match (&f.kind, &s.kind) {
+ (f_s, s_s) if f_s == s_s => (*f).clone(),
+
+ (
+ StatementKind::Assign(box (lhs, Rvalue::Use(Operand::Constant(f_c)))),
+ StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
+ ) => {
+ // From earlier loop we know that we are dealing with bool constants only:
+ let f_b = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
+ let s_b = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
+ if f_b == s_b {
+ // Same value in both blocks. Use statement as is.
+ (*f).clone()
+ } else {
+ // Different value between blocks. Make value conditional on switch condition.
+ let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+ let const_cmp = Operand::const_from_scalar(
+ tcx,
+ switch_ty,
+ crate::interpret::Scalar::from_uint(val, size),
+ rustc_span::DUMMY_SP,
+ );
+ let op = if f_b { BinOp::Eq } else { BinOp::Ne };
+ let rhs = Rvalue::BinaryOp(op, Operand::Copy(discr.clone()), const_cmp);
+ Statement {
+ source_info: f.source_info,
+ kind: StatementKind::Assign(box (*lhs, rhs)),
+ }
+ }
+ }
+
+ _ => unreachable!(),
+ }
+ });
+ from.statements.extend(new_stmts);
+ from.terminator_mut().kind = first.terminator().kind.clone();
+ }
+ }
+}
pub mod inline;
pub mod instcombine;
pub mod instrument_coverage;
+pub mod match_branches;
pub mod no_landing_pads;
pub mod nrvo;
pub mod promote_consts;
// with async primitives.
&generator::StateTransform,
&instcombine::InstCombine,
+ &match_branches::MatchBranchSimplification,
&const_prop::ConstProp,
&simplify_branches::SimplifyBranches::new("after-const-prop"),
&simplify_try::SimplifyArmIdentity,
/// of a larger candidate.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Candidate {
- /// Borrow of a constant temporary.
+ /// Borrow of a constant temporary, candidate for lifetime extension.
Ref(Location),
/// Promotion of the `x` in `[x; 32]`.
pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult {
// Prevent const trait methods from being annotated as `stable`.
if tcx.features().staged_api {
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
return Err((body.span, "trait methods cannot be stable const fn".into()));
}
tmp_assigned_vars.insert(*r);
}
- let mut dbg_info_to_adjust = Vec::new();
- for (i, var_info) in debug_info.iter().enumerate() {
- if tmp_assigned_vars.contains(var_info.place.local) {
- dbg_info_to_adjust.push(i);
- }
- }
+ let dbg_info_to_adjust: Vec<_> =
+ debug_info
+ .iter()
+ .enumerate()
+ .filter_map(|(i, var_info)| {
+ if tmp_assigned_vars.contains(var_info.place.local) { Some(i) } else { None }
+ })
+ .collect();
Some(ArmIdentityInfo {
local_temp_0: local_tmp_s0,
stmt: &Statement<'tcx>,
) -> Option<(Local, Local, VarField<'tcx>, &'tcx List<PlaceElem<'tcx>>)> {
match &stmt.kind {
- StatementKind::Assign(box (place_into, rvalue_from)) => match rvalue_from {
- Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)) => {
- let local_into = place_into.as_local()?;
- let (local_from, vf) = match_variant_field_place(*pf)?;
- Some((local_into, local_from, vf, pf.projection))
- }
- _ => None,
- },
+ StatementKind::Assign(box (
+ place_into,
+ Rvalue::Use(Operand::Copy(pf) | Operand::Move(pf)),
+ )) => {
+ let local_into = place_into.as_local()?;
+ let (local_from, vf) = match_variant_field_place(*pf)?;
+ Some((local_into, local_from, vf, pf.projection))
+ }
_ => None,
}
}
/// ```
fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local, VarField<'tcx>)> {
match &stmt.kind {
- StatementKind::Assign(box (place_from, rvalue_into)) => match rvalue_into {
- Rvalue::Use(Operand::Move(place_into)) => {
- let local_into = place_into.as_local()?;
- let (local_from, vf) = match_variant_field_place(*place_from)?;
- Some((local_into, local_from, vf))
- }
- _ => None,
- },
+ StatementKind::Assign(box (place_from, Rvalue::Use(Operand::Move(place_into)))) => {
+ let local_into = place_into.as_local()?;
+ let (local_from, vf) = match_variant_field_place(*place_from)?;
+ Some((local_into, local_from, vf))
+ }
_ => None,
}
}
if let TerminatorKind::SwitchInt { values, targets, .. } =
&mut body.basic_blocks_mut()[bb].terminator_mut().kind
{
- let vals = &*values;
- let zipped = vals.iter().zip(targets.iter());
-
- let mut matched_values = Vec::with_capacity(allowed_variants.len());
- let mut matched_targets = Vec::with_capacity(allowed_variants.len() + 1);
-
- for (val, target) in zipped {
- if allowed_variants.contains(val) {
- matched_values.push(*val);
- matched_targets.push(*target);
- } else {
- trace!("eliminating {:?} -> {:?}", val, target);
- }
- }
-
- // handle the "otherwise" branch
- matched_targets.push(targets.pop().unwrap());
-
- *values = matched_values.into();
- *targets = matched_targets;
+ // take otherwise out early
+ let otherwise = targets.pop().unwrap();
+ assert_eq!(targets.len(), values.len());
+ let mut i = 0;
+ targets.retain(|_| {
+ let keep = allowed_variants.contains(&values[i]);
+ i += 1;
+ keep
+ });
+ targets.push(otherwise);
+
+ values.to_mut().retain(|var| allowed_variants.contains(var));
} else {
unreachable!()
}
where
F: Fn(BasicBlock) -> bool,
{
- match *terminator_kind {
- TerminatorKind::Goto { target } if predicate(target) => Some(TerminatorKind::Unreachable),
+ let terminator = match *terminator_kind {
+ TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable,
TerminatorKind::SwitchInt { ref discr, switch_ty, ref values, ref targets } => {
let original_targets_len = targets.len();
let (otherwise, targets) = targets.split_last().unwrap();
- let retained = values
- .iter()
- .zip(targets.iter())
- .filter(|(_, &t)| !predicate(t))
- .collect::<Vec<_>>();
- let mut values = retained.iter().map(|&(v, _)| *v).collect::<Vec<_>>();
- let mut targets = retained.iter().map(|&(_, d)| *d).collect::<Vec<_>>();
+ let (mut values, mut targets): (Vec<_>, Vec<_>) =
+ values.iter().zip(targets.iter()).filter(|(_, &t)| !predicate(t)).unzip();
if !predicate(*otherwise) {
targets.push(*otherwise);
let retained_targets_len = targets.len();
if targets.is_empty() {
- Some(TerminatorKind::Unreachable)
+ TerminatorKind::Unreachable
} else if targets.len() == 1 {
- Some(TerminatorKind::Goto { target: targets[0] })
+ TerminatorKind::Goto { target: targets[0] }
} else if original_targets_len != retained_targets_len {
- Some(TerminatorKind::SwitchInt {
+ TerminatorKind::SwitchInt {
discr: discr.clone(),
switch_ty,
values: Cow::from(values),
targets,
- })
+ }
} else {
- None
+ return None;
}
}
- _ => None,
- }
+ _ => return None,
+ };
+ Some(terminator)
}
[dependencies]
rustc_arena = { path = "../librustc_arena" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_apfloat = { path = "../librustc_apfloat" }
rustc_attr = { path = "../librustc_attr" }
use rustc_hir::{GeneratorKind, HirIdMap, Node};
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::region;
use rustc_middle::mir::*;
use rustc_middle::ty::subst::Subst;
/// Construct the MIR for a given `DefId`.
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
- let id = tcx.hir().as_local_hir_id(def.did);
+ let id = tcx.hir().local_def_id_to_hir_id(def.did);
// Figure out what primary body this item has.
let (body_id, return_ty_span) = match tcx.hir().get(id) {
argument_scope: region::Scope,
ast_body: &'tcx hir::Expr<'tcx>,
) -> BlockAnd<()> {
- let tcx = self.hir.tcx();
- let attrs = tcx.codegen_fn_attrs(fn_def_id);
- let naked = attrs.flags.contains(CodegenFnAttrFlags::NAKED);
-
// Allocate locals for the function arguments
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
let source_info =
SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
- // Emit function argument debuginfo only for non-naked functions.
- // See: https://github.com/rust-lang/rust/issues/42779
- if naked {
- continue;
- }
-
// If this is a simple binding pattern, give debuginfo a nice name.
if let Some(arg) = arg_opt {
if let Some(ident) = arg.pat.simple_ident() {
}
}
+ let tcx = self.hir.tcx();
let tcx_hir = tcx.hir();
let hir_typeck_results = self.hir.typeck_results();
#![recursion_limit = "256"]
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_middle;
use rustc_span::Span;
crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: LocalDefId) {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
if let FnKind::Closure(_) = fn_like_node.kind() {
vis.reachable_recursive_calls.sort();
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span(hir_id));
tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
let mut db = lint.build("function cannot return without recursing");
}
Res::Def(DefKind::ConstParam, def_id) => {
- let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item_id = cx.tcx.hir().get_parent_node(hir_id);
let item_def_id = cx.tcx.hir().local_def_id(item_id);
let generics = cx.tcx.generics_of(item_def_id);
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
let body_id = match def_id.as_local() {
None => return,
- Some(id) => tcx.hir().body_owned_by(tcx.hir().as_local_hir_id(id)),
+ Some(id) => tcx.hir().body_owned_by(tcx.hir().local_def_id_to_hir_id(id)),
};
let mut visitor = MatchVisitor {
[dependencies]
bitflags = "1.0"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Pos, Span};
-use log::debug;
use std::char;
+use tracing::debug;
mod tokentrees;
mod unescape_error_reporting;
range: Range<usize>,
error: EscapeError,
) {
- log::debug!(
+ tracing::debug!(
"emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}",
lit,
span_with_quotes,
use std::path::Path;
use std::str;
-use log::{debug, info};
+use tracing::{debug, info};
pub const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");
use rustc_errors::{error_code, PResult};
use rustc_span::Span;
-use log::debug;
+use tracing::debug;
#[derive(Debug)]
pub(super) enum InnerAttrPolicy<'a> {
use rustc_span::symbol::{kw, Ident};
use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP};
-use log::{debug, trace};
+use tracing::{debug, trace};
const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments";
use super::{SemiColonMode, SeqSep, TokenExpectType};
use crate::maybe_recover_from_interpolated_ty_qpath;
-use log::debug;
use rustc_ast::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Lit, UnOp, DUMMY_NODE_ID};
use rustc_ast::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind};
use rustc_ast::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use std::mem;
+use tracing::debug;
/// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression
/// dropped into the token stream, which happens while parsing the result of
// want to keep their span info to improve diagnostics in these cases in a later stage.
(true, Some(AssocOp::Multiply)) | // `{ 42 } *foo = bar;` or `{ 42 } * 3`
(true, Some(AssocOp::Subtract)) | // `{ 42 } -5`
- (true, Some(AssocOp::LAnd)) | // `{ 42 } &&x` (#61475)
(true, Some(AssocOp::Add)) // `{ 42 } + 42
// If the next token is a keyword, then the tokens above *are* unambiguously incorrect:
// `if x { a } else { b } && if y { c } else { d }`
- if !self.look_ahead(1, |t| t.is_reserved_ident()) => {
+ if !self.look_ahead(1, |t| t.is_used_keyword()) => {
+ // These cases are ambiguous and can't be identified in the parser alone.
+ let sp = self.sess.source_map().start_point(self.token.span);
+ self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
+ false
+ }
+ (true, Some(AssocOp::LAnd)) => {
+ // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`. Separated from the
+ // above due to #74233.
// These cases are ambiguous and can't be identified in the parser alone.
let sp = self.sess.source_map().start_point(self.token.span);
self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span);
use rustc_span::source_map::{self, Span};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use log::debug;
use std::convert::TryFrom;
use std::mem;
+use tracing::debug;
impl<'a> Parser<'a> {
/// Parses a source module as a crate. This is the main entry point for the parser.
vis: Visibility,
attrs: Vec<Attribute>,
) -> PResult<'a, StructField> {
- let name = self.parse_ident()?;
+ let name = self.parse_ident_common(false)?;
self.expect(&token::Colon)?;
let ty = self.parse_ty()?;
Ok(StructField {
use diagnostics::Error;
pub use path::PathStyle;
-use log::debug;
use rustc_ast::ast::DUMMY_NODE_ID;
use rustc_ast::ast::{self, AttrStyle, AttrVec, Const, CrateSugar, Extern, Unsafe};
use rustc_ast::ast::{
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{respan, Span, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use tracing::debug;
use std::{cmp, mem, slice};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::symbol::{kw, sym, Ident};
-use log::debug;
use std::mem;
+use tracing::debug;
/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
path = "lib.rs"
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_attr = { path = "../librustc_attr" }
rustc_data_structures = { path = "../librustc_data_structures" }
fn check_def_id(&mut self, def_id: DefId) {
if let Some(def_id) = def_id.as_local() {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
if should_explore(self.tcx, hir_id) || self.struct_constructors.contains_key(&hir_id) {
self.worklist.push(hir_id);
}
fn insert_def_id(&mut self, def_id: DefId) {
if let Some(def_id) = def_id.as_local() {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
debug_assert!(!should_explore(self.tcx, hir_id));
self.live_symbols.insert(hir_id);
}
)
.chain(
// Seed entry point
- tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_hir_id(def_id)),
+ tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().local_def_id_to_hir_id(def_id)),
)
.collect::<Vec<_>>();
for &impl_did in inherent_impls.iter() {
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
if let Some(did) = item_did.as_local() {
- let item_hir_id = self.tcx.hir().as_local_hir_id(did);
+ let item_hir_id = self.tcx.hir().local_def_id_to_hir_id(did);
if self.live_symbols.contains(&item_hir_id) {
return true;
}
#[macro_use]
extern crate rustc_middle;
#[macro_use]
-extern crate log;
+extern crate tracing;
use rustc_middle::ty::query::Providers;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirIdSet, Node};
+use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::middle::privacy;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::config::CrateType;
use rustc_target::spec::abi::Abi;
return true;
}
}
- match tcx.hir().find(tcx.hir().as_local_hir_id(impl_src)) {
+ match tcx.hir().find(tcx.hir().local_def_id_to_hir_id(impl_src)) {
Some(Node::Item(item)) => item_might_be_inlined(tcx, &item, codegen_fn_attrs),
Some(..) | None => span_bug!(impl_item.span, "impl did is not an item"),
}
tcx: TyCtxt<'tcx>,
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
// The set of items which must be exported in the linkage sense.
- reachable_symbols: HirIdSet,
+ reachable_symbols: FxHashSet<LocalDefId>,
// A worklist of item IDs. Each item ID in this worklist will be inlined
// and will be scanned for further references.
- worklist: Vec<hir::HirId>,
+ // FIXME(eddyb) benchmark if this would be faster as a `VecDeque`.
+ worklist: Vec<LocalDefId>,
// Whether any output of this compilation is a library
any_library: bool,
}
_ => None,
};
- match res {
- Some(Res::Local(hir_id)) => {
- self.reachable_symbols.insert(hir_id);
- }
- Some(res) => {
- if let Some((hir_id, def_id)) = res.opt_def_id().and_then(|def_id| {
- def_id.as_local().map(|def_id| (self.tcx.hir().as_local_hir_id(def_id), def_id))
- }) {
- if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
- self.worklist.push(hir_id);
- } else {
- match res {
- // If this path leads to a constant, then we need to
- // recurse into the constant to continue finding
- // items that are reachable.
- Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
- self.worklist.push(hir_id);
- }
+ if let Some(res) = res {
+ if let Some(def_id) = res.opt_def_id().and_then(|def_id| def_id.as_local()) {
+ if self.def_id_represents_local_inlined_item(def_id.to_def_id()) {
+ self.worklist.push(def_id);
+ } else {
+ match res {
+ // If this path leads to a constant, then we need to
+ // recurse into the constant to continue finding
+ // items that are reachable.
+ Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
+ self.worklist.push(def_id);
+ }
- // If this wasn't a static, then the destination is
- // surely reachable.
- _ => {
- self.reachable_symbols.insert(hir_id);
- }
+ // If this wasn't a static, then the destination is
+ // surely reachable.
+ _ => {
+ self.reachable_symbols.insert(def_id);
}
}
}
}
- _ => {}
}
intravisit::walk_expr(self, expr)
// eligible for inlining and false otherwise.
fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
let hir_id = match def_id.as_local() {
- Some(def_id) => self.tcx.hir().as_local_hir_id(def_id),
+ Some(def_id) => self.tcx.hir().local_def_id_to_hir_id(def_id),
None => {
return false;
}
// Check the impl. If the generics on the self
// type of the impl require inlining, this method
// does too.
- let impl_hir_id = self.tcx.hir().as_local_hir_id(impl_did);
+ let impl_hir_id = self.tcx.hir().local_def_id_to_hir_id(impl_did);
match self.tcx.hir().expect_item(impl_hir_id).kind {
hir::ItemKind::Impl { .. } => {
let generics = self.tcx.generics_of(impl_did);
continue;
}
- if let Some(ref item) = self.tcx.hir().find(search_item) {
+ if let Some(ref item) =
+ self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(search_item))
+ {
self.propagate_node(item, search_item);
}
}
}
- fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
+ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: LocalDefId) {
if !self.any_library {
// If we are building an executable, only explicitly extern
// types need to be exported.
self.visit_nested_body(body);
}
hir::ImplItemKind::Fn(_, body) => {
- let did = self.tcx.hir().get_parent_did(search_item);
- if method_might_be_inlined(self.tcx, impl_item, did) {
+ let impl_def_id =
+ self.tcx.parent(search_item.to_def_id()).unwrap().expect_local();
+ if method_might_be_inlined(self.tcx, impl_item, impl_def_id) {
self.visit_nested_body(body)
}
}
_ => {
bug!(
"found unexpected node kind in worklist: {} ({:?})",
- self.tcx.hir().node_to_string(search_item),
+ self.tcx
+ .hir()
+ .node_to_string(self.tcx.hir().local_def_id_to_hir_id(search_item)),
node,
);
}
struct CollectPrivateImplItemsVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
access_levels: &'a privacy::AccessLevels,
- worklist: &'a mut Vec<hir::HirId>,
+ worklist: &'a mut Vec<LocalDefId>,
}
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx> {
if codegen_attrs.contains_extern_indicator()
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
{
- self.worklist.push(item.hir_id);
+ self.worklist.push(def_id);
}
// We need only trait impls here, not inherent impls, and only non-exported ones
if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind {
if !self.access_levels.is_reachable(item.hir_id) {
- self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.hir_id));
+ // FIXME(#53488) remove `let`
+ let tcx = self.tcx;
+ self.worklist
+ .extend(items.iter().map(|ii_ref| tcx.hir().local_def_id(ii_ref.id.hir_id)));
let trait_def_id = match trait_ref.path.res {
Res::Def(DefKind::Trait, def_id) => def_id,
return;
}
- // FIXME(#53488) remove `let`
- let tcx = self.tcx;
self.worklist.extend(
tcx.provided_trait_methods(trait_def_id)
- .map(|assoc| tcx.hir().as_local_hir_id(assoc.def_id.expect_local())),
+ .map(|assoc| assoc.def_id.expect_local()),
);
}
}
}
}
-fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> &'tcx HirIdSet {
+fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, crate_num: CrateNum) -> FxHashSet<LocalDefId> {
debug_assert!(crate_num == LOCAL_CRATE);
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
// If other crates link to us, they're going to expect to be able to
// use the lang items, so we need to be sure to mark them as
// exported.
- reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id));
+ reachable_context
+ .worklist
+ .extend(access_levels.map.iter().map(|(id, _)| tcx.hir().local_def_id(*id)));
for item in tcx.lang_items().items().iter() {
- if let Some(did) = *item {
- if let Some(hir_id) = did.as_local().map(|did| tcx.hir().as_local_hir_id(did)) {
- reachable_context.worklist.push(hir_id);
+ if let Some(def_id) = *item {
+ if let Some(def_id) = def_id.as_local() {
+ reachable_context.worklist.push(def_id);
}
}
}
debug!("Inline reachability shows: {:?}", reachable_context.reachable_symbols);
// Return the set of reachable symbols.
- tcx.arena.alloc(reachable_context.reachable_symbols)
+ reachable_context.reachable_symbols
}
pub fn provide(providers: &mut Providers) {
return tcx.region_scope_tree(closure_base_def_id);
}
- let id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let scope_tree = if let Some(body_id) = tcx.hir().maybe_body_owned_by(id) {
let mut visitor = RegionResolutionVisitor {
tcx,
return None;
}
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let body = tcx.hir().body(tcx.hir().maybe_body_owned_by(hir_id)?);
let mut local_collector = LocalCollector::default();
rustc_session = { path = "../librustc_session" }
rustc_span = { path = "../librustc_span" }
rustc_data_structures = { path = "../librustc_data_structures" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> (ty::Visibility, Span, &'static str) {
- match def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id)) {
+ match def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) {
Some(hir_id) => {
let vis = match tcx.hir().get(hir_id) {
Node::Item(item) => &item.vis,
fn new_min(find: &FindMin<'_, '_, Self>, def_id: DefId) -> Self {
cmp::min(
if let Some(def_id) = def_id.as_local() {
- let hir_id = find.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = find.tcx.hir().local_def_id_to_hir_id(def_id);
find.access_levels.map.get(&hir_id).cloned()
} else {
Self::MAX
if let Res::Def(def_kind, def_id) = export.res {
let vis = def_id_visibility(self.tcx, def_id).0;
if let Some(def_id) = def_id.as_local() {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
}
}
// there will be no corresponding item.
.filter(|def_id| def_id.index != CRATE_DEF_INDEX || def_id.krate != LOCAL_CRATE)
.and_then(|def_id| {
- def_id.as_local().map(|def_id| self.tcx.hir().as_local_hir_id(def_id))
+ def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
})
.map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id))
{
if export.vis == ty::Visibility::Public {
if let Some(def_id) = export.res.opt_def_id() {
if let Some(def_id) = def_id.as_local() {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
self.update(hir_id, Some(AccessLevel::Exported));
}
}
}
fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool {
if let Some(def_id) = def_id.as_local() {
- let hir_id = self.ev.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.ev.tcx.hir().local_def_id_to_hir_id(def_id);
if let ((ty::Visibility::Public, ..), _)
| (_, Some(AccessLevel::ReachableFromImplTrait)) =
(def_id_visibility(self.tcx(), def_id.to_def_id()), self.access_level)
if let Some(did) = did.as_local() {
// .. and it corresponds to a private type in the AST (this returns
// `None` for type parameters).
- match self.tcx.hir().find(self.tcx.hir().as_local_hir_id(did)) {
+ match self.tcx.hir().find(self.tcx.hir().local_def_id_to_hir_id(did)) {
Some(Node::Item(ref item)) => !item.vis.node.is_pub(),
Some(_) | None => false,
}
let did = tr.path.res.def_id();
if let Some(did) = did.as_local() {
- self.trait_is_public(self.tcx.hir().as_local_hir_id(did))
+ self.trait_is_public(self.tcx.hir().local_def_id_to_hir_id(did))
} else {
true // external traits must be public
}
}
let hir_id = match def_id.as_local() {
- Some(def_id) => self.tcx.hir().as_local_hir_id(def_id),
+ Some(def_id) => self.tcx.hir().local_def_id_to_hir_id(def_id),
None => return false,
};
let ret = self.required_visibility == ty::Visibility::Public
&& self.tcx.is_private_dep(item_id.krate);
- log::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
+ tracing::debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
ret
}
}
[dependencies]
rustc_arena = { path = "../librustc_arena" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc-rayon-core = "0.3.0"
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
+rustc_macros = { path = "../librustc_macros" }
rustc_index = { path = "../librustc_index" }
rustc_serialize = { path = "../librustc_serialize" }
rustc_span = { path = "../librustc_span" }
use std::fmt;
use std::hash::Hash;
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
pub struct DepNode<K> {
pub kind: K,
pub hash: Fingerprint,
/// some independent path or string that persists between runs without
/// the need to be mapped or unmapped. (This ensures we can serialize
/// them even in the absence of a tcx.)
-#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Encodable, Decodable)]
pub struct WorkProductId {
hash: Fingerprint,
}
/// may be added -- for example, new monomorphizations -- even if
/// nothing in P changed!). We will compare that hash against the
/// previous hash. If it matches up, we can reuse the object file.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Encodable, Decodable)]
pub struct WorkProduct {
pub cgu_name: String,
/// Saved file associated with this CGU.
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
pub struct PreviousDepGraph<K: DepKind> {
data: SerializedDepGraph<K>,
index: FxHashMap<DepNode<K>, SerializedDepNodeIndex>,
}
/// Data for use when recompiling the **current crate**.
-#[derive(Debug, RustcEncodable, RustcDecodable)]
+#[derive(Debug, Encodable, Decodable)]
pub struct SerializedDepGraph<K: DepKind> {
/// The set of all DepNodes in the graph
pub nodes: IndexVec<SerializedDepNodeIndex, DepNode<K>>,
#![feature(stmt_expr_attributes)]
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_data_structures;
+#[macro_use]
+extern crate rustc_macros;
pub mod cache;
pub mod dep_graph;
OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R,
OnMiss: FnOnce(Self::Key, QueryLookup<'_, CTX, Self::Key, Self::Sharded>) -> R;
- fn complete<CTX: QueryContext>(
+ fn complete(
&self,
- tcx: CTX,
lock_sharded_storage: &mut Self::Sharded,
key: Self::Key,
value: Self::Value,
}
#[inline]
- fn complete<CTX: QueryContext>(
+ fn complete(
&self,
- _: CTX,
lock_sharded_storage: &mut Self::Sharded,
key: K,
value: V,
}
#[inline]
- fn complete<CTX: QueryContext>(
+ fn complete(
&self,
- _: CTX,
lock_sharded_storage: &mut Self::Sharded,
key: K,
value: V,
/// Completes the query by updating the query cache with the `result`,
/// signals the waiter and forgets the JobOwner, so it won't poison the query
#[inline(always)]
- fn complete(self, tcx: CTX, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
+ fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
// We can move out of `self` here because we `mem::forget` it below
let key = unsafe { ptr::read(&self.key) };
let state = self.state;
QueryResult::Started(job) => job,
QueryResult::Poisoned => panic!(),
};
- let result = state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index);
+ let result = state.cache.complete(&mut lock.cache, key, result, dep_node_index);
(job, result)
};
tcx.store_diagnostics_for_anon_node(dep_node_index, diagnostics);
}
- return job.complete(tcx, result, dep_node_index);
+ return job.complete(result, dep_node_index);
}
let dep_node = query.to_dep_node(tcx, &key);
})
});
if let Some((result, dep_node_index)) = loaded {
- return job.complete(tcx, result, dep_node_index);
+ return job.complete(result, dep_node_index);
}
}
}
}
- let result = job.complete(tcx, result, dep_node_index);
+ let result = job.complete(result, dep_node_index);
(result, dep_node_index)
}
[dependencies]
bitflags = "1.2.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_ast = { path = "../librustc_ast" }
rustc_arena = { path = "../librustc_arena" }
rustc_middle = { path = "../librustc_middle" }
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
-use log::debug;
use std::cell::Cell;
use std::ptr;
+use tracing::debug;
type Res = def::Res<NodeId>;
use crate::Resolver;
-use log::debug;
use rustc_ast::ast::*;
use rustc_ast::token::{self, Token};
use rustc_ast::visit::{self, FnKind};
use rustc_span::hygiene::ExpnId;
use rustc_span::symbol::{kw, sym};
use rustc_span::Span;
+use tracing::debug;
crate fn collect_definitions(
resolver: &mut Resolver<'_>,
use std::cmp::Reverse;
use std::ptr;
-use log::debug;
use rustc_ast::ast::{self, Path};
use rustc_ast::util::lev_distance::find_best_match_for_name;
use rustc_ast_pretty::pprust;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, MultiSpan, Span};
+use tracing::debug;
use crate::imports::{Import, ImportKind, ImportResolver};
use crate::path_names_to_string;
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_span::{MultiSpan, Span};
-use log::*;
+use tracing::*;
use std::cell::Cell;
use std::{mem, ptr};
use rustc_span::Span;
use smallvec::{smallvec, SmallVec};
-use log::debug;
use rustc_span::source_map::{respan, Spanned};
use std::collections::BTreeSet;
use std::mem::{replace, take};
+use tracing::debug;
mod diagnostics;
crate mod lifetimes;
source: PathSource<'ast>,
crate_lint: CrateLint,
) -> PartialRes {
- log::debug!("smart_resolve_path_fragment(id={:?},qself={:?},path={:?}", id, qself, path);
+ tracing::debug!(
+ "smart_resolve_path_fragment(id={:?},qself={:?},path={:?}",
+ id,
+ qself,
+ path
+ );
let ns = source.namespace();
let is_expected = &|res| source.is_expected(res);
use rustc_ast::ast::{self, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind};
use rustc_ast::util::lev_distance::find_best_match_for_name;
+use rustc_ast::visit::FnKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Span, DUMMY_SP};
-use log::debug;
+use tracing::debug;
type Res = def::Res<ast::NodeId>;
let code = source.error_code(res.is_some());
let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code);
+ let is_assoc_fn = self.self_type_is_available(span);
// Emit help message for fake-self from other languages (e.g., `this` in Javascript).
- if ["this", "my"].contains(&&*item_str.as_str())
- && self.self_value_is_available(path[0].ident.span, span)
- {
+ if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn {
err.span_suggestion_short(
span,
"you might have meant to use `self` here instead",
"self".to_string(),
Applicability::MaybeIncorrect,
);
+ if !self.self_value_is_available(path[0].ident.span, span) {
+ if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) =
+ &self.diagnostic_metadata.current_function
+ {
+ let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
+ (param.span.shrink_to_lo(), "&self, ")
+ } else {
+ (
+ self.r
+ .session
+ .source_map()
+ .span_through_char(*fn_span, '(')
+ .shrink_to_hi(),
+ "&self",
+ )
+ };
+ err.span_suggestion_verbose(
+ span,
+ "if you meant to use `self`, you are also missing a `self` receiver \
+ argument",
+ sugg.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
}
// Emit special messages for unresolved `Self` and `self`.
if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) {
err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
} else {
- err.span_label(*span, "this function doesn't have a `self` parameter");
+ let doesnt = if is_assoc_fn {
+ let (span, sugg) = fn_kind
+ .decl()
+ .inputs
+ .get(0)
+ .map(|p| (p.span.shrink_to_lo(), "&self, "))
+ .unwrap_or_else(|| {
+ (
+ self.r
+ .session
+ .source_map()
+ .span_through_char(*span, '(')
+ .shrink_to_hi(),
+ "&self",
+ )
+ });
+ err.span_suggestion_verbose(
+ span,
+ "add a `self` receiver parameter to make the associated `fn` a method",
+ sugg.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ "doesn't"
+ } else {
+ "can't"
+ };
+ if let Some(ident) = fn_kind.ident() {
+ err.span_label(
+ ident.span,
+ &format!("this function {} have a `self` parameter", doesnt),
+ );
+ }
}
}
return (err, Vec::new());
use std::cell::Cell;
use std::mem::take;
-use log::debug;
+use tracing::debug;
// This counts the no of times a lifetime is used
#[derive(Clone, Copy, Debug)]
let def = self.map.defs.get(&lifetime.hir_id).cloned();
if let Some(Region::LateBound(_, def_id, _)) = def {
if let Some(def_id) = def_id.as_local() {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// Ensure that the parent of the def is an item, not HRTB
let parent_id = self.tcx.hir().get_parent_node(hir_id);
let parent_impl_id = hir::ImplItemId { hir_id: parent_id };
if let Some(def) =
lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0()))
{
- let hir_id = tcx.hir().as_local_hir_id(def.id().unwrap().expect_local());
+ let hir_id =
+ tcx.hir().local_def_id_to_hir_id(def.id().unwrap().expect_local());
signal_shadowing_problem(
tcx,
match lifetimeuseset {
Some(LifetimeUseSet::One(lifetime)) => {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
debug!("hir id first={:?}", hir_id);
if let Some((id, span, name)) = match self.tcx.hir().get(hir_id) {
Node::Lifetime(hir_lifetime) => Some((
if let Some(parent_def_id) = self.tcx.parent(def_id) {
if let Some(def_id) = parent_def_id.as_local() {
- let parent_hir_id = self.tcx.hir().as_local_hir_id(def_id);
+ let parent_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
// lifetimes in `derive` expansions don't count (Issue #53738)
if self.tcx.hir().attrs(parent_hir_id).iter().any(|attr| {
self.tcx.sess.check_name(attr, sym::automatically_derived)
debug!("not one use lifetime");
}
None => {
- let hir_id = self.tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
if let Some((id, span, name)) = match self.tcx.hir().get(hir_id) {
Node::Lifetime(hir_lifetime) => Some((
hir_lifetime.hir_id,
let map = &self.map;
let unsubst = if let Some(def_id) = def_id.as_local() {
- let id = self.tcx.hir().as_local_hir_id(def_id);
+ let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
&map.object_lifetime_defaults[&id]
} else {
let tcx = self.tcx;
Scope::Binder { ref lifetimes, s, .. } => {
if let Some(&def) = lifetimes.get(¶m.name.normalize_to_macros_2_0()) {
let hir_id =
- self.tcx.hir().as_local_hir_id(def.id().unwrap().expect_local());
+ self.tcx.hir().local_def_id_to_hir_id(def.id().unwrap().expect_local());
signal_shadowing_problem(
self.tcx,
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
-use log::debug;
use std::cell::{Cell, RefCell};
use std::collections::BTreeSet;
use std::{cmp, fmt, iter, ptr};
+use tracing::debug;
use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
path = "lib.rs"
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_ast = { path = "../librustc_ast" }
rustc_ast_pretty = { path = "../librustc_ast_pretty" }
RefKind, Relation, RelationKind, SpanData,
};
-use log::{debug, error};
+use tracing::{debug, error};
macro_rules! down_cast_data {
($id:ident, $kind:ident, $sp:expr) => {
RefKind, Relation, RelationKind, SpanData,
};
-use log::{debug, error, info};
+use tracing::{debug, error, info};
pub struct SaveContext<'tcx> {
tcx: TyCtxt<'tcx>,
[dependencies]
indexmap = "1"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+
+[dev-dependencies]
+rustc_macros = { path = "../librustc_macros" }
use smallvec::{Array, SmallVec};
-impl<A: Array<Item: Encodable>> Encodable for SmallVec<A> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
}
-impl<A: Array<Item: Decodable>> Decodable for SmallVec<A> {
- fn decode<D: Decoder>(d: &mut D) -> Result<SmallVec<A>, D::Error> {
+impl<D: Decoder, A: Array<Item: Decodable<D>>> Decodable<D> for SmallVec<A> {
+ fn decode(d: &mut D) -> Result<SmallVec<A>, D::Error> {
d.read_seq(|d, len| {
let mut vec = SmallVec::with_capacity(len);
// FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
}
}
-impl<T: Encodable> Encodable for LinkedList<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for LinkedList<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
}
-impl<T: Decodable> Decodable for LinkedList<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for LinkedList<T> {
+ fn decode(d: &mut D) -> Result<LinkedList<T>, D::Error> {
d.read_seq(|d, len| {
let mut list = LinkedList::new();
for i in 0..len {
}
}
-impl<T: Encodable> Encodable for VecDeque<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for VecDeque<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
}
-impl<T: Decodable> Decodable for VecDeque<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for VecDeque<T> {
+ fn decode(d: &mut D) -> Result<VecDeque<T>, D::Error> {
d.read_seq(|d, len| {
let mut deque: VecDeque<T> = VecDeque::with_capacity(len);
for i in 0..len {
}
}
-impl<K, V> Encodable for BTreeMap<K, V>
+impl<S: Encoder, K, V> Encodable<S> for BTreeMap<K, V>
where
- K: Encodable + PartialEq + Ord,
- V: Encodable,
+ K: Encodable<S> + PartialEq + Ord,
+ V: Encodable<S>,
{
- fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+ fn encode(&self, e: &mut S) -> Result<(), S::Error> {
e.emit_map(self.len(), |e| {
for (i, (key, val)) in self.iter().enumerate() {
e.emit_map_elt_key(i, |e| key.encode(e))?;
}
}
-impl<K, V> Decodable for BTreeMap<K, V>
+impl<D: Decoder, K, V> Decodable<D> for BTreeMap<K, V>
where
- K: Decodable + PartialEq + Ord,
- V: Decodable,
+ K: Decodable<D> + PartialEq + Ord,
+ V: Decodable<D>,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
+ fn decode(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
d.read_map(|d, len| {
let mut map = BTreeMap::new();
for i in 0..len {
}
}
-impl<T> Encodable for BTreeSet<T>
+impl<S: Encoder, T> Encodable<S> for BTreeSet<T>
where
- T: Encodable + PartialEq + Ord,
+ T: Encodable<S> + PartialEq + Ord,
{
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
}
-impl<T> Decodable for BTreeSet<T>
+impl<D: Decoder, T> Decodable<D> for BTreeSet<T>
where
- T: Decodable + PartialEq + Ord,
+ T: Decodable<D> + PartialEq + Ord,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
+ fn decode(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
d.read_seq(|d, len| {
let mut set = BTreeSet::new();
for i in 0..len {
}
}
-impl<K, V, S> Encodable for HashMap<K, V, S>
+impl<E: Encoder, K, V, S> Encodable<E> for HashMap<K, V, S>
where
- K: Encodable + Eq,
- V: Encodable,
+ K: Encodable<E> + Eq,
+ V: Encodable<E>,
S: BuildHasher,
{
- fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
e.emit_map(self.len(), |e| {
for (i, (key, val)) in self.iter().enumerate() {
e.emit_map_elt_key(i, |e| key.encode(e))?;
}
}
-impl<K, V, S> Decodable for HashMap<K, V, S>
+impl<D: Decoder, K, V, S> Decodable<D> for HashMap<K, V, S>
where
- K: Decodable + Hash + Eq,
- V: Decodable,
+ K: Decodable<D> + Hash + Eq,
+ V: Decodable<D>,
S: BuildHasher + Default,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
+ fn decode(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
d.read_map(|d, len| {
let state = Default::default();
let mut map = HashMap::with_capacity_and_hasher(len, state);
}
}
-impl<T, S> Encodable for HashSet<T, S>
+impl<E: Encoder, T, S> Encodable<E> for HashSet<T, S>
where
- T: Encodable + Eq,
+ T: Encodable<E> + Eq,
S: BuildHasher,
{
- fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
}
-impl<T, S> Decodable for HashSet<T, S>
+impl<E: Encoder, T, S> Encodable<E> for &HashSet<T, S>
where
- T: Decodable + Hash + Eq,
+ T: Encodable<E> + Eq,
+ S: BuildHasher,
+{
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+ (**self).encode(s)
+ }
+}
+
+impl<D: Decoder, T, S> Decodable<D> for HashSet<T, S>
+where
+ T: Decodable<D> + Hash + Eq,
S: BuildHasher + Default,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
+ fn decode(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
d.read_seq(|d, len| {
let state = Default::default();
let mut set = HashSet::with_capacity_and_hasher(len, state);
}
}
-impl<K, V, S> Encodable for indexmap::IndexMap<K, V, S>
+impl<E: Encoder, K, V, S> Encodable<E> for indexmap::IndexMap<K, V, S>
where
- K: Encodable + Hash + Eq,
- V: Encodable,
+ K: Encodable<E> + Hash + Eq,
+ V: Encodable<E>,
S: BuildHasher,
{
- fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
e.emit_map(self.len(), |e| {
for (i, (key, val)) in self.iter().enumerate() {
e.emit_map_elt_key(i, |e| key.encode(e))?;
}
}
-impl<K, V, S> Decodable for indexmap::IndexMap<K, V, S>
+impl<D: Decoder, K, V, S> Decodable<D> for indexmap::IndexMap<K, V, S>
where
- K: Decodable + Hash + Eq,
- V: Decodable,
+ K: Decodable<D> + Hash + Eq,
+ V: Decodable<D>,
S: BuildHasher + Default,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error> {
+ fn decode(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error> {
d.read_map(|d, len| {
let state = Default::default();
let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state);
}
}
-impl<T, S> Encodable for indexmap::IndexSet<T, S>
+impl<E: Encoder, T, S> Encodable<E> for indexmap::IndexSet<T, S>
where
- T: Encodable + Hash + Eq,
+ T: Encodable<E> + Hash + Eq,
S: BuildHasher,
{
- fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
}
-impl<T, S> Decodable for indexmap::IndexSet<T, S>
+impl<D: Decoder, T, S> Decodable<D> for indexmap::IndexSet<T, S>
where
- T: Decodable + Hash + Eq,
+ T: Decodable<D> + Hash + Eq,
S: BuildHasher + Default,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
+ fn decode(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
d.read_seq(|d, len| {
let state = Default::default();
let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state);
}
}
-impl<T: Encodable> Encodable for Rc<[T]> {
- fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
for (index, e) in self.iter().enumerate() {
s.emit_seq_elt(index, |s| e.encode(s))?;
}
}
-impl<T: Decodable> Decodable for Rc<[T]> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Rc<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
+ fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
d.read_seq(|d, len| {
let mut vec = Vec::with_capacity(len);
for index in 0..len {
}
}
-impl<T: Encodable> Encodable for Arc<[T]> {
- fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
for (index, e) in self.iter().enumerate() {
s.emit_seq_elt(index, |s| e.encode(s))?;
}
}
-impl<T: Decodable> Decodable for Arc<[T]> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Arc<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
+ fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
d.read_seq(|d, len| {
let mut vec = Vec::with_capacity(len);
for index in 0..len {
//!
//! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via
//! the serialization API.
-//! To be able to encode a piece of data, it must implement the `serialize::RustcEncodable` trait.
-//! To be able to decode a piece of data, it must implement the `serialize::RustcDecodable` trait.
+//! To be able to encode a piece of data, it must implement the `serialize::Encodable` trait.
+//! To be able to decode a piece of data, it must implement the `serialize::Decodable` trait.
//! The Rust compiler provides an annotation to automatically generate the code for these traits:
-//! `#[derive(RustcDecodable, RustcEncodable)]`
+//! `#[derive(Decodable, Encodable)]`
//!
//! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects.
//! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value.
//! A `json::Json` value can be encoded as a string or buffer using the functions described above.
//! You can also use the `json::Encoder` object, which implements the `Encoder` trait.
//!
-//! When using `ToJson` the `RustcEncodable` trait implementation is not mandatory.
+//! When using `ToJson` the `Encodable` trait implementation is not mandatory.
//!
//! # Examples of use
//!
//!
//! ```rust
//! # #![feature(rustc_private)]
+//! use rustc_macros::{Decodable, Encodable};
//! use rustc_serialize::json;
//!
//! // Automatically generate `Decodable` and `Encodable` trait implementations
-//! #[derive(RustcDecodable, RustcEncodable)]
+//! #[derive(Decodable, Encodable)]
//! pub struct TestStruct {
//! data_int: u8,
//! data_str: String,
//!
//! ```rust
//! # #![feature(rustc_private)]
+//! use rustc_macros::Encodable;
//! use rustc_serialize::json::{self, ToJson, Json};
//!
//! // A custom data structure
//! }
//! }
//!
-//! // Only generate `RustcEncodable` trait implementation
-//! #[derive(RustcEncodable)]
+//! // Only generate `Encodable` trait implementation
+//! #[derive(Encodable)]
//! pub struct ComplexNumRecord {
//! uid: u8,
//! dsc: String,
//!
//! ```rust
//! # #![feature(rustc_private)]
+//! use rustc_macros::Decodable;
//! use std::collections::BTreeMap;
//! use rustc_serialize::json::{self, Json, ToJson};
//!
-//! // Only generate `RustcDecodable` trait implementation
-//! #[derive(RustcDecodable)]
+//! // Only generate `Decodable` trait implementation
+//! #[derive(Decodable)]
//! pub struct TestStruct {
//! data_int: u8,
//! data_str: String,
}
/// Shortcut function to decode a JSON `&str` into an object
-pub fn decode<T: crate::Decodable>(s: &str) -> DecodeResult<T> {
+pub fn decode<T: crate::Decodable<Decoder>>(s: &str) -> DecodeResult<T> {
let json = match from_str(s) {
Ok(x) => x,
Err(e) => return Err(ParseError(e)),
}
/// Shortcut function to encode a `T` into a JSON `String`
-pub fn encode<T: crate::Encodable>(object: &T) -> Result<string::String, EncoderError> {
+pub fn encode<T: for<'r> crate::Encodable<Encoder<'r>>>(
+ object: &T,
+) -> Result<string::String, EncoderError> {
let mut s = String::new();
{
let mut encoder = Encoder::new(&mut s);
}
}
-impl Encodable for Json {
- fn encode<E: crate::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+impl<E: crate::Encoder> Encodable<E> for Json {
+ fn encode(&self, e: &mut E) -> Result<(), E::Error> {
match *self {
Json::I64(v) => v.encode(e),
Json::U64(v) => v.encode(e),
}
}
-impl<'a, T: Encodable> fmt::Display for AsJson<'a, T> {
+impl<'a, T: for<'r> Encodable<Encoder<'r>>> fmt::Display for AsJson<'a, T> {
/// Encodes a json value into a string
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut shim = FormatShim { inner: f };
}
}
-impl<'a, T: Encodable> fmt::Display for AsPrettyJson<'a, T> {
+impl<'a, T: for<'x> Encodable<PrettyEncoder<'x>>> fmt::Display for AsPrettyJson<'a, T> {
/// Encodes a json value into a string
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut shim = FormatShim { inner: f };
test(attr(allow(unused_variables), deny(warnings)))
)]
#![feature(box_syntax)]
-#![feature(min_specialization)]
#![feature(never_type)]
#![feature(nll)]
#![feature(associated_type_bounds)]
pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};
-pub use self::serialize::{SpecializationError, SpecializedDecoder, SpecializedEncoder};
-pub use self::serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
-
mod collection_impls;
mod serialize;
Core encoding and decoding interfaces.
*/
-use std::any;
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;
fn error(&mut self, err: &str) -> Self::Error;
}
-pub trait Encodable {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>;
-}
-
-pub trait Decodable: Sized {
- fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error>;
-}
-
-impl Encodable for usize {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_usize(*self)
- }
-}
-
-impl Decodable for usize {
- fn decode<D: Decoder>(d: &mut D) -> Result<usize, D::Error> {
- d.read_usize()
- }
-}
-
-impl Encodable for u8 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u8(*self)
- }
-}
-
-impl Decodable for u8 {
- fn decode<D: Decoder>(d: &mut D) -> Result<u8, D::Error> {
- d.read_u8()
- }
-}
-
-impl Encodable for u16 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u16(*self)
- }
-}
-
-impl Decodable for u16 {
- fn decode<D: Decoder>(d: &mut D) -> Result<u16, D::Error> {
- d.read_u16()
- }
-}
-
-impl Encodable for u32 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u32(*self)
- }
+/// Trait for types that can be serialized
+///
+/// This can be implemented using the `Encodable`, `TyEncodable` and
+/// `MetadataEncodable` macros.
+///
+/// * `Encodable` should be used in crates that don't depend on
+/// `rustc_middle`.
+/// * `MetadataEncodable` is used in `rustc_metadata` for types that contain
+/// `rustc_metadata::rmeta::Lazy`.
+/// * `TyEncodable` should be used for types that are only serialized in crate
+/// metadata or the incremental cache. This is most types in `rustc_middle`.
+pub trait Encodable<S: Encoder> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error>;
}
-impl Decodable for u32 {
- fn decode<D: Decoder>(d: &mut D) -> Result<u32, D::Error> {
- d.read_u32()
- }
-}
+/// Trait for types that can be deserialized
+///
+/// This can be implemented using the `Decodable`, `TyDecodable` and
+/// `MetadataDecodable` macros.
+///
+/// * `Decodable` should be used in crates that don't depend on
+/// `rustc_middle`.
+/// * `MetadataDecodable` is used in `rustc_metadata` for types that contain
+/// `rustc_metadata::rmeta::Lazy`.
+/// * `TyDecodable` should be used for types that are only serialized in crate
+/// metadata or the incremental cache. This is most types in `rustc_middle`.
+pub trait Decodable<D: Decoder>: Sized {
+ fn decode(d: &mut D) -> Result<Self, D::Error>;
+}
+
+macro_rules! direct_serialize_impls {
+ ($($ty:ident $emit_method:ident $read_method:ident),*) => {
+ $(
+ impl<S: Encoder> Encodable<S> for $ty {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+ s.$emit_method(*self)
+ }
+ }
-impl Encodable for ::std::num::NonZeroU32 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ impl<D: Decoder> Decodable<D> for $ty {
+ fn decode(d: &mut D) -> Result<$ty, D::Error> {
+ d.$read_method()
+ }
+ }
+ )*
+ }
+}
+
+direct_serialize_impls! {
+ usize emit_usize read_usize,
+ u8 emit_u8 read_u8,
+ u16 emit_u16 read_u16,
+ u32 emit_u32 read_u32,
+ u64 emit_u64 read_u64,
+ u128 emit_u128 read_u128,
+ isize emit_isize read_isize,
+ i8 emit_i8 read_i8,
+ i16 emit_i16 read_i16,
+ i32 emit_i32 read_i32,
+ i64 emit_i64 read_i64,
+ i128 emit_i128 read_i128,
+ f32 emit_f32 read_f32,
+ f64 emit_f64 read_f64,
+ bool emit_bool read_bool,
+ char emit_char read_char
+}
+
+impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u32(self.get())
}
}
-impl Decodable for ::std::num::NonZeroU32 {
- fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
+impl<D: Decoder> Decodable<D> for ::std::num::NonZeroU32 {
+ fn decode(d: &mut D) -> Result<Self, D::Error> {
d.read_u32().map(|d| ::std::num::NonZeroU32::new(d).unwrap())
}
}
-impl Encodable for u64 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u64(*self)
- }
-}
-
-impl Decodable for u64 {
- fn decode<D: Decoder>(d: &mut D) -> Result<u64, D::Error> {
- d.read_u64()
- }
-}
-
-impl Encodable for u128 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_u128(*self)
- }
-}
-
-impl Decodable for u128 {
- fn decode<D: Decoder>(d: &mut D) -> Result<u128, D::Error> {
- d.read_u128()
- }
-}
-
-impl Encodable for isize {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_isize(*self)
- }
-}
-
-impl Decodable for isize {
- fn decode<D: Decoder>(d: &mut D) -> Result<isize, D::Error> {
- d.read_isize()
- }
-}
-
-impl Encodable for i8 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_i8(*self)
- }
-}
-
-impl Decodable for i8 {
- fn decode<D: Decoder>(d: &mut D) -> Result<i8, D::Error> {
- d.read_i8()
- }
-}
-
-impl Encodable for i16 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_i16(*self)
- }
-}
-
-impl Decodable for i16 {
- fn decode<D: Decoder>(d: &mut D) -> Result<i16, D::Error> {
- d.read_i16()
- }
-}
-
-impl Encodable for i32 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_i32(*self)
- }
-}
-
-impl Decodable for i32 {
- fn decode<D: Decoder>(d: &mut D) -> Result<i32, D::Error> {
- d.read_i32()
- }
-}
-
-impl Encodable for i64 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_i64(*self)
- }
-}
-
-impl Decodable for i64 {
- fn decode<D: Decoder>(d: &mut D) -> Result<i64, D::Error> {
- d.read_i64()
- }
-}
-
-impl Encodable for i128 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_i128(*self)
- }
-}
-
-impl Decodable for i128 {
- fn decode<D: Decoder>(d: &mut D) -> Result<i128, D::Error> {
- d.read_i128()
+impl<S: Encoder> Encodable<S> for str {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+ s.emit_str(self)
}
}
-impl Encodable for str {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for &str {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_str(self)
}
}
-impl Encodable for String {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for String {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_str(&self[..])
}
}
-impl Decodable for String {
- fn decode<D: Decoder>(d: &mut D) -> Result<String, D::Error> {
+impl<D: Decoder> Decodable<D> for String {
+ fn decode(d: &mut D) -> Result<String, D::Error> {
Ok(d.read_str()?.into_owned())
}
}
-impl Encodable for f32 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_f32(*self)
- }
-}
-
-impl Decodable for f32 {
- fn decode<D: Decoder>(d: &mut D) -> Result<f32, D::Error> {
- d.read_f32()
- }
-}
-
-impl Encodable for f64 {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_f64(*self)
- }
-}
-
-impl Decodable for f64 {
- fn decode<D: Decoder>(d: &mut D) -> Result<f64, D::Error> {
- d.read_f64()
- }
-}
-
-impl Encodable for bool {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_bool(*self)
- }
-}
-
-impl Decodable for bool {
- fn decode<D: Decoder>(d: &mut D) -> Result<bool, D::Error> {
- d.read_bool()
- }
-}
-
-impl Encodable for char {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_char(*self)
- }
-}
-
-impl Decodable for char {
- fn decode<D: Decoder>(d: &mut D) -> Result<char, D::Error> {
- d.read_char()
- }
-}
-
-impl Encodable for () {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for () {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_unit()
}
}
-impl Decodable for () {
- fn decode<D: Decoder>(d: &mut D) -> Result<(), D::Error> {
+impl<D: Decoder> Decodable<D> for () {
+ fn decode(d: &mut D) -> Result<(), D::Error> {
d.read_nil()
}
}
-impl<T> Encodable for PhantomData<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T> Encodable<S> for PhantomData<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_unit()
}
}
-impl<T> Decodable for PhantomData<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<PhantomData<T>, D::Error> {
+impl<D: Decoder, T> Decodable<D> for PhantomData<T> {
+ fn decode(d: &mut D) -> Result<PhantomData<T>, D::Error> {
d.read_nil()?;
Ok(PhantomData)
}
}
-impl<T: Decodable> Decodable for Box<[T]> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<[T]> {
+ fn decode(d: &mut D) -> Result<Box<[T]>, D::Error> {
let v: Vec<T> = Decodable::decode(d)?;
Ok(v.into_boxed_slice())
}
}
-impl<T: Encodable> Encodable for Rc<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Rc<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
-impl<T: Decodable> Decodable for Rc<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Rc<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
+ fn decode(d: &mut D) -> Result<Rc<T>, D::Error> {
Ok(Rc::new(Decodable::decode(d)?))
}
}
-impl<T: Encodable> Encodable for [T] {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?
}
}
-impl<T: Encodable> Encodable for Vec<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?
}
}
-impl<T: Decodable> Decodable for Vec<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Vec<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
+ fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
d.read_seq(|d, len| {
let mut v = Vec::with_capacity(len);
for i in 0..len {
}
}
-impl Encodable for [u8; 20] {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for [u8; 20] {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?
}
}
-impl Decodable for [u8; 20] {
- fn decode<D: Decoder>(d: &mut D) -> Result<[u8; 20], D::Error> {
+impl<D: Decoder> Decodable<D> for [u8; 20] {
+ fn decode(d: &mut D) -> Result<[u8; 20], D::Error> {
d.read_seq(|d, len| {
assert!(len == 20);
let mut v = [0u8; 20];
}
}
-impl<'a, T: Encodable> Encodable for Cow<'a, [T]>
+impl<'a, S: Encoder, T: Encodable<S>> Encodable<S> for Cow<'a, [T]>
where
[T]: ToOwned<Owned = Vec<T>>,
{
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?
}
}
-impl<T: Decodable + ToOwned> Decodable for Cow<'static, [T]>
+impl<D: Decoder, T: Decodable<D> + ToOwned> Decodable<D> for Cow<'static, [T]>
where
[T]: ToOwned<Owned = Vec<T>>,
{
- fn decode<D: Decoder>(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
+ fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
d.read_seq(|d, len| {
let mut v = Vec::with_capacity(len);
for i in 0..len {
}
}
-impl<T: Encodable> Encodable for Option<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_option(|s| match *self {
None => s.emit_option_none(),
Some(ref v) => s.emit_option_some(|s| v.encode(s)),
}
}
-impl<T: Decodable> Decodable for Option<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Option<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
+ fn decode(d: &mut D) -> Result<Option<T>, D::Error> {
d.read_option(|d, b| if b { Ok(Some(Decodable::decode(d)?)) } else { Ok(None) })
}
}
-impl<T1: Encodable, T2: Encodable> Encodable for Result<T1, T2> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_enum("Result", |s| match *self {
Ok(ref v) => {
s.emit_enum_variant("Ok", 0, 1, |s| s.emit_enum_variant_arg(0, |s| v.encode(s)))
}
}
-impl<T1: Decodable, T2: Decodable> Decodable for Result<T1, T2> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Result<T1, T2>, D::Error> {
+impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> {
+ fn decode(d: &mut D) -> Result<Result<T1, T2>, D::Error> {
d.read_enum("Result", |d| {
d.read_enum_variant(&["Ok", "Err"], |d, disr| match disr {
0 => Ok(Ok(d.read_enum_variant_arg(0, |d| T1::decode(d))?)),
macro_rules! tuple {
() => ();
( $($name:ident,)+ ) => (
- impl<$($name:Decodable),+> Decodable for ($($name,)+) {
+ impl<D: Decoder, $($name: Decodable<D>),+> Decodable<D> for ($($name,)+) {
#[allow(non_snake_case)]
- fn decode<D: Decoder>(d: &mut D) -> Result<($($name,)+), D::Error> {
+ fn decode(d: &mut D) -> Result<($($name,)+), D::Error> {
let len: usize = count!($($name)+);
d.read_tuple(len, |d| {
let mut i = 0;
})
}
}
- impl<$($name:Encodable),+> Encodable for ($($name,)+) {
+ impl<S: Encoder, $($name: Encodable<S>),+> Encodable<S> for ($($name,)+) {
#[allow(non_snake_case)]
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
let ($(ref $name,)+) = *self;
let mut n = 0;
$(let $name = $name; n += 1;)+
tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
-impl Encodable for path::Path {
- fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for path::Path {
+ fn encode(&self, e: &mut S) -> Result<(), S::Error> {
self.to_str().unwrap().encode(e)
}
}
-impl Encodable for path::PathBuf {
- fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for path::PathBuf {
+ fn encode(&self, e: &mut S) -> Result<(), S::Error> {
path::Path::encode(self, e)
}
}
-impl Decodable for path::PathBuf {
- fn decode<D: Decoder>(d: &mut D) -> Result<path::PathBuf, D::Error> {
+impl<D: Decoder> Decodable<D> for path::PathBuf {
+ fn decode(d: &mut D) -> Result<path::PathBuf, D::Error> {
let bytes: String = Decodable::decode(d)?;
Ok(path::PathBuf::from(bytes))
}
}
-impl<T: Encodable + Copy> Encodable for Cell<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S> + Copy> Encodable<S> for Cell<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
self.get().encode(s)
}
}
-impl<T: Decodable + Copy> Decodable for Cell<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Cell<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D> + Copy> Decodable<D> for Cell<T> {
+ fn decode(d: &mut D) -> Result<Cell<T>, D::Error> {
Ok(Cell::new(Decodable::decode(d)?))
}
}
// `encoder.error("attempting to Encode borrowed RefCell")`
// from `encode` when `try_borrow` returns `None`.
-impl<T: Encodable> Encodable for RefCell<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for RefCell<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
self.borrow().encode(s)
}
}
-impl<T: Decodable> Decodable for RefCell<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<RefCell<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for RefCell<T> {
+ fn decode(d: &mut D) -> Result<RefCell<T>, D::Error> {
Ok(RefCell::new(Decodable::decode(d)?))
}
}
-impl<T: Encodable> Encodable for Arc<T> {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: Encodable<S>> Encodable<S> for Arc<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
-impl<T: Decodable> Decodable for Arc<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<Arc<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<T> {
+ fn decode(d: &mut D) -> Result<Arc<T>, D::Error> {
Ok(Arc::new(Decodable::decode(d)?))
}
}
-// ___________________________________________________________________________
-// Specialization-based interface for multi-dispatch Encodable/Decodable.
-
-/// Implement this trait on your `{Encodable,Decodable}::Error` types
-/// to override the default panic behavior for missing specializations.
-pub trait SpecializationError {
- /// Creates an error for a missing method specialization.
- /// Defaults to panicking with type, trait & method names.
- /// `S` is the encoder/decoder state type,
- /// `T` is the type being encoded/decoded, and
- /// the arguments are the names of the trait
- /// and method that should've been overridden.
- fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> Self;
-}
-
-impl<E> SpecializationError for E {
- default fn not_found<S, T: ?Sized>(trait_name: &'static str, method_name: &'static str) -> E {
- panic!(
- "missing specialization: `<{} as {}<{}>>::{}` not overridden",
- any::type_name::<S>(),
- trait_name,
- any::type_name::<T>(),
- method_name
- );
- }
-}
-
-/// Implement this trait on encoders, with `T` being the type
-/// you want to encode (employing `UseSpecializedEncodable`),
-/// using a strategy specific to the encoder.
-pub trait SpecializedEncoder<T: ?Sized + UseSpecializedEncodable>: Encoder {
- /// Encode the value in a manner specific to this encoder state.
- fn specialized_encode(&mut self, value: &T) -> Result<(), Self::Error>;
-}
-
-impl<E: Encoder, T: ?Sized + UseSpecializedEncodable> SpecializedEncoder<T> for E {
- default fn specialized_encode(&mut self, value: &T) -> Result<(), E::Error> {
- value.default_encode(self)
- }
-}
-
-/// Implement this trait on decoders, with `T` being the type
-/// you want to decode (employing `UseSpecializedDecodable`),
-/// using a strategy specific to the decoder.
-pub trait SpecializedDecoder<T: UseSpecializedDecodable>: Decoder {
- /// Decode a value in a manner specific to this decoder state.
- fn specialized_decode(&mut self) -> Result<T, Self::Error>;
-}
-
-impl<D: Decoder, T: UseSpecializedDecodable> SpecializedDecoder<T> for D {
- default fn specialized_decode(&mut self) -> Result<T, D::Error> {
- T::default_decode(self)
- }
-}
-
-/// Implement this trait on your type to get an `Encodable`
-/// implementation which goes through `SpecializedEncoder`.
-pub trait UseSpecializedEncodable {
- /// Defaults to returning an error (see `SpecializationError`).
- fn default_encode<E: Encoder>(&self, _: &mut E) -> Result<(), E::Error> {
- Err(E::Error::not_found::<E, Self>("SpecializedEncoder", "specialized_encode"))
- }
-}
-
-impl<T: ?Sized + UseSpecializedEncodable> Encodable for T {
- default fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
- E::specialized_encode(e, self)
- }
-}
-
-/// Implement this trait on your type to get an `Decodable`
-/// implementation which goes through `SpecializedDecoder`.
-pub trait UseSpecializedDecodable: Sized {
- /// Defaults to returning an error (see `SpecializationError`).
- fn default_decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
- Err(D::Error::not_found::<D, Self>("SpecializedDecoder", "specialized_decode"))
- }
-}
-
-impl<T: UseSpecializedDecodable> Decodable for T {
- default fn decode<D: Decoder>(d: &mut D) -> Result<T, D::Error> {
- D::specialized_decode(d)
- }
-}
-
-// Can't avoid specialization for &T and Box<T> impls,
-// as proxy impls on them are blankets that conflict
-// with the Encodable and Decodable impls above,
-// which only have `default` on their methods
-// for this exact reason.
-// May be fixable in a simpler fashion via the
-// more complex lattice model for specialization.
-impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- (**self).encode(s)
- }
-}
-impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder, T: ?Sized + Encodable<S>> Encodable<S> for Box<T> {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
-impl<T: Decodable> UseSpecializedDecodable for Box<T> {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
+impl<D: Decoder, T: Decodable<D>> Decodable<D> for Box<T> {
+ fn decode(d: &mut D) -> Result<Box<T>, D::Error> {
Ok(box Decodable::decode(d)?)
}
}
-impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {}
-impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {}
from_str, DecodeResult, Decoder, DecoderError, Encoder, EncoderError, Json, JsonEvent, Parser,
StackElement,
};
+use rustc_macros::{Decodable, Encodable};
use rustc_serialize::json;
use rustc_serialize::{Decodable, Encodable};
use std::string;
use Animal::*;
-#[derive(RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Decodable, Eq, PartialEq, Debug)]
struct OptionData {
opt: Option<usize>,
}
);
}
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(PartialEq, Encodable, Decodable, Debug)]
enum Animal {
Dog,
Frog(string::String, isize),
}
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(PartialEq, Encodable, Decodable, Debug)]
struct Inner {
a: (),
b: usize,
c: Vec<string::String>,
}
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Debug)]
+#[derive(PartialEq, Encodable, Decodable, Debug)]
struct Outer {
inner: Vec<Inner>,
}
);
}
-#[derive(RustcDecodable)]
+#[derive(Decodable)]
struct FloatStruct {
f: f64,
a: Vec<f64>,
assert_eq!(from_str("{\n \"foo\":\n \"bar\""), Err(SyntaxError(EOFWhileParsingObject, 3, 8)));
}
-#[derive(RustcDecodable)]
+#[derive(Decodable)]
#[allow(dead_code)]
struct DecodeStruct {
x: f64,
z: string::String,
w: Vec<DecodeStruct>,
}
-#[derive(RustcDecodable)]
+#[derive(Decodable)]
enum DecodeEnum {
A(f64),
B(string::String),
}
-fn check_err<T: Decodable>(to_parse: &'static str, expected: DecoderError) {
+fn check_err<T: Decodable<Decoder>>(to_parse: &'static str, expected: DecoderError) {
let res: DecodeResult<T> = match from_str(to_parse) {
Err(e) => Err(ParseError(e)),
Ok(json) => Decodable::decode(&mut Decoder::new(json)),
#[test]
fn test_hashmap_with_enum_key() {
use std::collections::HashMap;
- #[derive(RustcEncodable, Eq, Hash, PartialEq, RustcDecodable, Debug)]
+ #[derive(Encodable, Eq, Hash, PartialEq, Decodable, Debug)]
enum Enum {
Foo,
#[allow(dead_code)]
#[test]
fn test_encode_hashmap_with_arbitrary_key() {
use std::collections::HashMap;
- #[derive(PartialEq, Eq, Hash, RustcEncodable)]
+ #[derive(PartialEq, Eq, Hash, Encodable)]
struct ArbitraryType(usize);
let mut hm: HashMap<ArbitraryType, bool> = HashMap::new();
hm.insert(ArbitraryType(1), true);
#![allow(rustc::internal)]
+use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{Decoder, Encoder};
use rustc_serialize::{Decodable, Encodable};
use std::fmt::Debug;
-#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
struct Struct {
a: (),
b: u8,
q: Option<u32>,
}
-fn check_round_trip<T: Encodable + Decodable + PartialEq + Debug>(values: Vec<T>) {
+fn check_round_trip<T: Encodable<Encoder> + for<'a> Decodable<Decoder<'a>> + PartialEq + Debug>(
+ values: Vec<T>,
+) {
let mut encoder = Encoder::new(Vec::new());
for value in &values {
- Encodable::encode(&value, &mut encoder).unwrap();
+ Encodable::encode(value, &mut encoder).unwrap();
}
let data = encoder.into_inner();
}]);
}
-#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
enum Enum {
Variant1,
Variant2(usize, f32),
[dependencies]
bitflags = "1.2.1"
getopts = "0.2"
-log = { package = "tracing", version = "0.1" }
+rustc_macros = { path = "../librustc_macros" }
+tracing = "0.1"
rustc_errors = { path = "../librustc_errors" }
rustc_feature = { path = "../librustc_feature" }
rustc_target = { path = "../librustc_target" }
//! compilation. This is used for incremental compilation tests and debug
//! output.
-use log::debug;
use rustc_data_structures::fx::FxHashMap;
use rustc_span::{Span, Symbol};
use std::sync::{Arc, Mutex};
+use tracing::debug;
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub enum CguReuse {
}
bitflags! {
- #[derive(Default, RustcEncodable, RustcDecodable)]
+ #[derive(Default, Encodable, Decodable)]
pub struct SanitizerSet: u8 {
const ADDRESS = 1 << 0;
const LEAK = 1 << 1;
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Encodable, Decodable)]
pub enum SymbolManglingVersion {
Legacy,
V0,
Full,
}
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Encodable, Decodable)]
pub enum OutputType {
Bitcode,
Assembly,
impl_stable_hash_via_hash!(EntryFnType);
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
pub enum CrateType {
Executable,
Dylib,
}
}
};
- log::debug!("got unpretty option: {:?}", first);
+ tracing::debug!("got unpretty option: {:?}", first);
first
}
}
use std::path::{Path, PathBuf};
use crate::search_paths::{PathKind, SearchPath, SearchPathFile};
-use log::debug;
use rustc_fs_util::fix_windows_verbatim_for_gcc;
+use tracing::debug;
#[derive(Copy, Clone)]
pub enum FileMatch {
#[macro_use]
extern crate bitflags;
+#[macro_use]
+extern crate rustc_macros;
pub mod cgu_reuse_tracker;
pub mod utils;
}
}
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, Encodable, Decodable)]
pub enum PathKind {
Native,
Crate,
}
}
/// Delay a span_bug() call until abort_if_errors()
+ #[track_caller]
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.diagnostic().delay_span_bug(sp, msg)
}
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-fuchsia",
+ "x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
const LSAN_SUPPORTED_TARGETS: &[&str] =
&["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
const MSAN_SUPPORTED_TARGETS: &[&str] =
- &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"];
- const TSAN_SUPPORTED_TARGETS: &[&str] =
- &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+ &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
+ const TSAN_SUPPORTED_TARGETS: &[&str] = &[
+ "aarch64-unknown-linux-gnu",
+ "x86_64-apple-darwin",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-linux-gnu",
+ ];
// Sanitizers can only be used on some tested platforms.
for s in sess.opts.debugging_opts.sanitizer {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
pub enum NativeLibKind {
/// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC) included
/// when linking a final binary, but not when archiving an rlib.
scoped-tls = "1.0"
unicode-width = "0.1.4"
cfg-if = "0.1.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
sha-1 = "0.8"
md-5 = "0.8"
use rustc_data_structures::AtomicRef;
use rustc_index::vec::Idx;
use rustc_macros::HashStable_Generic;
-use rustc_serialize::{Decoder, Encoder};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::borrow::Borrow;
use std::fmt;
/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
/// Therefore, make sure to include the context when encode a `CrateNum`.
-impl rustc_serialize::UseSpecializedEncodable for CrateNum {
- fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
- e.emit_u32(self.as_u32())
+impl<E: Encoder> Encodable<E> for CrateNum {
+ default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+ s.emit_u32(self.as_u32())
}
}
-impl rustc_serialize::UseSpecializedDecodable for CrateNum {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
+
+impl<D: Decoder> Decodable<D> for CrateNum {
+ default fn decode(d: &mut D) -> Result<CrateNum, D::Error> {
Ok(CrateNum::from_u32(d.read_u32()?))
}
}
}
}
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, RustcEncodable, RustcDecodable)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
pub struct DefPathHash(pub Fingerprint);
impl Borrow<Fingerprint> for DefPathHash {
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
pub struct DefIndex {
- DEBUG_FORMAT = "DefIndex({})",
+ ENCODABLE = custom // (only encodable in metadata)
+ DEBUG_FORMAT = "DefIndex({})",
/// The crate root is always assigned index 0 by the AST Map code,
/// thanks to `NodeCollector::new`.
const CRATE_DEF_INDEX = 0,
}
}
-impl rustc_serialize::UseSpecializedEncodable for DefIndex {}
-impl rustc_serialize::UseSpecializedDecodable for DefIndex {}
+impl<E: Encoder> Encodable<E> for DefIndex {
+ default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
+ panic!("cannot encode `DefIndex` with `{}`", std::any::type_name::<E>());
+ }
+}
+
+impl<D: Decoder> Decodable<D> for DefIndex {
+ default fn decode(_: &mut D) -> Result<DefIndex, D::Error> {
+ panic!("cannot decode `DefIndex` with `{}`", std::any::type_name::<D>());
+ }
+}
/// A `DefId` identifies a particular *definition*, by combining a crate
/// index and a def index.
}
}
-impl rustc_serialize::UseSpecializedEncodable for DefId {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- let krate = u64::from(self.krate.as_u32());
- let index = u64::from(self.index.as_u32());
- s.emit_u64((krate << 32) | index)
+impl<E: Encoder> Encodable<E> for DefId {
+ default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+ s.emit_struct("DefId", 2, |s| {
+ s.emit_struct_field("krate", 0, |s| self.krate.encode(s))?;
+
+ s.emit_struct_field("index", 1, |s| self.index.encode(s))
+ })
}
}
-impl rustc_serialize::UseSpecializedDecodable for DefId {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
- let def_id = d.read_u64()?;
- let krate = CrateNum::from_u32((def_id >> 32) as u32);
- let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
- Ok(DefId { krate, index })
+
+impl<D: Decoder> Decodable<D> for DefId {
+ default fn decode(d: &mut D) -> Result<DefId, D::Error> {
+ d.read_struct("DefId", 2, |d| {
+ Ok(DefId {
+ krate: d.read_struct_field("krate", 0, Decodable::decode)?,
+ index: d.read_struct_field("index", 1, Decodable::decode)?,
+ })
+ })
}
}
}
}
-impl rustc_serialize::UseSpecializedEncodable for LocalDefId {}
-impl rustc_serialize::UseSpecializedDecodable for LocalDefId {}
+impl<E: Encoder> Encodable<E> for LocalDefId {
+ fn encode(&self, s: &mut E) -> Result<(), E::Error> {
+ self.to_def_id().encode(s)
+ }
+}
+
+impl<D: Decoder> Decodable<D> for LocalDefId {
+ fn decode(d: &mut D) -> Result<LocalDefId, D::Error> {
+ DefId::decode(d).map(|d| d.expect_local())
+ }
+}
impl<CTX: HashStableContext> HashStable<CTX> for DefId {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
use rustc_macros::HashStable_Generic;
/// The edition of the compiler (RFC 2052)
-#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)]
+#[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
#[derive(HashStable_Generic)]
pub enum Edition {
// editions must be kept in order, oldest to newest
use crate::{Span, DUMMY_SP};
use crate::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use log::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_macros::HashStable_Generic;
-use rustc_serialize::{
- Decodable, Decoder, Encodable, Encoder, UseSpecializedDecodable, UseSpecializedEncodable,
-};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fmt;
+use tracing::*;
/// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SyntaxContext(u32);
-#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
+#[derive(Debug, Encodable, Decodable, Clone)]
pub struct SyntaxContextData {
outer_expn: ExpnId,
outer_transparency: Transparency,
/// A property of a macro expansion that determines how identifiers
/// produced by that expansion are resolved.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub enum Transparency {
/// Identifier produced by a transparent expansion is always resolved at call-site.
/// A subset of properties from both macro definition and macro call available through global data.
/// Avoid using this if you have access to the original definition or call structures.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
pub struct ExpnData {
// --- The part unique to each expansion.
/// The kind of this expansion - macro or compiler desugaring.
}
/// Expansion kind.
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum ExpnKind {
/// No expansion, aka root expansion. Only `ExpnId::root()` has this kind.
Root,
}
/// The kind of macro invocation or definition.
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
#[derive(HashStable_Generic)]
pub enum MacroKind {
/// A bang macro `foo!()`.
}
/// The kind of AST transform.
-#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum AstPass {
StdImports,
TestHarness,
}
/// The kind of compiler desugaring.
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum DesugaringKind {
/// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
/// However, we do not want to blame `c` for unreachability but rather say that `i`
}
/// A location in the desugaring of a `for` loop
-#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
pub enum ForLoopLoc {
Head,
IntoIter,
}
}
-impl UseSpecializedEncodable for ExpnId {}
-impl UseSpecializedDecodable for ExpnId {}
-
#[derive(Default)]
pub struct HygieneEncodeContext {
/// All `SyntaxContexts` for which we have written `SyntaxContextData` into crate metadata.
}
Ok(())
}
+
pub fn for_all_data<E, F: FnMut((u32, SyntaxContext, &SyntaxContextData)) -> Result<(), E>>(
mut f: F,
) -> Result<(), E> {
Ok(())
}
+impl<E: Encoder> Encodable<E> for ExpnId {
+ default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
+ panic!("cannot encode `ExpnId` with `{}`", std::any::type_name::<E>());
+ }
+}
+
+impl<D: Decoder> Decodable<D> for ExpnId {
+ default fn decode(_: &mut D) -> Result<Self, D::Error> {
+ panic!("cannot decode `ExpnId` with `{}`", std::any::type_name::<D>());
+ }
+}
+
pub fn for_all_expn_data<E, F: FnMut(u32, &ExpnData) -> Result<(), E>>(mut f: F) -> Result<(), E> {
let all_data = HygieneData::with(|data| data.expn_data.clone());
for (i, data) in all_data.into_iter().enumerate() {
}
}
-impl UseSpecializedEncodable for SyntaxContext {}
-impl UseSpecializedDecodable for SyntaxContext {}
+impl<E: Encoder> Encodable<E> for SyntaxContext {
+ default fn encode(&self, _: &mut E) -> Result<(), E::Error> {
+ panic!("cannot encode `SyntaxContext` with `{}`", std::any::type_name::<E>());
+ }
+}
+
+impl<D: Decoder> Decodable<D> for SyntaxContext {
+ default fn decode(_: &mut D) -> Result<Self, D::Error> {
+ panic!("cannot decode `SyntaxContext` with `{}`", std::any::type_name::<D>());
+ }
+}
#![feature(option_expect_none)]
#![feature(refcell_take)]
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
extern crate rustc_macros;
use rustc_data_structures::AtomicRef;
//
// FIXME: We should use this enum or something like it to get rid of the
// use of magic `/rust/1.x/...` paths across the board.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable_Generic)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
+#[derive(HashStable_Generic, Decodable, Encodable)]
pub enum RealFileName {
Named(PathBuf),
/// For de-virtualized paths (namely paths into libstd that have been mapped
}
/// Differentiates between real files and common virtual files.
-#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
-#[derive(HashStable_Generic)]
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)]
+#[derive(HashStable_Generic, Decodable, Encodable)]
pub enum FileName {
Real(RealFileName),
/// Call to `quote!`.
/// the error, and would be rendered with `^^^`.
/// - They can have a *label*. In this case, the label is written next
/// to the mark in the snippet when we render.
-#[derive(Clone, Debug, Hash, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, Encodable, Decodable)]
pub struct MultiSpan {
primary_spans: Vec<Span>,
span_labels: Vec<(Span, String)>,
}
}
-impl rustc_serialize::UseSpecializedEncodable for Span {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<E: Encoder> Encodable<E> for Span {
+ default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
let span = self.data();
s.emit_struct("Span", 2, |s| {
s.emit_struct_field("lo", 0, |s| span.lo.encode(s))?;
-
s.emit_struct_field("hi", 1, |s| span.hi.encode(s))
})
}
}
-
-impl rustc_serialize::UseSpecializedDecodable for Span {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<Span, D::Error> {
- d.read_struct("Span", 2, |d| {
+impl<D: Decoder> Decodable<D> for Span {
+ default fn decode(s: &mut D) -> Result<Span, D::Error> {
+ s.read_struct("Span", 2, |d| {
let lo = d.read_struct_field("lo", 0, Decodable::decode)?;
let hi = d.read_struct_field("hi", 1, Decodable::decode)?;
- Ok(Span::with_root_ctxt(lo, hi))
+
+ Ok(Span::new(lo, hi, SyntaxContext::root()))
})
}
}
}
/// Identifies an offset of a multi-byte character in a `SourceFile`.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
pub struct MultiByteChar {
/// The absolute offset of the character in the `SourceMap`.
pub pos: BytePos,
}
/// Identifies an offset of a non-narrow character in a `SourceFile`.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
pub enum NonNarrowChar {
/// Represents a zero-width character.
ZeroWidth(BytePos),
}
/// Identifies an offset of a character that was normalized away from `SourceFile`.
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)]
pub struct NormalizedPos {
/// The absolute offset of the character in the `SourceMap`.
pub pos: BytePos,
#[derive(Debug)]
pub struct OffsetOverflowError;
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
pub enum SourceFileHashAlgorithm {
Md5,
Sha1,
rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm);
/// The hash of the on-disk source file used for debug info.
-#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
-#[derive(HashStable_Generic)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
pub struct SourceFileHash {
pub kind: SourceFileHashAlgorithm,
value: [u8; 20],
pub cnum: CrateNum,
}
-impl Encodable for SourceFile {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for SourceFile {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("SourceFile", 8, |s| {
s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
s.emit_struct_field("name_was_remapped", 1, |s| self.name_was_remapped.encode(s))?;
}
}
-impl Decodable for SourceFile {
- fn decode<D: Decoder>(d: &mut D) -> Result<SourceFile, D::Error> {
+impl<D: Decoder> Decodable<D> for SourceFile {
+ fn decode(d: &mut D) -> Result<SourceFile, D::Error> {
d.read_struct("SourceFile", 8, |d| {
let name: FileName = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
let name_was_remapped: bool =
}
}
-impl Encodable for BytePos {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u32(self.0)
}
}
-impl Decodable for BytePos {
- fn decode<D: Decoder>(d: &mut D) -> Result<BytePos, D::Error> {
+impl<D: rustc_serialize::Decoder> Decodable<D> for BytePos {
+ fn decode(d: &mut D) -> Result<BytePos, D::Error> {
Ok(BytePos(d.read_u32()?))
}
}
use std::path::{Path, PathBuf};
use std::sync::atomic::Ordering;
-use log::debug;
use std::fs;
use std::io;
+use tracing::debug;
#[cfg(test)]
mod tests;
impl<T> !DerefMut for MonotonicVec<T> {}
}
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
+#[derive(Clone, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
pub struct Spanned<T> {
pub node: T,
pub span: Span,
// This is a `SourceFile` identifier that is used to correlate `SourceFile`s between
// subsequent compilation sessions (which is something we need to do during
// incremental compilation).
-#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
pub struct StableSourceFileId(u128);
// FIXME: we need a more globally consistent approach to the problem solved by
use rustc_arena::DroplessArena;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_macros::{symbols, HashStable_Generic};
+use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_serialize::{UseSpecializedDecodable, UseSpecializedEncodable};
use std::cmp::{Ord, PartialEq, PartialOrd};
use std::fmt;
}
}
-#[derive(Copy, Clone, Eq, HashStable_Generic)]
+#[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)]
pub struct Ident {
pub name: Symbol,
pub span: Span,
}
}
-impl UseSpecializedEncodable for Ident {
- fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_struct("Ident", 2, |s| {
- s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
- s.emit_struct_field("span", 1, |s| self.span.encode(s))
- })
- }
-}
-
-impl UseSpecializedDecodable for Ident {
- fn default_decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
- d.read_struct("Ident", 2, |d| {
- Ok(Ident {
- name: d.read_struct_field("name", 0, Decodable::decode)?,
- span: d.read_struct_field("span", 1, Decodable::decode)?,
- })
- })
- }
-}
-
/// This is the most general way to print identifiers.
/// AST pretty-printer is used as a fallback for turning AST structures into token streams for
/// proc macros. Additionally, proc macros may stringify their input and expect it survive the
}
}
-impl Encodable for Symbol {
- fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+impl<S: Encoder> Encodable<S> for Symbol {
+ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
self.with(|string| s.emit_str(string))
}
}
-impl Decodable for Symbol {
+impl<D: Decoder> Decodable<D> for Symbol {
#[inline]
- fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
+ fn decode(d: &mut D) -> Result<Symbol, D::Error> {
Ok(Symbol::intern(&d.read_str()?))
}
}
use super::Symbol;
use std::convert::TryInto;
- symbols!();
+ define_symbols!();
// Used from a macro in `librustc_feature/accepted.rs`
pub use super::kw::MacroRules as macro_rules;
doctest = false
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
punycode = "0.4.0"
rustc-demangle = "0.1.16"
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
use rustc_middle::util::common::record_time;
-use log::debug;
+use tracing::debug;
use std::fmt::{self, Write};
use std::mem::{self, discriminant};
use rustc_middle::ty::{self, Instance, TyCtxt};
use rustc_session::config::SymbolManglingVersion;
-use log::debug;
+use tracing::debug;
mod legacy;
mod v0;
let disambiguator = tcx.sess.local_crate_disambiguator();
return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
}
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
match tcx.hir().get(hir_id) {
Node::ForeignItem(_) => true,
_ => false,
[dependencies]
bitflags = "1.2.1"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_macros = { path = "../librustc_macros" }
rustc_serialize = { path = "../librustc_serialize" }
}
/// Size of a type in bytes.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub struct Size {
raw: u64,
}
/// Alignment of a type in bytes (always a power of two).
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub struct Align {
pow2: u8,
}
/// A pair of alignments, ABI-mandated and preferred.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
#[derive(HashStable_Generic)]
pub struct AbiAndPrefAlign {
pub abi: Align,
$class:ident,
)*
}) => {
- #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
+ #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
#[allow(non_camel_case_types)]
pub enum $arch_regclass {
$($class,)*
)*
}) => {
#[allow(unreachable_code)]
- #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
+ #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
#[allow(non_camel_case_types)]
pub enum $arch_reg {
$($reg,)*
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
pub enum InlineAsmArch {
X86,
X86_64,
}
}
-#[derive(
- Copy,
- Clone,
- RustcEncodable,
- RustcDecodable,
- Debug,
- Eq,
- PartialEq,
- Hash,
- HashStable_Generic
-)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
pub enum InlineAsmReg {
X86(X86InlineAsmReg),
Arm(ArmInlineAsmReg),
}
}
-#[derive(
- Copy,
- Clone,
- RustcEncodable,
- RustcDecodable,
- Debug,
- Eq,
- PartialEq,
- Hash,
- HashStable_Generic
-)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
pub enum InlineAsmRegClass {
X86(X86InlineAsmRegClass),
Arm(ArmInlineAsmRegClass),
}
}
-#[derive(
- Copy,
- Clone,
- RustcEncodable,
- RustcDecodable,
- Debug,
- Eq,
- PartialEq,
- Hash,
- HashStable_Generic
-)]
+#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
pub enum InlineAsmRegOrRegClass {
Reg(InlineAsmReg),
RegClass(InlineAsmRegClass),
#![feature(associated_type_bounds)]
#![feature(exhaustive_patterns)]
-// FIXME(#56935): Work around ICEs during cross-compilation.
-#[allow(unused)]
+#[macro_use]
extern crate rustc_macros;
#[macro_use]
-extern crate log;
+extern crate tracing;
pub mod abi;
pub mod asm;
#[cfg(test)]
mod tests;
-#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Clone, Copy, Debug)]
-#[derive(HashStable_Generic)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum Abi {
// N.B., this ordering MUST match the AbiDatas array below.
// (This is ensured by the test indices_are_correct().)
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_gnu_base::opts();
base.cpu = "pentium4".to_string();
+ base.pre_link_args
+ .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
base.max_atomic_width = Some(64);
base.eliminate_frame_pointer = false; // Required for backtraces
base.linker = Some("i686-w64-mingw32-gcc".to_string());
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_uwp_gnu_base::opts();
base.cpu = "pentium4".to_string();
+ base.pre_link_args
+ .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pe".to_string()]);
base.max_atomic_width = Some(64);
base.eliminate_frame_pointer = false; // Required for backtraces
((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
}
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable, HashStable_Generic)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
pub enum PanicStrategy {
Unwind,
Abort,
}
}
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
pub enum RelroLevel {
Full,
Partial,
}
}
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable)]
pub enum MergeFunctions {
Disabled,
Trampolines,
}
/// Either a target triple string or a path to a JSON file.
-#[derive(PartialEq, Clone, Debug, Hash, RustcEncodable, RustcDecodable)]
+#[derive(PartialEq, Clone, Debug, Hash, Encodable, Decodable)]
pub enum TargetTriple {
TargetTriple(String),
TargetPath(PathBuf),
use crate::spec::crt_objects::{self, CrtObjectsFallback};
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
let mut late_link_args_static = LinkArgs::new();
// Order of `late_link_args*` was found through trial and error to work with various
// mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
- late_link_args.insert(
- LinkerFlavor::Gcc,
- vec![
- "-lmsvcrt".to_string(),
- "-lmingwex".to_string(),
- "-lmingw32".to_string(),
- // mingw's msvcrt is a weird hybrid import library and static library.
- // And it seems that the linker fails to use import symbols from msvcrt
- // that are required from functions in msvcrt in certain cases. For example
- // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
- // The library is purposely listed twice to fix that.
- //
- // See https://github.com/rust-lang/rust/pull/47483 for some more details.
- "-lmsvcrt".to_string(),
- "-luser32".to_string(),
- "-lkernel32".to_string(),
- ],
- );
- late_link_args_dynamic.insert(
- LinkerFlavor::Gcc,
- vec![
- // If any of our crates are dynamically linked then we need to use
- // the shared libgcc_s-dw2-1.dll. This is required to support
- // unwinding across DLL boundaries.
- "-lgcc_s".to_string(),
- "-lgcc".to_string(),
- "-lkernel32".to_string(),
- ],
- );
- late_link_args_static.insert(
- LinkerFlavor::Gcc,
- vec![
- // If all of our crates are statically linked then we can get away
- // with statically linking the libgcc unwinding code. This allows
- // binaries to be redistributed without the libgcc_s-dw2-1.dll
- // dependency, but unfortunately break unwinding across DLL
- // boundaries when unwinding across FFI boundaries.
- "-lgcc_eh".to_string(),
- "-l:libpthread.a".to_string(),
- "-lgcc".to_string(),
- // libpthread depends on libmsvcrt, so we need to link it *again*.
- "-lmsvcrt".to_string(),
- "-lkernel32".to_string(),
- ],
- );
+ let mingw_libs = vec![
+ "-lmsvcrt".to_string(),
+ "-lmingwex".to_string(),
+ "-lmingw32".to_string(),
+ // mingw's msvcrt is a weird hybrid import library and static library.
+ // And it seems that the linker fails to use import symbols from msvcrt
+ // that are required from functions in msvcrt in certain cases. For example
+ // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
+ // The library is purposely listed twice to fix that.
+ //
+ // See https://github.com/rust-lang/rust/pull/47483 for some more details.
+ "-lmsvcrt".to_string(),
+ "-luser32".to_string(),
+ "-lkernel32".to_string(),
+ ];
+ late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
+ late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
+ let dynamic_unwind_libs = vec![
+ // If any of our crates are dynamically linked then we need to use
+ // the shared libgcc_s-dw2-1.dll. This is required to support
+ // unwinding across DLL boundaries.
+ "-lgcc_s".to_string(),
+ "-lgcc".to_string(),
+ "-lkernel32".to_string(),
+ ];
+ late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
+ late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
+ let static_unwind_libs = vec![
+ // If all of our crates are statically linked then we can get away
+ // with statically linking the libgcc unwinding code. This allows
+ // binaries to be redistributed without the libgcc_s-dw2-1.dll
+ // dependency, but unfortunately break unwinding across DLL
+ // boundaries when unwinding across FFI boundaries.
+ "-lgcc_eh".to_string(),
+ "-l:libpthread.a".to_string(),
+ "-lgcc".to_string(),
+ // libpthread depends on libmsvcrt, so we need to link it *again*.
+ "-lmsvcrt".to_string(),
+ "-lkernel32".to_string(),
+ ];
+ late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
+ late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);
TargetOptions {
// FIXME(#13846) this should be enabled for windows
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, TargetOptions};
pub fn opts() -> TargetOptions {
let base = super::windows_gnu_base::opts();
let mut late_link_args = LinkArgs::new();
let late_link_args_dynamic = LinkArgs::new();
let late_link_args_static = LinkArgs::new();
- late_link_args.insert(
- LinkerFlavor::Gcc,
- vec![
- //"-lwinstorecompat".to_string(),
- //"-lmingwex".to_string(),
- //"-lwinstorecompat".to_string(),
- "-lwinstorecompat".to_string(),
- "-lruntimeobject".to_string(),
- "-lsynchronization".to_string(),
- "-lvcruntime140_app".to_string(),
- "-lucrt".to_string(),
- "-lwindowsapp".to_string(),
- "-lmingwex".to_string(),
- "-lmingw32".to_string(),
- ],
- );
+ let mingw_libs = vec![
+ //"-lwinstorecompat".to_string(),
+ //"-lmingwex".to_string(),
+ //"-lwinstorecompat".to_string(),
+ "-lwinstorecompat".to_string(),
+ "-lruntimeobject".to_string(),
+ "-lsynchronization".to_string(),
+ "-lvcruntime140_app".to_string(),
+ "-lucrt".to_string(),
+ "-lwindowsapp".to_string(),
+ "-lmingwex".to_string(),
+ "-lmingw32".to_string(),
+ ];
+ late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
+ late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs.clone());
TargetOptions {
executables: false,
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_gnu_base::opts();
base.cpu = "x86-64".to_string();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+ base.pre_link_args
+ .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
base.max_atomic_width = Some(64);
base.linker = Some("x86_64-w64-mingw32-gcc".to_string());
-use crate::spec::{LinkerFlavor, Target, TargetResult};
+use crate::spec::{LinkerFlavor, LldFlavor, Target, TargetResult};
pub fn target() -> TargetResult {
let mut base = super::windows_uwp_gnu_base::opts();
base.cpu = "x86-64".to_string();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
+ base.pre_link_args
+ .insert(LinkerFlavor::Lld(LldFlavor::Ld), vec!["-m".to_string(), "i386pep".to_string()]);
base.max_atomic_width = Some(64);
Ok(Target {
[dependencies]
rustc_parse_format = { path = "../librustc_parse_format" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_attr = { path = "../librustc_attr" }
rustc_middle = { path = "../librustc_middle" }
rustc_ast = { path = "../librustc_ast" }
#[macro_use]
extern crate rustc_data_structures;
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_middle;
// }
// ```
if let Some(def_id) = def_id.as_local() {
- let opaque_hir_id = tcx.hir().as_local_hir_id(def_id);
+ let opaque_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = self.parent_def_id;
let def_scope_default = || {
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
def_id: LocalDefId,
opaque_hir_id: hir::HirId,
) -> bool {
- let mut hir_id = tcx.hir().as_local_hir_id(def_id);
+ let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
// Named opaque types can be defined by any siblings or children of siblings.
let scope = tcx.hir().get_defining_scope(opaque_hir_id);
let clauses = predicates.into_iter().map(ChalkEnvironmentClause::Predicate);
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
enum NodeKind {
self.tcx.sess.source_map().guess_head_span(
self.tcx.hir().span_if_local(closure_def_id).unwrap(),
);
- let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id.expect_local());
+ let hir_id =
+ self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
let mut err = struct_span_err!(
self.tcx.sess,
closure_span,
};
let hir = self.tcx.hir();
- let hir_id = hir.as_local_hir_id(def_id.as_local()?);
+ let hir_id = hir.local_def_id_to_hir_id(def_id.as_local()?);
let parent_node = hir.get_parent_node(hir_id);
match hir.find(parent_node) {
Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
let generator_body = generator_did
.as_local()
- .map(|def_id| hir.as_local_hir_id(def_id))
+ .map(|def_id| hir.local_def_id_to_hir_id(def_id))
.and_then(|hir_id| hir.maybe_body_owned_by(hir_id))
.map(|body_id| hir.body(body_id));
let mut visitor = AwaitsVisitor::default();
.tcx
.parent(generator_did)
.and_then(|parent_did| parent_did.as_local())
- .map(|parent_did| hir.as_local_hir_id(parent_did))
+ .map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
.and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
.map(|name| {
format!("future returned by `{}` is not {}", name, trait_name)
let ty = ty.super_fold_with(self);
match ty.kind {
- ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
- // (*)
+ ty::Opaque(def_id, substs) => {
// Only normalize `impl Trait` after type-checking, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty,
}
ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
- // (*)
-
- // (*) This is kind of hacky -- we need to be able to
+ // This is kind of hacky -- we need to be able to
// handle normalization within binders because
// otherwise we wind up a need to normalize when doing
// trait matching (since you can have a trait
let ty = ty.super_fold_with(self);
match ty.kind {
- ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => {
- // (*)
+ ty::Opaque(def_id, substs) => {
// Only normalize `impl Trait` after type-checking, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty,
}
ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
- // (*)
- // (*) This is kind of hacky -- we need to be able to
+ // This is kind of hacky -- we need to be able to
// handle normalization within binders because
// otherwise we wind up a need to normalize when doing
// trait matching (since you can have a trait
};
tcx.struct_span_lint_hir(
lint,
- tcx.hir().as_local_hir_id(impl_def_id),
+ tcx.hir().local_def_id_to_hir_id(impl_def_id),
impl_span,
decorate,
)
diag.span_label(*sp, format!("referenced here ({})", use_desc));
}
}
- diag.span_label(
- self.bottom().1,
- format!("trait alias used in trait object type ({})", use_desc),
- );
+ if self.top().1 != self.bottom().1 {
+ // When the trait object is in a return type these two spans match, we don't want
+ // redundant labels.
+ diag.span_label(
+ self.bottom().1,
+ format!("trait alias used in trait object type ({})", use_desc),
+ );
+ }
}
pub fn trait_ref(&self) -> ty::PolyTraitRef<'tcx> {
path = "lib.rs"
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_hir = { path = "../librustc_hir" }
#![recursion_limit = "256"]
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_middle;
path = "lib.rs"
[dependencies]
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_errors = { path = "../librustc_errors" }
use rustc_trait_selection::traits;
use traits::{translate_substs, Reveal};
-use log::debug;
+use tracing::debug;
fn resolve_instance<'tcx>(
tcx: TyCtxt<'tcx>,
#[macro_use]
extern crate rustc_middle;
#[macro_use]
-extern crate log;
+extern crate tracing;
use rustc_middle::ty::query::Providers;
}
fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
- let id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let parent_id = tcx.hir().get_parent_item(id);
let parent_def_id = tcx.hir().local_def_id(parent_id);
let parent_item = tcx.hir().expect_item(parent_id);
}
fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item = tcx.hir().expect_item(hir_id);
if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
defaultness
}
fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
- let id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item = tcx.hir().expect_item(id);
match item.kind {
hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
let body_id = def_id
.as_local()
- .map(|def_id| tcx.hir().as_local_hir_id(def_id))
+ .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
.map_or(hir::CRATE_HIR_ID, |id| {
tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id)
});
/// Check if a function is async.
fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
[dependencies]
rustc_arena = { path = "../librustc_arena" }
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
rustc_middle = { path = "../librustc_middle" }
rustc_attr = { path = "../librustc_attr" }
rustc_data_structures = { path = "../librustc_data_structures" }
def: Option<&ty::GenericParamDef>,
) -> ty::Region<'tcx> {
let tcx = self.tcx();
- let lifetime_name = |def_id| tcx.hir().name(tcx.hir().as_local_hir_id(def_id));
+ let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id));
let r = match tcx.named_region(lifetime.hir_id) {
Some(rl::Region::Static) => tcx.lifetimes.re_static,
span: Span,
trait_bounds: &[hir::PolyTraitRef<'_>],
lifetime: &hir::Lifetime,
+ borrowed: bool,
) -> Ty<'tcx> {
let tcx = self.tcx();
"additional use",
);
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
+ err.help(&format!(
+ "consider creating a new trait with all of these as super-traits and using that \
+ trait here instead: `trait NewTrait: {} {{}}`",
+ regular_traits
+ .iter()
+ .map(|t| t.trait_ref().print_only_trait_path().to_string())
+ .collect::<Vec<_>>()
+ .join(" + "),
+ ));
+ err.note(
+ "auto-traits like `Send` and `Sync` are traits that have special properties; \
+ for more information on them, visit \
+ <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
+ );
err.emit();
}
self.ast_region_to_region(lifetime, None)
} else {
self.re_infer(None, span).unwrap_or_else(|| {
- // FIXME: these can be redundant with E0106, but not always.
- struct_span_err!(
+ let mut err = struct_span_err!(
tcx.sess,
span,
E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound"
- )
- .emit();
+ );
+ if borrowed {
+ // We will have already emitted an error E0106 complaining about a
+ // missing named lifetime in `&dyn Trait`, so we elide this one.
+ err.delay_as_bug();
+ } else {
+ err.emit();
+ }
tcx.lifetimes.re_static
})
}
debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
- let param_hir_id = tcx.hir().as_local_hir_id(ty_param_def_id);
+ let param_hir_id = tcx.hir().local_def_id_to_hir_id(ty_param_def_id);
let param_name = tcx.hir().ty_param_name(param_hir_id);
self.one_bound_for_assoc_type(
|| {
let parent_def_id = def_id
.and_then(|def_id| {
- def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id))
+ def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
})
.map(|hir_id| tcx.hir().get_parent_did(hir_id).to_def_id());
assert_eq!(opt_self_ty, None);
self.prohibit_generics(path.segments);
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item_id = tcx.hir().get_parent_node(hir_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
/// Parses the programmer's textual representation of a type into our
/// internal notion of a type.
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
+ self.ast_ty_to_ty_inner(ast_ty, false)
+ }
+
+ /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
+ /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
+ fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> {
debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind);
let tcx = self.tcx();
hir::TyKind::Rptr(ref region, ref mt) => {
let r = self.ast_region_to_region(region, None);
debug!("ast_ty_to_ty: r={:?}", r);
- let t = self.ast_ty_to_ty(&mt.ty);
+ let t = self.ast_ty_to_ty_inner(&mt.ty, true);
tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl })
}
hir::TyKind::Never => tcx.types.never,
))
}
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
- self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
+ self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed)
}
hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
use rustc_infer::infer::{InferOk, InferResult};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, GenericParamDefKind, Ty};
+use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
let generator_types =
check_fn(self, self.param_env, liberated_sig, decl, expr.hir_id, body, gen).1;
- let base_substs = InternalSubsts::identity_for_item(
+ let parent_substs = InternalSubsts::identity_for_item(
self.tcx,
self.tcx.closure_base_def_id(expr_def_id.to_def_id()),
);
- // HACK(eddyb) this hardcodes indices into substs but it should rely on
- // `ClosureSubsts` and `GeneratorSubsts` providing constructors, instead.
- // That would also remove the need for most of the inference variables,
- // as they immediately unified with the actual type below, including
- // the `InferCtxt::closure_sig` and `ClosureSubsts::sig_ty` methods.
- let tupled_upvars_idx = base_substs.len() + if generator_types.is_some() { 4 } else { 2 };
- let substs =
- base_substs.extend_to(self.tcx, expr_def_id.to_def_id(), |param, _| match param.kind {
- GenericParamDefKind::Lifetime => span_bug!(expr.span, "closure has lifetime param"),
- GenericParamDefKind::Type { .. } => if param.index as usize == tupled_upvars_idx {
- self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(
- |upvars| {
- upvars.iter().map(|(&var_hir_id, _)| {
- // Create type variables (for now) to represent the transformed
- // types of upvars. These will be unified during the upvar
- // inference phase (`upvar.rs`).
- self.infcx.next_ty_var(TypeVariableOrigin {
- // FIXME(eddyb) distinguish upvar inference variables from the rest.
- kind: TypeVariableOriginKind::ClosureSynthetic,
- span: self.tcx.hir().span(var_hir_id),
- })
- })
- },
- ))
- } else {
- // Create type variables (for now) to represent the various
- // pieces of information kept in `{Closure,Generic}Substs`.
- // They will either be unified below, or later during the upvar
- // inference phase (`upvar.rs`)
+
+ let tupled_upvars_ty =
+ self.tcx.mk_tup(self.tcx.upvars_mentioned(expr_def_id).iter().flat_map(|upvars| {
+ upvars.iter().map(|(&var_hir_id, _)| {
+ // Create type variables (for now) to represent the transformed
+ // types of upvars. These will be unified during the upvar
+ // inference phase (`upvar.rs`).
self.infcx.next_ty_var(TypeVariableOrigin {
+ // FIXME(eddyb) distinguish upvar inference variables from the rest.
kind: TypeVariableOriginKind::ClosureSynthetic,
- span: expr.span,
+ span: self.tcx.hir().span(var_hir_id),
})
- }
- .into(),
- GenericParamDefKind::Const => span_bug!(expr.span, "closure has const param"),
- });
+ })
+ }));
+
if let Some(GeneratorTypes { resume_ty, yield_ty, interior, movability }) = generator_types
{
- let generator_substs = substs.as_generator();
- self.demand_eqtype(expr.span, resume_ty, generator_substs.resume_ty());
- self.demand_eqtype(expr.span, yield_ty, generator_substs.yield_ty());
- self.demand_eqtype(expr.span, liberated_sig.output(), generator_substs.return_ty());
- self.demand_eqtype(expr.span, interior, generator_substs.witness());
-
- // HACK(eddyb) this forces the types equated above into `substs` but
- // it should rely on `GeneratorSubsts` providing a constructor, instead.
- let substs = self.resolve_vars_if_possible(&substs);
+ let generator_substs = ty::GeneratorSubsts::new(
+ self.tcx,
+ ty::GeneratorSubstsParts {
+ parent_substs,
+ resume_ty,
+ yield_ty,
+ return_ty: liberated_sig.output(),
+ witness: interior,
+ tupled_upvars_ty,
+ },
+ );
- return self.tcx.mk_generator(expr_def_id.to_def_id(), substs, movability);
+ return self.tcx.mk_generator(
+ expr_def_id.to_def_id(),
+ generator_substs.substs,
+ movability,
+ );
}
// Tuple up the arguments and insert the resulting function type into
expr_def_id, sig, opt_kind
);
- let sig_fn_ptr_ty = self.tcx.mk_fn_ptr(sig);
- self.demand_eqtype(expr.span, sig_fn_ptr_ty, substs.as_closure().sig_as_fn_ptr_ty());
+ let closure_kind_ty = match opt_kind {
+ Some(kind) => kind.to_ty(self.tcx),
- if let Some(kind) = opt_kind {
- self.demand_eqtype(expr.span, kind.to_ty(self.tcx), substs.as_closure().kind_ty());
- }
+ // Create a type variable (for now) to represent the closure kind.
+ // It will be unified during the upvar inference phase (`upvar.rs`)
+ None => self.infcx.next_ty_var(TypeVariableOrigin {
+ // FIXME(eddyb) distinguish closure kind inference variables from the rest.
+ kind: TypeVariableOriginKind::ClosureSynthetic,
+ span: expr.span,
+ }),
+ };
- // HACK(eddyb) this forces the types equated above into `substs` but
- // it should rely on `ClosureSubsts` providing a constructor, instead.
- let substs = self.resolve_vars_if_possible(&substs);
+ let closure_substs = ty::ClosureSubsts::new(
+ self.tcx,
+ ty::ClosureSubstsParts {
+ parent_substs,
+ closure_kind_ty,
+ closure_sig_as_fn_ptr_ty: self.tcx.mk_fn_ptr(sig),
+ tupled_upvars_ty,
+ },
+ );
- let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), substs);
+ let closure_type = self.tcx.mk_closure(expr_def_id.to_def_id(), closure_substs.substs);
debug!("check_closure: expr.hir_id={:?} closure_type={:?}", expr.hir_id, closure_type);
let ty = AstConv::ast_ty_to_ty(fcx, ty);
// Get the `impl Trait`'s `DefId`.
if let ty::Opaque(def_id, _) = ty.kind {
- let hir_id = fcx.tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = fcx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
// Get the `impl Trait`'s `Item` so that we can get its trait bounds and
// get the `Trait`'s `DefId`.
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
// This node-id should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`). This is what
// `regionck_item` expects.
- let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id.expect_local());
+ let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
// We sometimes modify the span further down.
let mut cause = ObligationCause::new(
trait_sig: ty::FnSig<'tcx>,
) -> (Span, Option<Span>) {
let tcx = infcx.tcx;
- let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id.expect_local());
+ let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
ImplItemKind::Fn(ref impl_m_sig, _) => {
(&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter())
match *terr {
TypeError::Mutability => {
if let Some(def_id) = trait_m.def_id.as_local() {
- let trait_m_hir_id = tcx.hir().as_local_hir_id(def_id);
+ let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(),
_ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
}
TypeError::Sorts(ExpectedFound { .. }) => {
if let Some(def_id) = trait_m.def_id.as_local() {
- let trait_m_hir_id = tcx.hir().as_local_hir_id(def_id);
+ let trait_m_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let (trait_m_output, trait_m_iter) =
match tcx.hir().expect_trait_item(trait_m_hir_id).kind {
TraitItemKind::Fn(ref trait_m_sig, _) => {
err_occurred = true;
let (trait_spans, impl_trait_spans) = if let Some(def_id) = trait_.def_id.as_local() {
- let trait_hir_id = tcx.hir().as_local_hir_id(def_id);
+ let trait_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
if trait_item.generics.params.is_empty() {
(Some(vec![trait_item.generics.span]), vec![])
(trait_span.map(|s| vec![s]), vec![])
};
- let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id.expect_local());
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_.def_id.expect_local());
let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
let impl_item_impl_trait_spans: Vec<Span> = impl_item
.generics
let impl_number_args = impl_m_fty.inputs().skip_binder().len();
if trait_number_args != impl_number_args {
let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
- let trait_id = tcx.hir().as_local_hir_id(def_id);
+ let trait_id = tcx.hir().local_def_id_to_hir_id(def_id);
match tcx.hir().expect_trait_item(trait_id).kind {
TraitItemKind::Fn(ref trait_m_sig, _) => {
let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
} else {
trait_item_span
};
- let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id.expect_local());
+ let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind {
ImplItemKind::Fn(ref impl_m_sig, _) => {
let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
impl_m_type_params.zip(trait_m_type_params)
{
if impl_synthetic != trait_synthetic {
- let impl_hir_id = tcx.hir().as_local_hir_id(impl_def_id.expect_local());
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_def_id.expect_local());
let impl_span = tcx.hir().span(impl_hir_id);
let trait_span = tcx.def_span(trait_def_id);
let mut err = struct_span_err!(
// FIXME: this is obviously suboptimal since the name can already be used
// as another generic argument
let new_name = tcx.sess.source_map().span_to_snippet(trait_span).ok()?;
- let trait_m = tcx.hir().as_local_hir_id(trait_m.def_id.as_local()?);
+ let trait_m = tcx.hir().local_def_id_to_hir_id(trait_m.def_id.as_local()?);
let trait_m = tcx.hir().trait_item(hir::TraitItemId { hir_id: trait_m });
- let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id.as_local()?);
+ let impl_m = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.as_local()?);
let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
// in case there are no generics, take the spot between the function name
(None, Some(hir::SyntheticTyParamKind::ImplTrait)) => {
err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
(|| {
- let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id.as_local()?);
+ let impl_m = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.as_local()?);
let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m });
let input_tys = match impl_m.kind {
hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
// Create a parameter environment that represents the implementation's
// method.
- let impl_c_hir_id = tcx.hir().as_local_hir_id(impl_c.def_id.expect_local());
+ let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local());
// Compute placeholder form of impl and trait const tys.
let impl_ty = tcx.type_of(impl_c.def_id);
);
let trait_c_hir_id =
- trait_c.def_id.as_local().map(|def_id| tcx.hir().as_local_hir_id(def_id));
+ trait_c.def_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
let trait_c_span = trait_c_hir_id.map(|trait_c_hir_id| {
// Add a label to the Span containing just the type of the const
match tcx.hir().expect_trait_item(trait_c_hir_id).kind {
// This `HirId` should be used for the `body_id` field on each
// `ObligationCause` (and the `FnCtxt`). This is what
// `regionck_item` expects.
- let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
+ let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
let cause = ObligationCause::new(
impl_ty_span,
impl_ty_hir_id,
let infcx = &inh.infcx;
let mut selcx = traits::SelectionContext::new(&infcx);
- let impl_ty_hir_id = tcx.hir().as_local_hir_id(impl_ty.def_id.expect_local());
+ let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_hir_id);
let cause = ObligationCause::new(
impl_ty_span,
}
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
self.suggest_missing_await(err, expr, expected, expr_ty);
+ self.suggest_missing_parentheses(err, expr);
self.note_need_for_fn_pointer(err, expected, expr_ty);
}
drop_impl_ty: Ty<'tcx>,
self_type_did: DefId,
) -> Result<(), ErrorReported> {
- let drop_impl_hir_id = tcx.hir().as_local_hir_id(drop_impl_did);
+ let drop_impl_hir_id = tcx.hir().local_def_id_to_hir_id(drop_impl_did);
// check that the impl type can be made to match the trait type.
// absent. So we report an error that the Drop impl injected a
// predicate that is not present on the struct definition.
- let self_type_hir_id = tcx.hir().as_local_hir_id(self_type_did);
+ let self_type_hir_id = tcx.hir().local_def_id_to_hir_id(self_type_did);
// We can assume the predicates attached to struct/enum definition
// hold.
}
let param_def_id = generic_param.def_id;
let param_hir_id = match param_def_id.as_local() {
- Some(x) => self.tcx.hir().as_local_hir_id(x),
+ Some(x) => self.tcx.hir().local_def_id_to_hir_id(x),
None => return,
};
let param_span = self.tcx.hir().span(param_hir_id);
self.assemble_inherent_impl_for_primitive(lang_def_id);
}
}
+ ty::Array(_, _) => {
+ let lang_def_id = lang_items.array_impl();
+ self.assemble_inherent_impl_for_primitive(lang_def_id);
+ }
ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => {
let (lang_def_id1, lang_def_id2) = match mutbl {
hir::Mutability::Not => {
{
if let ty::Adt(def, _) = p.trait_ref.self_ty().kind {
let node = def.did.as_local().map(|def_id| {
- self.tcx.hir().get(self.tcx.hir().as_local_hir_id(def_id))
+ self.tcx
+ .hir()
+ .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
});
if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
if let Some(g) = kind.generics() {
candidates: Vec<DefId>,
) {
let module_did = self.tcx.parent_module(self.body_id);
- let module_id = self.tcx.hir().as_local_hir_id(module_did);
+ let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
let krate = self.tcx.hir().krate();
let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id);
if let Some(span) = span {
let id = item
.def_id
.as_local()
- .map(|def_id| self.tcx.hir().as_local_hir_id(def_id));
+ .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
if let Some(hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(fn_sig, method),
..
let type_param = generics.type_param(param, self.tcx);
let hir = &self.tcx.hir();
if let Some(def_id) = type_param.def_id.as_local() {
- let id = hir.as_local_hir_id(def_id);
+ let id = hir.local_def_id_to_hir_id(def_id);
// Get the `hir::Param` to verify whether it already has any bounds.
// We do this to avoid suggesting code that ends up as `T: FooBar`,
// instead we suggest `T: Foo + Bar` in that case.
/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
let fallback = move || {
- let span = tcx.hir().span(tcx.hir().as_local_hir_id(def_id));
+ let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
tcx.ty_error_with_message(span, "diagnostic only typeck table used")
};
typeck_with_fallback(tcx, def_id, fallback)
return tcx.typeck(outer_def_id);
}
- let id = tcx.hir().as_local_hir_id(def_id);
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
let span = tcx.hir().span(id);
// Figure out what primary body this item has.
}
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
- let outer_hir_id = hir.as_local_hir_id(outer_def_id);
+ let outer_hir_id = hir.local_def_id_to_hir_id(outer_def_id);
GatherLocalsVisitor { fcx: &fcx, parent_id: outer_hir_id }.visit_body(body);
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// Check that the main return type implements the termination trait.
if let Some(term_id) = tcx.lang_items().termination() {
if let Some((def_id, EntryFnType::Main)) = tcx.entry_fn(LOCAL_CRATE) {
- let main_id = hir.as_local_hir_id(def_id);
+ let main_id = hir.local_def_id_to_hir_id(def_id);
if main_id == fn_id {
let substs = tcx.mk_substs_trait(declared_ret_ty, &[]);
let trait_ref = ty::TraitRef::new(term_id, substs);
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
/// in "inheriting lifetimes".
fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
- let item = tcx.hir().expect_item(tcx.hir().as_local_hir_id(def_id));
+ let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
debug!(
"check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
def_id, span, item
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let id = tcx.hir().get_parent_item(hir_id);
tcx.hir()
.find(id)
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
err.span_label(span, "cannot resolve opaque type");
// Find the the owner that declared this `impl Trait` type.
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let mut prev_hir_id = hir_id;
let mut hir_id = tcx.hir().get_parent_node(hir_id);
while let Some(node) = tcx.hir().find(hir_id) {
source: hir::LocalSource::Normal,
..
}) => {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let typeck_results =
tcx.typeck(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
if let Some(ty) = typeck_results.node_type_opt(expr.hir_id) {
// Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
let variant_did = def.variants[VariantIdx::new(i)].def_id;
- let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did.expect_local());
+ let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local());
let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
let i_span = match variant_i.disr_expr {
Some(ref expr) => tcx.hir().span(expr.hir_id),
fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> {
let tcx = self.tcx;
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item_id = tcx.hir().ty_param_owner(hir_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
}
}
+ fn suggest_missing_parentheses(&self, err: &mut DiagnosticBuilder<'_>, expr: &hir::Expr<'_>) {
+ let sp = self.tcx.sess.source_map().start_point(expr.span);
+ if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
+ // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
+ self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None);
+ }
+ }
+
fn note_need_for_fn_pointer(
&self,
err: &mut DiagnosticBuilder<'_>,
let param_def_id = generics.type_param(&p, tcx).def_id;
if let Some(generics) = param_def_id
.as_local()
- .map(|id| hir.as_local_hir_id(id))
+ .map(|id| hir.local_def_id_to_hir_id(id))
.and_then(|id| hir.find(hir.get_parent_item(id)))
.as_ref()
.and_then(|node| node.generics())
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
/// the types first.
pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let item = tcx.hir().expect_item(hir_id);
debug!(
}
pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let trait_item = tcx.hir().expect_trait_item(hir_id);
let method_sig = match trait_item.kind {
}
pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let impl_item = tcx.hir().expect_impl_item(hir_id);
let method_sig = match impl_item.kind {
let generics = tcx.generics_of(def_id);
let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
- tcx.hir().as_local_hir_id(local_id)
+ tcx.hir().local_def_id_to_hir_id(local_id)
} else {
// Opaque types from other crates won't have defining uses in this crate.
return ty;
fn visit_opaque_types(&mut self, span: Span) {
for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
- let hir_id = self.tcx().hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local());
let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id);
debug_assert!(!instantiated_ty.has_escaping_bound_vars());
// Note that if we carry through to the `extern_mod_stmt_cnum` query
// below it'll cause a panic because `def_id` is actually bogus at this
// point in time otherwise.
- if tcx.hir().find(tcx.hir().as_local_hir_id(def_id)).is_none() {
+ if tcx.hir().find(tcx.hir().local_def_id_to_hir_id(def_id)).is_none() {
return false;
}
true
for extern_crate in &crates_to_lint {
let def_id = extern_crate.def_id.expect_local();
- let id = tcx.hir().as_local_hir_id(def_id);
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
let item = tcx.hir().expect_item(id);
// If the crate is fully unused, we suggest removing it altogether.
return;
}
- let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
let sp = match tcx.hir().expect_item(impl_hir_id).kind {
ItemKind::Impl { self_ty, .. } => self_ty.span,
_ => bug!("expected Drop impl item"),
fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_copy: impl_did={:?}", impl_did);
- let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
let self_type = tcx.type_of(impl_did);
debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
- let impl_hir_id = tcx.hir().as_local_hir_id(impl_did);
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
let span = tcx.hir().span(impl_hir_id);
let dispatch_from_dyn_trait = tcx.require_lang_item(DispatchFromDynTraitLangItem, Some(span));
debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
// this provider should only get invoked for local def-ids
- let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local());
+ let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did.expect_local());
let span = tcx.hir().span(impl_hir_id);
let coerce_unsized_trait = tcx.require_lang_item(CoerceUnsizedTraitLangItem, Some(span));
item.span,
);
}
+ ty::Array(_, _) => {
+ self.check_primitive_impl(
+ def_id,
+ lang_items.array_impl(),
+ None,
+ "array",
+ "[T; N]",
+ item.span,
+ );
+ }
ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
if matches!(inner.kind, ty::Slice(_)) =>
{
}
pub fn hir_id(&self) -> hir::HirId {
- self.tcx.hir().as_local_hir_id(self.item_def_id.expect_local())
+ self.tcx.hir().local_def_id_to_hir_id(self.item_def_id.expect_local())
}
pub fn node(&self) -> hir::Node<'tcx> {
// written inline like `<T: Foo>` or in a where-clause like
// `where T: Foo`.
- let param_id = tcx.hir().as_local_hir_id(def_id);
+ let param_id = tcx.hir().local_def_id_to_hir_id(def_id);
let param_owner = tcx.hir().ty_param_owner(param_id);
let param_owner_def_id = tcx.hir().local_def_id(param_owner);
let generics = tcx.generics_of(param_owner_def_id);
.unwrap_or_default();
let mut extend = None;
- let item_hir_id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
+ let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
let ast_generics = match tcx.hir().get(item_hir_id) {
Node::TraitItem(item) => &item.generics,
parent_did: LocalDefId,
) -> ty::VariantDef {
let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
- let hir_id = tcx.hir().as_local_hir_id(variant_did.unwrap_or(parent_did));
+ let hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.unwrap_or(parent_did));
let fields = def
.fields()
.iter()
use rustc_hir::*;
let def_id = def_id.expect_local();
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let item = match tcx.hir().get(hir_id) {
Node::Item(item) => item,
_ => bug!(),
/// the transitive super-predicates are converted.
fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
debug!("super_predicates(trait_def_id={:?})", trait_def_id);
- let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id.expect_local());
+ let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
let item = match tcx.hir().get(trait_hir_id) {
Node::Item(item) => item,
}
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let item = tcx.hir().expect_item(hir_id);
let (is_auto, unsafety) = match item.kind {
fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
use rustc_hir::*;
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
let parent_def_id = match node {
use rustc_hir::*;
let def_id = def_id.expect_local();
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let icx = ItemCtxt::new(tcx, def_id.to_def_id());
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id);
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
match tcx.hir().expect_item(hir_id).kind {
hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
}
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
let item = tcx.hir().expect_item(hir_id);
match &item.kind {
}
}
- let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let node = tcx.hir().get(hir_id);
let mut is_trait = None;
if !codegen_fn_attrs.no_sanitize.is_empty() {
if codegen_fn_attrs.inline == InlineAttr::Always {
if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
- let hir_id = tcx.hir().as_local_hir_id(id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(id.expect_local());
tcx.struct_span_lint_hir(
lint::builtin::INLINE_NO_SANITIZE,
hir_id,
/// Checks the function annotated with `#[target_feature]` is not a safe
/// trait method implementation, reporting an error if it is.
fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span: Span) {
- let hir_id = tcx.hir().as_local_hir_id(id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(id);
let node = tcx.hir().get(hir_id);
if let Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) = node {
let parent_id = tcx.hir().get_parent_item(hir_id);
pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
use hir::*;
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
if let Node::AnonConst(_) = tcx.hir().get(hir_id) {
let parent_node_id = tcx.hir().get_parent_node(hir_id);
let def_id = def_id.expect_local();
use rustc_hir::*;
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let icx = ItemCtxt::new(tcx, def_id.to_def_id());
}
}
- let hir_id = tcx.hir().as_local_hir_id(def_id);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let scope = tcx.hir().get_defining_scope(hir_id);
let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
/// by the time we borrow check, and it's not clear how we should handle
/// those.
fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
- let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
+ let scope = tcx.hir().get_defining_scope(tcx.hir().local_def_id_to_hir_id(opaque_ty_id));
let scope_def_id = tcx.hir().local_def_id(scope);
let opaque_ty_def_id = opaque_ty_id.to_def_id();
if concrete_ty.has_erased_regions() {
// FIXME(impl_trait_in_bindings) Handle this case.
tcx.sess.span_fatal(
- tcx.hir().span(tcx.hir().as_local_hir_id(opaque_ty_id)),
+ tcx.hir().span(tcx.hir().local_def_id_to_hir_id(opaque_ty_id)),
"lifetimes in impl Trait types in bindings are not currently supported",
);
}
if let Some(obligations) = wf::obligations(
infcx,
tcx.param_env(impl1_def_id),
- tcx.hir().as_local_hir_id(impl1_def_id),
+ tcx.hir().local_def_id_to_hir_id(impl1_def_id),
arg,
span,
) {
#![recursion_limit = "256"]
#[macro_use]
-extern crate log;
+extern crate tracing;
#[macro_use]
extern crate rustc_middle;
}
fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: LocalDefId) {
- let main_id = tcx.hir().as_local_hir_id(main_def_id);
+ let main_id = tcx.hir().local_def_id_to_hir_id(main_def_id);
let main_span = tcx.def_span(main_def_id);
let main_t = tcx.type_of(main_def_id);
match main_t.kind {
}
fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: LocalDefId) {
- let start_id = tcx.hir().as_local_hir_id(start_def_id);
+ let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id);
let start_span = tcx.def_span(start_def_id);
let start_t = tcx.type_of(start_def_id);
match start_t.kind {
debug!("InferVisitor::visit_item(item={:?})", item_did);
- let hir_id = self.tcx.hir().as_local_hir_id(item_did);
+ let hir_id = self.tcx.hir().local_def_id_to_hir_id(item_did);
let item = match self.tcx.hir().get(hir_id) {
Node::Item(item) => item,
_ => bug!(),
}
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[(ty::Predicate<'_>, Span)] {
- let id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
+ let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
match tcx.hir().get(id) {
Node::Item(item) => match item.kind {
return;
}
- let id = tcx.hir().as_local_hir_id(def_id);
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
let inferred_start = self.terms_cx.inferred_starts[&id];
let current_item = &CurrentItem { inferred_start };
match tcx.type_of(def_id).kind {
}
let (local, remote) = if let Some(def_id) = def_id.as_local() {
- let id = self.tcx().hir().as_local_hir_id(def_id);
+ let id = self.tcx().hir().local_def_id_to_hir_id(def_id);
(Some(self.terms_cx.inferred_starts[&id]), None)
} else {
(None, Some(self.tcx().variances_of(def_id)))
}
fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
- let id = tcx.hir().as_local_hir_id(item_def_id.expect_local());
+ let id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
let unsupported = || {
// Variance not relevant.
span_bug!(tcx.hir().span(id), "asked to compute variance for wrong kind of item")
all.into_iter() // iterating over (Option<DefId>, Variance)
.filter(|&(ref d, _)| d.is_some())
.map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
- .filter_map(|(d, v)| d.as_local().map(|d| tcx.hir().as_local_hir_id(d)).map(|n| (n, v))) // (HirId, Variance)
+ .filter_map(|(d, v)| {
+ d.as_local().map(|d| tcx.hir().local_def_id_to_hir_id(d)).map(|n| (n, v))
+ }) // (HirId, Variance)
.collect()
}
}
let for_ = if let Some(did) = did.as_local() {
- let hir_id = tcx.hir().as_local_hir_id(did);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(did);
match tcx.hir().expect_item(hir_id).kind {
hir::ItemKind::Impl { self_ty, .. } => self_ty.clean(cx),
_ => panic!("did given to build_impl was not an impl"),
let predicates = tcx.explicit_predicates_of(did);
let (trait_items, generics) = if let Some(did) = did.as_local() {
- let hir_id = tcx.hir().as_local_hir_id(did);
+ let hir_id = tcx.hir().local_def_id_to_hir_id(did);
match tcx.hir().expect_item(hir_id).kind {
hir::ItemKind::Impl { ref generics, ref items, .. } => (
items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
pub fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
if let Some(did) = did.as_local() {
- let hir_id = cx.tcx.hir().as_local_hir_id(did);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(did);
rustc_hir_pretty::id_to_string(&cx.tcx.hir(), hir_id)
} else {
cx.tcx.rendered_const(did)
expr: print_inlined_const(cx, did),
value: clean::utils::print_evaluated_const(cx, did),
is_literal: did.as_local().map_or(false, |did| {
- clean::utils::is_literal_expr(cx, cx.tcx.hir().as_local_hir_id(did))
+ clean::utils::is_literal_expr(cx, cx.tcx.hir().local_def_id_to_hir_id(did))
}),
}
}
if let Res::Def(DefKind::TyAlias, def_id) = path.res {
// Substitute private type aliases
if let Some(def_id) = def_id.as_local() {
- let hir_id = cx.tcx.hir().as_local_hir_id(def_id);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if !cx.renderinfo.borrow().access_levels.is_exported(def_id.to_def_id()) {
alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
}
Bool => tcx.lang_items().bool_impl(),
Str => tcx.lang_items().str_impl(),
Slice => tcx.lang_items().slice_impl(),
- Array => tcx.lang_items().slice_impl(),
+ Array => tcx.lang_items().array_impl(),
Tuple => None,
Unit => None,
RawPointer => tcx.lang_items().const_ptr_impl(),
match n.val {
ty::ConstKind::Unevaluated(def, _, promoted) => {
let mut s = if let Some(def) = def.as_local() {
- let hir_id = cx.tcx.hir().as_local_hir_id(def.did);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
} else {
inline::print_inlined_const(cx, def.did)
def_id
}
- /// Like the function of the same name on the HIR map, but skips calling it on fake DefIds.
+ /// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
/// (This avoids a slice-index-out-of-bounds panic.)
pub fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
if self.all_fake_def_ids.borrow().contains(&def_id) {
None
} else {
- def_id.as_local().map(|def_id| self.tcx.hir().as_local_hir_id(def_id))
+ def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
}
}
}
let hir = tcx.hir();
- let body = hir.body(hir.body_owned_by(hir.as_local_hir_id(def_id)));
+ let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(def_id)));
debug!("visiting body for {:?}", def_id);
EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
(rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
(Some(h), _) => h,
(None, Some(item_did)) => {
match item_did.as_local() {
- Some(item_did) => self.tcx.hir().as_local_hir_id(item_did),
+ Some(item_did) => self.tcx.hir().local_def_id_to_hir_id(item_did),
None => {
// If non-local, no need to check anything.
return;
{
use rustc_hir::def_id::LOCAL_CRATE;
- let hir_src = self.cx.tcx.hir().as_local_hir_id(src_id);
- let hir_dst = self.cx.tcx.hir().as_local_hir_id(dst_id);
+ let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
+ let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id);
if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src)
&& !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst)
lang_items.bool_impl(),
lang_items.char_impl(),
lang_items.str_impl(),
+ lang_items.array_impl(),
lang_items.slice_impl(),
lang_items.slice_u8_impl(),
lang_items.str_alloc_impl(),
}
let res_hir_id = match res_did.as_local() {
- Some(n) => tcx.hir().as_local_hir_id(n),
+ Some(n) => tcx.hir().local_def_id_to_hir_id(n),
None => return false,
};
CoverageMappingWriter.write(OS);
}
+extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
+ StringRef FuncNameRef(FuncName);
+ return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
+}
+
extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
StringRef NameRef(Name);
return IndexedInstrProf::ComputeHash(NameRef);
// CHECK-NEXT: define void @naked_with_args(i{{[0-9]+( %0)?}})
pub fn naked_with_args(a: isize) {
// CHECK-NEXT: {{.+}}:
- // CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
+ // CHECK-NEXT: %a = alloca i{{[0-9]+}}
&a; // keep variable in an alloca
// CHECK: ret void
}
#[naked]
pub fn naked_with_args_and_return(a: isize) -> isize {
// CHECK-NEXT: {{.+}}:
- // CHECK-NEXT: %_1 = alloca i{{[0-9]+}}
+ // CHECK-NEXT: %a = alloca i{{[0-9]+}}
&a; // keep variable in an alloca
// CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
a
+++ /dev/null
-// min-lldb-version: 310
-
-// We have to ignore android because of this issue:
-// https://github.com/rust-lang/rust/issues/74847
-// ignore-android
-//
-// We need to use inline assembly, so just use one platform
-// only-x86_64
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:run
-
-// gdb-command:info args
-// gdb-check:No arguments.
-// gdb-command:continue
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:run
-
-// lldb-command:frame variable
-// lldbg-check:(unsigned long) = 111 (unsigned long) = 222
-// lldbr-check:(unsigned long) = 111 (unsigned long) = 222
-// lldb-command:continue
-
-
-#![feature(asm)]
-#![feature(naked_functions)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-fn main() {
- naked(111, 222);
-}
-
-#[naked]
-extern "C" fn naked(x: usize, y: usize) {
- unsafe { asm!("ret"); } // #break
-}
--- /dev/null
+- // MIR for `bar` before MatchBranchSimplification
++ // MIR for `bar` after MatchBranchSimplification
+
+ fn bar(_1: i32) -> (bool, bool, bool, bool) {
+ debug i => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:11:8: 11:9
+ let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:11:19: 11:43
+ let _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+ let _6: (); // in scope 0 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+ scope 1 {
+ debug a => _2; // in scope 1 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+ let _3: bool; // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+ scope 2 {
+ debug b => _3; // in scope 2 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+ let _4: bool; // in scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+ scope 3 {
+ debug c => _4; // in scope 3 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+ let _5: bool; // in scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+ scope 4 {
+ debug d => _5; // in scope 4 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+ }
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+ StorageLive(_3); // scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+ StorageLive(_4); // scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+ StorageLive(_5); // scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+ StorageLive(_6); // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+- switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
++ _2 = Ne(_1, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
++ // ty::Const
++ // + ty: i32
++ // + val: Value(Scalar(0x00000007))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++ _3 = Eq(_1, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
++ // ty::Const
++ // + ty: i32
++ // + val: Value(Scalar(0x00000007))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++ _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
++ // ty::Const
++ // + ty: bool
++ // + val: Value(Scalar(0x00))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
++ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
++ _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
++ // ty::Const
++ // + ty: bool
++ // + val: Value(Scalar(0x01))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
++ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++ goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
+ }
+
+ bb1: {
+ _2 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:26:13: 26:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:26:17: 26:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:27:13: 27:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:27:17: 27:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:28:13: 28:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:28:17: 28:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:29:17: 29:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+ }
+
+ bb2: {
+ _2 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:19:17: 19:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _3 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:20:17: 20:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+ }
+
+ bb3: {
+ StorageDead(_6); // scope 4 at $DIR/matches_reduce_branches.rs:32:6: 32:7
+ StorageLive(_7); // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+ _7 = _2; // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+ StorageLive(_8); // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+ _8 = _3; // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+ StorageLive(_9); // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+ _9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+ StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+ _10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+ (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_7); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_5); // scope 3 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ StorageDead(_4); // scope 2 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ StorageDead(_3); // scope 1 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ return; // scope 0 at $DIR/matches_reduce_branches.rs:35:2: 35:2
+ }
+ }
+
--- /dev/null
+- // MIR for `bar` before MatchBranchSimplification
++ // MIR for `bar` after MatchBranchSimplification
+
+ fn bar(_1: i32) -> (bool, bool, bool, bool) {
+ debug i => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:11:8: 11:9
+ let mut _0: (bool, bool, bool, bool); // return place in scope 0 at $DIR/matches_reduce_branches.rs:11:19: 11:43
+ let _2: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+ let _6: (); // in scope 0 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+ let mut _7: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+ let mut _8: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+ let mut _9: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+ let mut _10: bool; // in scope 0 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+ scope 1 {
+ debug a => _2; // in scope 1 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+ let _3: bool; // in scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+ scope 2 {
+ debug b => _3; // in scope 2 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+ let _4: bool; // in scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+ scope 3 {
+ debug c => _4; // in scope 3 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+ let _5: bool; // in scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+ scope 4 {
+ debug d => _5; // in scope 4 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+ }
+ }
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:12:9: 12:10
+ StorageLive(_3); // scope 1 at $DIR/matches_reduce_branches.rs:13:9: 13:10
+ StorageLive(_4); // scope 2 at $DIR/matches_reduce_branches.rs:14:9: 14:10
+ StorageLive(_5); // scope 3 at $DIR/matches_reduce_branches.rs:15:9: 15:10
+ StorageLive(_6); // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+- switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
++ _2 = Ne(_1, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
++ // ty::Const
++ // + ty: i32
++ // + val: Value(Scalar(0x00000007))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++ _3 = Eq(_1, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
++ // ty::Const
++ // + ty: i32
++ // + val: Value(Scalar(0x00000007))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000007)) }
++ _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
++ // ty::Const
++ // + ty: bool
++ // + val: Value(Scalar(0x00))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
++ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
++ _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
++ // ty::Const
++ // + ty: bool
++ // + val: Value(Scalar(0x01))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
++ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
++ goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:18:9: 18:10
+ }
+
+ bb1: {
+ _2 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:26:13: 26:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:26:17: 26:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:27:13: 27:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:27:17: 27:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:28:13: 28:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:28:17: 28:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:29:13: 29:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:29:17: 29:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+ }
+
+ bb2: {
+ _2 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:19:13: 19:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:19:17: 19:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _3 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:20:13: 20:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:20:17: 20:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:21:13: 21:22
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:21:17: 21:22
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:22:13: 22:21
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:22:17: 22:21
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:17:5: 32:6
+ }
+
+ bb3: {
+ StorageDead(_6); // scope 4 at $DIR/matches_reduce_branches.rs:32:6: 32:7
+ StorageLive(_7); // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+ _7 = _2; // scope 4 at $DIR/matches_reduce_branches.rs:34:6: 34:7
+ StorageLive(_8); // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+ _8 = _3; // scope 4 at $DIR/matches_reduce_branches.rs:34:9: 34:10
+ StorageLive(_9); // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+ _9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:34:12: 34:13
+ StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+ _10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:34:15: 34:16
+ (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:34:5: 34:17
+ StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_7); // scope 4 at $DIR/matches_reduce_branches.rs:34:16: 34:17
+ StorageDead(_5); // scope 3 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ StorageDead(_4); // scope 2 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ StorageDead(_3); // scope 1 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:35:1: 35:2
+ return; // scope 0 at $DIR/matches_reduce_branches.rs:35:2: 35:2
+ }
+ }
+
--- /dev/null
+- // MIR for `foo` before MatchBranchSimplification
++ // MIR for `foo` after MatchBranchSimplification
+
+ fn foo(_1: std::option::Option<()>) -> () {
+ debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:5:8: 5:11
+ let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:5:25: 5:25
+ let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
++ _2 = Eq(_3, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ // ty::Const
++ // + ty: isize
++ // + val: Value(Scalar(0x00000000))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++ // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) }
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+ }
+
+ bb1: {
+ _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ }
+
+ bb2: {
+ _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ }
+
+ bb3: {
+ switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+ }
+
+ bb4: {
+ _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+ // ty::Const
+ // + ty: ()
+ // + val: Value(Scalar(<ZST>))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
+ // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+ goto -> bb5; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+ }
+
+ bb5: {
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+ return; // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
+ }
+ }
+
--- /dev/null
+- // MIR for `foo` before MatchBranchSimplification
++ // MIR for `foo` after MatchBranchSimplification
+
+ fn foo(_1: std::option::Option<()>) -> () {
+ debug bar => _1; // in scope 0 at $DIR/matches_reduce_branches.rs:5:8: 5:11
+ let mut _0: (); // return place in scope 0 at $DIR/matches_reduce_branches.rs:5:25: 5:25
+ let mut _2: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _3: isize; // in scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _3 = discriminant(_1); // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+- switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
++ _2 = Eq(_3, const 0_isize); // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++ // ty::Const
++ // + ty: isize
++ // + val: Value(Scalar(0x0000000000000000))
++ // mir::Constant
++ // + span: $DIR/matches_reduce_branches.rs:1:1: 1:1
++ // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) }
++ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:6:22: 6:26
+ }
+
+ bb1: {
+ _2 = const false; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
+ goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ }
+
+ bb2: {
+ _2 = const true; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // ty::Const
+ // + ty: bool
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ }
+
+ bb3: {
+ switchInt(_2) -> [false: bb4, otherwise: bb5]; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+ }
+
+ bb4: {
+ _0 = const (); // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+ // ty::Const
+ // + ty: ()
+ // + val: Value(Scalar(<ZST>))
+ // mir::Constant
+ // + span: $DIR/matches_reduce_branches.rs:6:5: 8:6
+ // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+ goto -> bb5; // scope 0 at $DIR/matches_reduce_branches.rs:6:5: 8:6
+ }
+
+ bb5: {
+ StorageDead(_2); // scope 0 at $DIR/matches_reduce_branches.rs:9:1: 9:2
+ return; // scope 0 at $DIR/matches_reduce_branches.rs:9:2: 9:2
+ }
+ }
+
--- /dev/null
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR matches_reduce_branches.foo.MatchBranchSimplification.diff
+// EMIT_MIR matches_reduce_branches.bar.MatchBranchSimplification.diff
+
+fn foo(bar: Option<()>) {
+ if matches!(bar, None) {
+ ()
+ }
+}
+
+fn bar(i: i32) -> (bool, bool, bool, bool) {
+ let a;
+ let b;
+ let c;
+ let d;
+
+ match i {
+ 7 => {
+ a = false;
+ b = true;
+ c = false;
+ d = true;
+ ()
+ }
+ _ => {
+ a = true;
+ b = false;
+ c = false;
+ d = true;
+ ()
+ }
+ };
+
+ (a, b, c, d)
+}
+
+
+fn main() {
+ let _ = foo(None);
+ let _ = foo(Some(()));
+ let _ = bar(0);
+}
--- /dev/null
+- // MIR for `exhaustive_match` before MatchBranchSimplification
++ // MIR for `exhaustive_match` after MatchBranchSimplification
+
+ fn exhaustive_match(_1: E) -> u8 {
+ debug e => _1; // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
+ let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
+ let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+
+ bb0: {
+ _2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+ switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+ }
+
+ bb1: {
+ _0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
+ // ty::Const
+ // + ty: u8
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:14:17: 14:18
+ // + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+ }
+
+ bb2: {
+ _0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
+ // ty::Const
+ // + ty: u8
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:13:17: 13:18
+ // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+ }
+
+ bb3: {
+ return; // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
+ }
+ }
+
--- /dev/null
+- // MIR for `exhaustive_match` before MatchBranchSimplification
++ // MIR for `exhaustive_match` after MatchBranchSimplification
+
+ fn exhaustive_match(_1: E) -> u8 {
+ debug e => _1; // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
+ let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
+ let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+
+ bb0: {
+ _2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+ switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
+ }
+
+ bb1: {
+ _0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
+ // ty::Const
+ // + ty: u8
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:14:17: 14:18
+ // + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+ }
+
+ bb2: {
+ _0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
+ // ty::Const
+ // + ty: u8
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:13:17: 13:18
+ // + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
+ }
+
+ bb3: {
+ return; // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
+ }
+ }
+
--- /dev/null
+- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
++ // MIR for `exhaustive_match_i8` after MatchBranchSimplification
+
+ fn exhaustive_match_i8(_1: E) -> i8 {
+ debug e => _1; // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
+ let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
+ let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+
+ bb0: {
+ _2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+ switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+ }
+
+ bb1: {
+ _0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
+ // ty::Const
+ // + ty: i8
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:22:17: 22:18
+ // + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+ }
+
+ bb2: {
+ _0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
+ // ty::Const
+ // + ty: i8
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:21:17: 21:18
+ // + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+ }
+
+ bb3: {
+ return; // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
+ }
+ }
+
--- /dev/null
+- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
++ // MIR for `exhaustive_match_i8` after MatchBranchSimplification
+
+ fn exhaustive_match_i8(_1: E) -> i8 {
+ debug e => _1; // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
+ let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
+ let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+
+ bb0: {
+ _2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+ switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
+ }
+
+ bb1: {
+ _0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
+ // ty::Const
+ // + ty: i8
+ // + val: Value(Scalar(0x01))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:22:17: 22:18
+ // + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+ }
+
+ bb2: {
+ _0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
+ // ty::Const
+ // + ty: i8
+ // + val: Value(Scalar(0x00))
+ // mir::Constant
+ // + span: $DIR/matches_u8.rs:21:17: 21:18
+ // + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
+ goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
+ }
+
+ bb3: {
+ return; // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
+ }
+ }
+
--- /dev/null
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
+// EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
+
+pub enum E {
+ A,
+ B,
+}
+
+#[no_mangle]
+pub fn exhaustive_match(e: E) -> u8 {
+ match e {
+ E::A => 0,
+ E::B => 1,
+ }
+}
+
+#[no_mangle]
+pub fn exhaustive_match_i8(e: E) -> i8 {
+ match e {
+ E::A => 0,
+ E::B => 1,
+ }
+}
+
+fn main() {
+ assert_eq!(exhaustive_match(E::A), 0);
+ assert_eq!(exhaustive_match(E::B), 1);
+
+ assert_eq!(exhaustive_match_i8(E::A), 0);
+ assert_eq!(exhaustive_match_i8(E::B), 1);
+}
# FIXME(richkadel): Debug the following problem, and reenable on Windows (by
# removing the `# ignore-msvc` directive above). The current implementation
-# generates a segfault when running the instrumented `main` executable,
-# after the `main` program code executes, but before the process terminates.
-# This most likely points to a problem generating the LLVM "main.profraw"
+# generates a segfault when running the instrumented `testprog` executable,
+# after the `main()` function completes, but before the process terminates.
+# This most likely points to a problem generating the LLVM "testprog.profraw"
# file.
-include ../tools.mk
+UNAME = $(shell uname)
+
+ifeq ($(UNAME),Darwin)
+ INSTR_PROF_DATA_SUFFIX=,regular,live_support
+ DATA_SECTION_PREFIX=__DATA,
+ LLVM_COV_SECTION_PREFIX=__LLVM_COV,
+else
+ INSTR_PROF_DATA_SUFFIX=
+ DATA_SECTION_PREFIX=
+ LLVM_COV_SECTION_PREFIX=
+endif
+
# This test makes sure that LLVM coverage maps are genereated in LLVM IR.
COMMON_FLAGS=-Zinstrument-coverage
all:
# Compile the test program with instrumentation, and also generate LLVM IR
- $(RUSTC) $(COMMON_FLAGS) main.rs
+ $(RUSTC) $(COMMON_FLAGS) testprog.rs \
+ --emit=link,llvm-ir
+
+ # check the LLVM IR
+ifdef IS_WIN32
+ cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt \
+ -check-prefixes=CHECK,WIN32 \
+ -DPRIVATE_GLOBAL="internal global" \
+ -DINSTR_PROF_DATA=".lprfd$$M" \
+ -DINSTR_PROF_NAME=".lprfn$$M" \
+ -DINSTR_PROF_CNTS=".lprfc$$M" \
+ -DINSTR_PROF_VALS=".lprfv$$M" \
+ -DINSTR_PROF_VNODES=".lprfnd$$M" \
+ -DINSTR_PROF_COVMAP=".lcovmap$$M" \
+ -DINSTR_PROF_ORDERFILE=".lorderfile$$M"
+else
+ cat "$(TMPDIR)"/testprog.ll | "$(LLVM_FILECHECK)" filecheck-patterns.txt \
+ -check-prefixes=CHECK \
+ -DPRIVATE_GLOBAL="private global" \
+ -DINSTR_PROF_DATA="$(DATA_SECTION_PREFIX)__llvm_prf_data$(INSTR_PROF_DATA_SUFFIX)" \
+ -DINSTR_PROF_NAME="$(DATA_SECTION_PREFIX)__llvm_prf_names" \
+ -DINSTR_PROF_CNTS="$(DATA_SECTION_PREFIX)__llvm_prf_cnts" \
+ -DINSTR_PROF_VALS="$(DATA_SECTION_PREFIX)__llvm_prf_vals" \
+ -DINSTR_PROF_VNODES="$(DATA_SECTION_PREFIX)__llvm_prf_vnds" \
+ -DINSTR_PROF_COVMAP="$(LLVM_COV_SECTION_PREFIX)__llvm_covmap" \
+ -DINSTR_PROF_ORDERFILE="$(DATA_SECTION_PREFIX)__llvm_orderfile"
+endif
# Run it in order to generate some profiling data,
# with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
# output the coverage stats for this run.
- LLVM_PROFILE_FILE="$(TMPDIR)"/main.profraw \
- $(call RUN,main)
+ LLVM_PROFILE_FILE="$(TMPDIR)"/testprog.profraw \
+ $(call RUN,testprog)
# Postprocess the profiling data so it can be used by the llvm-cov tool
"$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \
- "$(TMPDIR)"/main.profraw \
- -o "$(TMPDIR)"/main.profdata
+ "$(TMPDIR)"/testprog.profraw \
+ -o "$(TMPDIR)"/testprog.profdata
# Generate a coverage report using `llvm-cov show`. The output ordering
# can be non-deterministic, so ignore the return status. If the test fails
# when comparing the JSON `export`, the `show` output may be useful when
# debugging.
"$(LLVM_BIN_DIR)"/llvm-cov show \
- --Xdemangler="$(RUST_DEMANGLER)" \
- --show-line-counts-or-regions \
- --instr-profile="$(TMPDIR)"/main.profdata \
- $(call BIN,"$(TMPDIR)"/main) \
+ --Xdemangler="$(RUST_DEMANGLER)" \
+ --show-line-counts-or-regions \
+ --instr-profile="$(TMPDIR)"/testprog.profdata \
+ $(call BIN,"$(TMPDIR)"/testprog) \
> "$(TMPDIR)"/actual_show_coverage.txt
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/actual_show_coverage.txt typical_show_coverage.txt
+else
# Compare the show coverage output
$(DIFF) typical_show_coverage.txt "$(TMPDIR)"/actual_show_coverage.txt || \
- >&2 echo 'diff failed for `llvm-cov show` (might not be an error)'
+ >&2 echo 'diff failed for `llvm-cov show` (might not be an error)'
+endif
# Generate a coverage report in JSON, using `llvm-cov export`, and fail if
# there are differences from the expected output.
"$(LLVM_BIN_DIR)"/llvm-cov export \
- --summary-only \
- --instr-profile="$(TMPDIR)"/main.profdata \
- $(call BIN,"$(TMPDIR)"/main) \
+ --summary-only \
+ --instr-profile="$(TMPDIR)"/testprog.profdata \
+ $(call BIN,"$(TMPDIR)"/testprog) \
| "$(PYTHON)" prettify_json.py \
> "$(TMPDIR)"/actual_export_coverage.json
+ifdef RUSTC_BLESS_TEST
+ cp "$(TMPDIR)"/actual_export_coverage.json expected_export_coverage.json
+else
# Check that the exported JSON coverage data matches what we expect
$(DIFF) expected_export_coverage.json "$(TMPDIR)"/actual_export_coverage.json
+endif
{
"files": [
{
- "filename": "main.rs",
+ "filename": "testprog.rs",
"summary": {
"functions": {
"count": 7,
--- /dev/null
+# Check for metadata, variables, declarations, and function definitions injected
+# into LLVM IR when compiling with -Zinstrument-coverage.
+
+WIN32: $__llvm_profile_runtime_user = comdat any
+
+CHECK: @__llvm_coverage_mapping = internal constant
+CHECK-SAME: section "[[INSTR_PROF_COVMAP]]", align 8
+
+WIN32: @__llvm_profile_runtime = external global i32
+
+CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]]
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8
+
+CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog14will_be_called = [[PRIVATE_GLOBAL]]
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+CHECK-SAME: ()* @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called to i8*),
+CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8
+
+CHECK: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]]
+CHECK-SAME: section "[[INSTR_PROF_CNTS]]", align 8
+
+CHECK: @__profd__R{{[a-zA-Z0-9_]+}}testprog4main = [[PRIVATE_GLOBAL]]
+CHECK-SAME: @__profc__R{{[a-zA-Z0-9_]+}}testprog4main,
+CHECK-SAME: ()* @_R{{[a-zA-Z0-9_]+}}testprog4main to i8*),
+CHECK-SAME: section "[[INSTR_PROF_DATA]]", align 8
+
+CHECK: @__llvm_prf_nm = private constant
+CHECK-SAME: section "[[INSTR_PROF_NAME]]", align 1
+
+CHECK: @llvm.used = appending global
+CHECK-SAME: i8* bitcast ({ {{.*}} }* @__llvm_coverage_mapping to i8*)
+WIN32-SAME: i8* bitcast (i32 ()* @__llvm_profile_runtime_user to i8*)
+CHECK-SAME: i8* bitcast ({ {{.*}} }* @__profd__R{{[a-zA-Z0-9_]*}}testprog4main to i8*)
+CHECK-SAME: i8* getelementptr inbounds ({{.*}}* @__llvm_prf_nm, i32 0, i32 0)
+CHECK-SAME: section "llvm.metadata"
+
+CHECK: define hidden { {{.*}} } @_R{{[a-zA-Z0-9_]+}}testprog14will_be_called() unnamed_addr #{{[0-9]+}} {
+CHECK-NEXT: start:
+CHECK-NOT: bb{{[0-9]+}}:
+CHECK: %pgocount = load i64, i64* getelementptr inbounds
+CHECK-SAME: * @__profc__R{{[a-zA-Z0-9_]+}}testprog14will_be_called,
+
+CHECK: declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #[[LLVM_INSTRPROF_INCREMENT_ATTR:[0-9]+]]
+
+WIN32: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() #[[LLVM_PROFILE_RUNTIME_USER_ATTR:[0-9]+]] comdat {
+WIN32-NEXT: %1 = load i32, i32* @__llvm_profile_runtime
+WIN32-NEXT: ret i32 %1
+WIN32-NEXT: }
+
+CHECK: attributes #[[LLVM_INSTRPROF_INCREMENT_ATTR]] = { nounwind }
+WIN32: attributes #[[LLVM_PROFILE_RUNTIME_USER_ATTR]] = { noinline }
\ No newline at end of file
+++ /dev/null
-pub fn will_be_called() -> &'static str {
- let val = "called";
- println!("{}", val);
- val
-}
-
-pub fn will_not_be_called() -> bool {
- println!("should not have been called");
- false
-}
-
-pub fn print<T>(left: &str, value: T, right: &str)
-where
- T: std::fmt::Display,
-{
- println!("{}{}{}", left, value, right);
-}
-
-pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
-where
- F: FnOnce(&T)
-{
- if should_wrap {
- wrapper(&inner)
- }
-}
-
-fn main() {
- let less = 1;
- let more = 100;
-
- if less < more {
- wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
- wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
- } else {
- wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
- }
-}
--- /dev/null
+pub fn will_be_called() -> &'static str {
+ let val = "called";
+ println!("{}", val);
+ val
+}
+
+pub fn will_not_be_called() -> bool {
+ println!("should not have been called");
+ false
+}
+
+pub fn print<T>(left: &str, value: T, right: &str)
+where
+ T: std::fmt::Display,
+{
+ println!("{}{}{}", left, value, right);
+}
+
+pub fn wrap_with<F, T>(inner: T, should_wrap: bool, wrapper: F)
+where
+ F: FnOnce(&T)
+{
+ if should_wrap {
+ wrapper(&inner)
+ }
+}
+
+fn main() {
+ let less = 1;
+ let more = 100;
+
+ if less < more {
+ wrap_with(will_be_called(), less < more, |inner| print(" ***", inner, "*** "));
+ wrap_with(will_be_called(), more < less, |inner| print(" ***", inner, "*** "));
+ } else {
+ wrap_with(will_not_be_called(), true, |inner| print("wrapped result is: ", inner, ""));
+ }
+}
25| 2| }
26| 2|}
------------------
- | main[317d481089b8c8fe]::wrap_with::<main[317d481089b8c8fe]::main::{closure#0}, &str>:
+ | testprog[317d481089b8c8fe]::wrap_with::<testprog[317d481089b8c8fe]::main::{closure#0}, &str>:
| 22| 1|{
| 23| 1| if should_wrap {
| 24| 1| wrapper(&inner)
| 25| 1| }
| 26| 1|}
------------------
- | main[317d481089b8c8fe]::wrap_with::<main[317d481089b8c8fe]::main::{closure#1}, &str>:
+ | testprog[317d481089b8c8fe]::wrap_with::<testprog[317d481089b8c8fe]::main::{closure#1}, &str>:
| 22| 1|{
| 23| 1| if should_wrap {
| 24| 1| wrapper(&inner)
# needs-sanitizer-support
# needs-sanitizer-address
-# only-linux
-include ../tools.mk
# needs-sanitizer-support
# needs-sanitizer-address
-# only-linux
-include ../tools.mk
# needs-sanitizer-support
# needs-sanitizer-address
-# only-linux
-include ../tools.mk
-#![ crate_name = "test" ]
+#![crate_name = "test"]
#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(associated_type_defaults)]
extern crate krate2 as krate3;
use rustc_graphviz::RenderOption;
-use std::collections::{HashMap,HashSet};
use std::cell::RefCell;
+use std::collections::{HashMap, HashSet};
use std::io::Write;
-
use sub::sub2 as msalias;
use sub::sub2;
use sub::sub2::nested_struct as sub_struct;
// buglink test - see issue #1337.
fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
- let s = sub_struct{ field2: 45u32, };
+ let s = sub_struct { field2: 45u32 };
// import tests
fn foo(x: &Write) {}
pub enum nested_enum {
Nest2 = 2,
- Nest3 = 3
+ Nest3 = 3,
}
}
}
type SF = some_fields;
trait SuperTrait {
- fn qux(&self) { panic!(); }
+ fn qux(&self) {
+ panic!();
+ }
}
trait SomeTrait: SuperTrait {
}
}
-impl SuperTrait for some_fields {
-}
+impl SuperTrait for some_fields {}
impl SubTrait for some_fields {}
42
}
- fn align_to<T>(&mut self) {
-
- }
+ fn align_to<T>(&mut self) {}
fn test(&mut self) {
self.align_to::<bool>();
}
}
-impl SuperTrait for nofields {
-}
+impl SuperTrait for nofields {}
impl SomeTrait for nofields {
fn Method(&self, x: u32) -> u32 {
self.Method(x);
Ints(isize, isize),
Floats(f64, f64),
Strings(&'a str, &'a str, &'a str),
- MyTypes(MyType, MyType)
+ MyTypes(MyType, MyType),
}
#[derive(Copy, Clone)]
enum SomeOtherEnum {
SomeConst1,
SomeConst2,
- SomeConst3
+ SomeConst3,
}
enum SomeStructEnum {
- EnumStruct{a:isize, b:isize},
- EnumStruct2{f1:MyType, f2:MyType},
- EnumStruct3{f1:MyType, f2:MyType, f3:SomeEnum<'static>}
+ EnumStruct { a: isize, b: isize },
+ EnumStruct2 { f1: MyType, f2: MyType },
+ EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
}
fn matchSomeEnum(val: SomeEnum) {
match val {
- SomeEnum::Ints(int1, int2) => { println(&(int1+int2).to_string()); }
- SomeEnum::Floats(float1, float2) => { println(&(float2*float1).to_string()); }
- SomeEnum::Strings(.., s3) => { println(s3); }
- SomeEnum::MyTypes(mt1, mt2) => { println(&(mt1.field1 - mt2.field1).to_string()); }
+ SomeEnum::Ints(int1, int2) => {
+ println(&(int1 + int2).to_string());
+ }
+ SomeEnum::Floats(float1, float2) => {
+ println(&(float2 * float1).to_string());
+ }
+ SomeEnum::Strings(.., s3) => {
+ println(s3);
+ }
+ SomeEnum::MyTypes(mt1, mt2) => {
+ println(&(mt1.field1 - mt2.field1).to_string());
+ }
}
}
fn matchSomeStructEnum(se: SomeStructEnum) {
match se {
- SomeStructEnum::EnumStruct{a:a, ..} => println(&a.to_string()),
- SomeStructEnum::EnumStruct2{f1:f1, f2:f_2} => println(&f_2.field1.to_string()),
- SomeStructEnum::EnumStruct3{f1, ..} => println(&f1.field1.to_string()),
+ SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
+ SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
+ SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
}
}
-
fn matchSomeStructEnum2(se: SomeStructEnum) {
use SomeStructEnum::*;
match se {
- EnumStruct{a: ref aaa, ..} => println(&aaa.to_string()),
- EnumStruct2{f1, f2: f2} => println(&f1.field1.to_string()),
- EnumStruct3{f1, f3: SomeEnum::Ints(..), f2} => println(&f1.field1.to_string()),
- _ => {},
+ EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
+ EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
+ EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
+ _ => {}
}
}
fn matchSomeOtherEnum(val: SomeOtherEnum) {
use SomeOtherEnum::{SomeConst2, SomeConst3};
match val {
- SomeOtherEnum::SomeConst1 => { println("I'm const1."); }
- SomeConst2 | SomeConst3 => { println("I'm const2 or const3."); }
+ SomeOtherEnum::SomeConst1 => {
+ println("I'm const1.");
+ }
+ SomeConst2 | SomeConst3 => {
+ println("I'm const2 or const3.");
+ }
}
}
-fn hello<X: SomeTrait>((z, a) : (u32, String), ex: X) {
+fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
SameDir2::hello(43);
println(&yy.to_string());
let x = 32.0f32;
let _ = (x + ((x * x) + 1.0).sqrt()).ln();
- let s: Box<SomeTrait> = box some_fields {field1: 43};
- let s2: Box<some_fields> = box some_fields {field1: 43};
+ let s: Box<SomeTrait> = box some_fields { field1: 43 };
+ let s2: Box<some_fields> = box some_fields { field1: 43 };
let s3 = box nofields;
s.Method(43);
}
}
-fn main() { // foo
- let s = box some_fields {field1: 43};
+fn main() {
+ // foo
+ let s = box some_fields { field1: 43 };
hello((43, "a".to_string()), *s);
sub::sub2::hello();
sub2::sub3::hello();
let vs = variable_str!(32);
let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
- let _ = blah {
- used_link_args: RefCell::new([]),
- };
+ let _ = blah { used_link_args: RefCell::new([]) };
let s1 = nofields;
- let s2 = SF { field1: 55};
- let s3: some_fields = some_fields{ field1: 55};
- let s4: msalias::nested_struct = sub::sub2::nested_struct{ field2: 55};
- let s4: msalias::nested_struct = sub2::nested_struct{ field2: 55};
+ let s2 = SF { field1: 55 };
+ let s3: some_fields = some_fields { field1: 55 };
+ let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
+ let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
println(&s2.field1.to_string());
- let s5: MyType = box some_fields{ field1: 55};
- let s = SameDir::SameStruct{name: "Bob".to_string()};
- let s = SubDir::SubStruct{name:"Bob".to_string()};
+ let s5: MyType = box some_fields { field1: 55 };
+ let s = SameDir::SameStruct { name: "Bob".to_string() };
+ let s = SubDir::SubStruct { name: "Bob".to_string() };
let s6: SomeEnum = SomeEnum::MyTypes(box s2.clone(), s5);
let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
matchSomeEnum(s6);
matchSomeEnum(s7);
let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
matchSomeOtherEnum(s8);
- let s9: SomeStructEnum = SomeStructEnum::EnumStruct2{ f1: box some_fields{ field1:10 },
- f2: box s2 };
+ let s9: SomeStructEnum =
+ SomeStructEnum::EnumStruct2 { f1: box some_fields { field1: 10 }, f2: box s2 };
matchSomeStructEnum(s9);
for x in &vec![1, 2, 3] {
struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
-pub trait Error {
-}
+pub trait Error {}
impl Error + 'static {
pub fn is<T: Error + 'static>(&self) -> bool {
}
}
extern crate rustc_serialize;
-#[derive(Clone, Copy, Hash, RustcEncodable, RustcDecodable,
- PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
+#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
struct AllDerives(i32);
fn test_format_args() {
print!("x is {}, y is {1}, name is {n}", x, y, n = name);
}
-
union TestUnion {
- f1: u32
+ f1: u32,
}
struct FrameBuffer;
type Bar = FrameBuffer;
}
-#[doc(include="extra-docs.md")]
+#[doc(include = "extra-docs.md")]
struct StructWithDocs;
+++ /dev/null
-// run-pass
-
-#![allow(dead_code)]
-#![feature(rustc_private)]
-#![no_std]
-
-extern crate rustc_serialize;
-
-#[derive(RustcEncodable)]
-struct Bar {
- x: u32,
-}
-
-#[derive(RustcDecodable)]
-struct Baz {
- x: u32,
-}
-
-fn main() {
- Bar { x: 0 };
- Baz { x: 0 };
-}
// run-pass
#![allow(unused_imports)]
-
#![feature(box_syntax)]
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
-use rustc_serialize::{Encodable, Decodable};
+use rustc_macros::{Decodable, Encodable};
use rustc_serialize::json;
+use rustc_serialize::{Decodable, Encodable};
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
struct A {
foo: Box<[bool]>,
}
#![allow(unused_imports)]
// This briefly tests the capability of `Cell` and `RefCell` to implement the
// `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]`
-
-
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
-use std::cell::{Cell, RefCell};
-use rustc_serialize::{Encodable, Decodable};
+use rustc_macros::{Decodable, Encodable};
use rustc_serialize::json;
+use rustc_serialize::{Decodable, Encodable};
+use std::cell::{Cell, RefCell};
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
struct A {
- baz: isize
+ baz: isize,
}
-#[derive(RustcEncodable, RustcDecodable)]
+#[derive(Encodable, Decodable)]
struct B {
foo: Cell<bool>,
bar: RefCell<A>,
}
fn main() {
- let obj = B {
- foo: Cell::new(true),
- bar: RefCell::new( A { baz: 2 } )
- };
+ let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
let s = json::encode(&obj).unwrap();
let obj2: B = json::decode(&s).unwrap();
assert_eq!(obj.foo.get(), obj2.foo.get());
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
mod submod {
+ use rustc_macros::{Decodable, Encodable};
+
// if any of these are implemented without global calls for any
// function calls, then being in a submodule will (correctly)
// cause errors about unrecognised module `std` (or `extra`)
- #[derive(PartialEq, PartialOrd, Eq, Ord,
- Hash,
- Clone,
- Debug,
- RustcEncodable, RustcDecodable)]
- enum A { A1(usize), A2(isize) }
+ #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
+ enum A {
+ A1(usize),
+ A2(isize),
+ }
- #[derive(PartialEq, PartialOrd, Eq, Ord,
- Hash,
- Clone,
- Debug,
- RustcEncodable, RustcDecodable)]
- struct B { x: usize, y: isize }
+ #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
+ struct B {
+ x: usize,
+ y: isize,
+ }
- #[derive(PartialEq, PartialOrd, Eq, Ord,
- Hash,
- Clone,
- Debug,
- RustcEncodable, RustcDecodable)]
+ #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone, Debug, Encodable, Decodable)]
struct C(usize, isize);
-
}
pub fn main() {}
#![allow(non_upper_case_globals)]
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
+use rustc_macros::{Decodable, Encodable};
+
pub const other: u8 = 1;
pub const f: u8 = 1;
pub const d: u8 = 1;
pub const state: u8 = 1;
pub const cmp: u8 = 1;
-#[derive(Ord,Eq,PartialOrd,PartialEq,Debug,RustcDecodable,RustcEncodable,Hash)]
+#[derive(Ord, Eq, PartialOrd, PartialEq, Debug, Decodable, Encodable, Hash)]
struct Foo {}
-fn main() {
-}
+fn main() {}
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
- Default, Debug, RustcEncodable, RustcDecodable)]
+use rustc_macros::{Decodable, Encodable};
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
struct S {}
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
- Default, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encodable, Decodable)]
struct Z();
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash,
- Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
enum E {
V {},
U,
#![allow(unused_must_use)]
#![allow(dead_code)]
#![allow(unused_imports)]
-
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
-use std::io::Cursor;
-use std::io::prelude::*;
use std::fmt;
+use std::io::prelude::*;
+use std::io::Cursor;
use std::slice;
-use rustc_serialize::{Encodable, Encoder};
+use rustc_macros::Encodable;
use rustc_serialize::json;
use rustc_serialize::opaque;
+use rustc_serialize::{Encodable, Encoder};
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct Foo {
baz: bool,
}
-#[derive(RustcEncodable)]
+#[derive(Encodable)]
struct Bar {
froboz: usize,
}
// ...
}
-fn encode_json<T: Encodable>(val: &T, wr: &mut Cursor<Vec<u8>>) {
+fn encode_json<T: for<'a> Encodable<json::Encoder<'a>>>(val: &T, wr: &mut Cursor<Vec<u8>>) {
write!(wr, "{}", json::as_json(val));
}
-fn encode_opaque<T: Encodable>(val: &T, wr: Vec<u8>) {
+fn encode_opaque<T: Encodable<opaque::Encoder>>(val: &T, wr: Vec<u8>) {
let mut encoder = opaque::Encoder::new(wr);
val.encode(&mut encoder);
}
pub fn main() {
- let target = Foo{baz: false,};
+ let target = Foo { baz: false };
let proto = WireProtocol::JSON;
match proto {
WireProtocol::JSON => encode_json(&target, &mut Cursor::new(Vec::new())),
- WireProtocol::Opaque => encode_opaque(&target, Vec::new())
+ WireProtocol::Opaque => encode_opaque(&target, Vec::new()),
}
}
#![allow(unused_imports)]
#![feature(rustc_private)]
+extern crate rustc_macros;
extern crate rustc_serialize;
-use rustc_serialize::{Encodable, Decodable};
+use rustc_macros::{Decodable, Encodable};
use rustc_serialize::json;
+use rustc_serialize::{Decodable, Encodable};
-#[derive(RustcEncodable, RustcDecodable, PartialEq, Debug)]
+#[derive(Encodable, Decodable, PartialEq, Debug)]
struct UnitLikeStruct;
pub fn main() {
#![allow(unused_imports)]
#![allow(unused_must_use)]
// pretty-expanded FIXME #23616
-
#![feature(rustc_private)]
extern crate rustc_serialize;
-use std::fmt;
-use rustc_serialize::{Encoder, Encodable};
use rustc_serialize::json;
+use rustc_serialize::{Encodable, Encoder};
+use std::fmt;
-struct Foo<T: Encodable> {
+struct Foo<T: for<'a> Encodable<json::Encoder<'a>>> {
v: T,
}
-impl<T: Encodable> Drop for Foo<T> {
+impl<T: for<'a> Encodable<json::Encoder<'a>>> Drop for Foo<T> {
fn drop(&mut self) {
json::encode(&self.v);
}
extern crate rustc_serialize;
-use rustc_serialize::{Encodable, Decodable};
+use rustc_serialize::{json, Decodable, Encodable};
use std::fmt::Display;
-pub trait Entity : Decodable + Encodable + Sized {
- type Key: Clone + Decodable + Encodable + ToString + Display + Eq + Ord + Sized;
+pub trait Entity: Decodable<json::Decoder> + for<'a> Encodable<json::Encoder<'a>> + Sized {
+ type Key: Clone
+ + Decodable<json::Decoder>
+ + for<'a> Encodable<json::Encoder<'a>>
+ + ToString
+ + Display
+ + Eq
+ + Ord
+ + Sized;
fn id(&self) -> Self::Key;
pub id: E::Key,
}
-impl<E> DbRef<E> where E: Entity {
+impl<E> DbRef<E>
+where
+ E: Entity,
+{
fn get(self) -> Option<E> {
E::find_by_id(self.id)
}
// run-pass
#![allow(dead_code)]
-
#![feature(rustc_private)]
extern crate rustc_serialize;
use rustc_serialize::{json, Decodable};
-trait JD : Decodable {}
+trait JD: Decodable<json::Decoder> {}
fn exec<T: JD>() {
let doc = json::from_str("").unwrap();
#![feature(rustc_private)]
+extern crate rustc_macros;
#[allow(dead_code)]
-
extern crate rustc_serialize;
-#[derive(RustcDecodable, RustcEncodable,Debug)]
+use rustc_macros::{Decodable, Encodable};
+
+#[derive(Decodable, Encodable, Debug)]
struct A {
a: String,
}
--> $DIR/missing-associated-types.rs:12:32
|
LL | type Foo<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Y<Rhs>;
- | -------- ^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -------- ^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + X<Rhs> + Y<Rhs> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Mul`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:12:21
--> $DIR/missing-associated-types.rs:15:32
|
LL | type Bar<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Z<Rhs>;
- | -------- ^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -------- ^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + X<Rhs> + Z<Rhs> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0191]: the value of the associated types `A` (from trait `Z`), `B` (from trait `Z`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Div`), `Output` (from trait `std::ops::Div`), `Output` (from trait `std::ops::Mul`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:15:21
--> $DIR/missing-associated-types.rs:18:32
|
LL | type Baz<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Y<Rhs>;
- | -------- ^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -------- ^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + Y<Rhs> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:18:21
--> $DIR/missing-associated-types.rs:21:32
|
LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>;
- | -------- ^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -------- ^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + Fine<Rhs> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0191]: the value of the associated types `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:21:21
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
--> $DIR/bad-sized.rs:4:28
|
LL | let x: Vec<dyn Trait + Sized> = Vec::new();
- | ----- ^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ----- ^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Trait + std::marker::Sized {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/bad-sized.rs:4:12
// check-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
trait Trait {}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/apit-with-const-param.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error: constant expression depends on a generic parameter
+ --> $DIR/array-size-in-generic-struct-param.rs:9:38
+ |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+ | ^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+ --> $DIR/array-size-in-generic-struct-param.rs:20:10
+ |
+LL | arr: [u8; CFG.arr_size],
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/array-size-in-generic-struct-param.rs:9:48
+ |
+LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
+ | ^ non-trivial anonymous constants must not depend on the parameter `N`
+ |
+ = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/array-size-in-generic-struct-param.rs:20:15
+ |
+LL | arr: [u8; CFG.arr_size],
+ | ^^^ non-trivial anonymous constants must not depend on the parameter `CFG`
+ |
+ = help: it is currently only allowed to use either `CFG` or `{ CFG }` as generic constants
+
+error: using `Config` as const generic parameters is forbidden
+ --> $DIR/array-size-in-generic-struct-param.rs:18:21
+ |
+LL | struct B<const CFG: Config> {
+ | ^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 3 previous errors
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Tests that array sizes that depend on const-params are checked using `ConstEvaluatable`.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#[allow(dead_code)]
struct ArithArrayLen<const N: usize>([u32; 0 + N]);
-//~^ ERROR constant expression depends on a generic parameter
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters must not be used inside of non trivial constant values
#[derive(PartialEq, Eq)]
struct Config {
}
struct B<const CFG: Config> {
- arr: [u8; CFG.arr_size], //~ ERROR constant expression depends on a generic parameter
+ //[min]~^ ERROR using `Config` as const generic parameters is forbidden
+ arr: [u8; CFG.arr_size],
+ //[full]~^ ERROR constant expression depends on a generic parameter
+ //[min]~^^ ERROR generic parameters must not be used inside of non trivial
}
const C: Config = Config { arr_size: 5 };
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/array-size-in-generic-struct-param.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
- --> $DIR/array-size-in-generic-struct-param.rs:5:38
- |
-LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
- | ^^^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
- --> $DIR/array-size-in-generic-struct-param.rs:14:10
- |
-LL | arr: [u8; CFG.arr_size],
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub trait Foo {
fn foo(&self);
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/broken-mir-1.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
use std::fmt::Debug;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/broken-mir-2.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/cannot-infer-const-args.rs:12:5
+ |
+LL | foo();
+ | ^^^
+ |
+ = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/cannot-infer-const-args.rs:12:5
+ |
+LL | foo();
+ | ^^^
+ |
+ = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn foo<const X: usize>() -> usize {
0
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/cannot-infer-const-args.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0282]: type annotations needed
- --> $DIR/cannot-infer-const-args.rs:9:5
- |
-LL | foo();
- | ^^^
- |
- = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0282`.
// run-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn foo<const N: usize>(v: &[u8; N]) -> &[u8] {
v
// Test that a concrete const type i.e. A<2>, can be used as an argument type in a function
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct A<const N: usize>; // ok
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/concrete-const-as-fn-arg.rs:4:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// Test that a method/associated non-method within an impl block of a concrete const type i.e. A<2>,
// is callable.
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub struct A<const N: u32>;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/concrete-const-impl-method.rs:5:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
+// Checks that `impl Trait<{anon_const}> for Type` evaluates successfully.
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
trait IsZeroTrait<const IS_ZERO: bool>{}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/condition-in-trait-const-arg.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn const_u32_identity<const X: u32>() -> u32 {
X
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-arg-in-fn.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// run-pass
+// revisions: full
+// FIXME(#75323) Omitted min revision for now due to ICE.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
#![allow(dead_code)]
fn test<const N: usize>() {}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-argument-non-static-lifetime.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error: expected one of `,` or `>`, found `+`
+ --> $DIR/const-expression-parameter.rs:16:22
+ |
+LL | i32_identity::<1 + 2>();
+ | ^ expected one of `,` or `>`
+
+error: aborting due to previous error
+
--- /dev/null
+error: expected one of `,` or `>`, found `+`
+ --> $DIR/const-expression-parameter.rs:16:22
+ |
+LL | i32_identity::<1 + 2>();
+ | ^ expected one of `,` or `>`
+
+error: aborting due to previous error
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn i32_identity<const X: i32>() -> i32 {
5
+++ /dev/null
-error: expected one of `,` or `>`, found `+`
- --> $DIR/const-expression-parameter.rs:13:22
- |
-LL | i32_identity::<1 + 2>();
- | ^ expected one of `,` or `>`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-expression-parameter.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to previous error; 1 warning emitted
-
+// Checks that `const fn` with const params can be used.
// run-pass
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
const fn const_u32_identity<const X: u32>() -> u32 {
X
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-fn-with-const-param.rs:2:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Foo<T, const N: usize>([T; N]);
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-generic-array-wrapper.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#[derive(Debug)]
struct S<const N: usize>;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-generic-type_name.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// check-pass
+// revisions: full min
-#![allow(incomplete_features)]
-#![feature(const_generics)]
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Foo<const A: usize, const B: usize>;
--- /dev/null
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:11:19
+ |
+LL | struct A<const N: &u8>;
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:16:15
+ |
+LL | impl<const N: &u8> A<N> {
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:19:21
+ |
+LL | fn foo<const M: &u8>(&self) {}
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:24:15
+ |
+LL | impl<const N: &u8> B for A<N> {}
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:28:17
+ |
+LL | fn bar<const N: &u8>() {}
+ | ^ explicit lifetime name needed here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
--- /dev/null
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:11:19
+ |
+LL | struct A<const N: &u8>;
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:16:15
+ |
+LL | impl<const N: &u8> A<N> {
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:19:21
+ |
+LL | fn foo<const M: &u8>(&self) {}
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:24:15
+ |
+LL | impl<const N: &u8> B for A<N> {}
+ | ^ explicit lifetime name needed here
+
+error[E0637]: `&` without an explicit lifetime name cannot be used here
+ --> $DIR/const-param-elided-lifetime.rs:28:17
+ |
+LL | fn bar<const N: &u8>() {}
+ | ^ explicit lifetime name needed here
+
+error: using `&'static u8` as const generic parameters is forbidden
+ --> $DIR/const-param-elided-lifetime.rs:11:19
+ |
+LL | struct A<const N: &u8>;
+ | ^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+ --> $DIR/const-param-elided-lifetime.rs:16:15
+ |
+LL | impl<const N: &u8> A<N> {
+ | ^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+ --> $DIR/const-param-elided-lifetime.rs:24:15
+ |
+LL | impl<const N: &u8> B for A<N> {}
+ | ^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+ --> $DIR/const-param-elided-lifetime.rs:28:17
+ |
+LL | fn bar<const N: &u8>() {}
+ | ^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+ --> $DIR/const-param-elided-lifetime.rs:19:21
+ |
+LL | fn foo<const M: &u8>(&self) {}
+ | ^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0637`.
// behaviour of trait bounds where `fn foo<T: Ord<&u8>>() {}` is illegal. Though we could change
// elided lifetimes within the type of a const generic parameters to be 'static, like elided
// lifetimes within const/static items.
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct A<const N: &u8>;
//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
trait B {}
-impl<const N: &u8> A<N> { //~ ERROR `&` without an explicit lifetime name cannot be used here
+impl<const N: &u8> A<N> {
+//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
fn foo<const M: &u8>(&self) {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
+ //[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
}
impl<const N: &u8> B for A<N> {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
fn bar<const N: &u8>() {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
+//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
fn main() {}
+++ /dev/null
-error[E0637]: `&` without an explicit lifetime name cannot be used here
- --> $DIR/const-param-elided-lifetime.rs:9:19
- |
-LL | struct A<const N: &u8>;
- | ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
- --> $DIR/const-param-elided-lifetime.rs:13:15
- |
-LL | impl<const N: &u8> A<N> {
- | ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
- --> $DIR/const-param-elided-lifetime.rs:14:21
- |
-LL | fn foo<const M: &u8>(&self) {}
- | ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
- --> $DIR/const-param-elided-lifetime.rs:18:15
- |
-LL | impl<const N: &u8> B for A<N> {}
- | ^ explicit lifetime name needed here
-
-error[E0637]: `&` without an explicit lifetime name cannot be used here
- --> $DIR/const-param-elided-lifetime.rs:21:17
- |
-LL | fn bar<const N: &u8>() {}
- | ^ explicit lifetime name needed here
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-param-elided-lifetime.rs:6:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 5 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0637`.
--- /dev/null
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/const-param-from-outer-fn.rs:9:9
+ |
+LL | fn foo<const X: u32>() {
+ | - const parameter from outer function
+LL | fn bar() -> u32 {
+ | --- try adding a local generic parameter in this method instead
+LL | X
+ | ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
--- /dev/null
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/const-param-from-outer-fn.rs:9:9
+ |
+LL | fn foo<const X: u32>() {
+ | - const parameter from outer function
+LL | fn bar() -> u32 {
+ | --- try adding a local generic parameter in this method instead
+LL | X
+ | ^ use of generic parameter from outer function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn foo<const X: u32>() {
fn bar() -> u32 {
+++ /dev/null
-error[E0401]: can't use generic parameters from outer function
- --> $DIR/const-param-from-outer-fn.rs:6:9
- |
-LL | fn foo<const X: u32>() {
- | - const parameter from outer function
-LL | fn bar() -> u32 {
- | --- try adding a local generic parameter in this method instead
-LL | X
- | ^ use of generic parameter from outer function
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-param-from-outer-fn.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0401`.
+// Check that const parameters are permitted in traits.
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
-trait Trait<const T: ()> {}
+
+trait Trait<const T: u8> {}
fn main() {}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-param-in-trait.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0770]: the type of const parameters must not depend on other generic parameters
+ --> $DIR/const-param-type-depends-on-const-param.rs:12:52
+ |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+ | ^ the type must not depend on the parameter `N`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+ --> $DIR/const-param-type-depends-on-const-param.rs:16:40
+ |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+ | ^ the type must not depend on the parameter `N`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0770`.
--- /dev/null
+error[E0770]: the type of const parameters must not depend on other generic parameters
+ --> $DIR/const-param-type-depends-on-const-param.rs:12:52
+ |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+ | ^ the type must not depend on the parameter `N`
+
+error[E0770]: the type of const parameters must not depend on other generic parameters
+ --> $DIR/const-param-type-depends-on-const-param.rs:16:40
+ |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+ | ^ the type must not depend on the parameter `N`
+
+error: using `[u8; _]` as const generic parameters is forbidden
+ --> $DIR/const-param-type-depends-on-const-param.rs:12:47
+ |
+LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
+ | ^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `[u8; _]` as const generic parameters is forbidden
+ --> $DIR/const-param-type-depends-on-const-param.rs:16:35
+ |
+LL | pub struct SelfDependent<const N: [u8; N]>;
+ | ^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0770`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
// Currently, const parameters cannot depend on other generic parameters,
// as our current implementation can't really support this.
pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR using `[u8; _]` as const generic parameters is forbidden
pub struct SelfDependent<const N: [u8; N]>;
//~^ ERROR: the type of const parameters must not depend on other generic parameters
+//[min]~^^ ERROR using `[u8; _]` as const generic parameters is forbidden
fn main() {}
+++ /dev/null
-error[E0770]: the type of const parameters must not depend on other generic parameters
- --> $DIR/const-param-type-depends-on-const-param.rs:9:52
- |
-LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
- | ^ the type must not depend on the parameter `N`
-
-error[E0770]: the type of const parameters must not depend on other generic parameters
- --> $DIR/const-param-type-depends-on-const-param.rs:12:40
- |
-LL | pub struct SelfDependent<const N: [u8; N]>;
- | ^ the type must not depend on the parameter `N`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-param-type-depends-on-const-param.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0770`.
--- /dev/null
+error[E0770]: the type of const parameters must not depend on other generic parameters
+ --> $DIR/const-param-type-depends-on-type-param.rs:12:34
+ |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+ | ^ the type must not depend on the parameter `T`
+
+error[E0392]: parameter `T` is never used
+ --> $DIR/const-param-type-depends-on-type-param.rs:12:22
+ |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+ | ^ unused parameter
+ |
+ = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
--- /dev/null
+error[E0770]: the type of const parameters must not depend on other generic parameters
+ --> $DIR/const-param-type-depends-on-type-param.rs:12:34
+ |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+ | ^ the type must not depend on the parameter `T`
+
+error[E0392]: parameter `T` is never used
+ --> $DIR/const-param-type-depends-on-type-param.rs:12:22
+ |
+LL | pub struct Dependent<T, const X: T>([(); X]);
+ | ^ unused parameter
+ |
+ = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0392, E0770.
+For more information about an error, try `rustc --explain E0392`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
// Currently, const parameters cannot depend on other generic parameters,
// as our current implementation can't really support this.
+++ /dev/null
-error[E0770]: the type of const parameters must not depend on other generic parameters
- --> $DIR/const-param-type-depends-on-type-param.rs:9:34
- |
-LL | pub struct Dependent<T, const X: T>([(); X]);
- | ^ the type must not depend on the parameter `T`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-param-type-depends-on-type-param.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0392]: parameter `T` is never used
- --> $DIR/const-param-type-depends-on-type-param.rs:9:22
- |
-LL | pub struct Dependent<T, const X: T>([(); X]);
- | ^ unused parameter
- |
- = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-Some errors have detailed explanations: E0392, E0770.
-For more information about an error, try `rustc --explain E0392`.
--- /dev/null
+error: const parameter `x` should have an upper case name
+ --> $DIR/const-parameter-uppercase-lint.rs:9:15
+ |
+LL | fn noop<const x: u32>() {
+ | ^ help: convert the identifier to upper case (notice the capitalization): `X`
+ |
+note: the lint level is defined here
+ --> $DIR/const-parameter-uppercase-lint.rs:7:9
+ |
+LL | #![deny(non_upper_case_globals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+error: const parameter `x` should have an upper case name
+ --> $DIR/const-parameter-uppercase-lint.rs:9:15
+ |
+LL | fn noop<const x: u32>() {
+ | ^ help: convert the identifier to upper case (notice the capitalization): `X`
+ |
+note: the lint level is defined here
+ --> $DIR/const-parameter-uppercase-lint.rs:7:9
+ |
+LL | #![deny(non_upper_case_globals)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#![deny(non_upper_case_globals)]
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-parameter-uppercase-lint.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: const parameter `x` should have an upper case name
- --> $DIR/const-parameter-uppercase-lint.rs:6:15
- |
-LL | fn noop<const x: u32>() {
- | ^ help: convert the identifier to upper case (notice the capitalization): `X`
- |
-note: the lint level is defined here
- --> $DIR/const-parameter-uppercase-lint.rs:4:9
- |
-LL | #![deny(non_upper_case_globals)]
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
+// Check that arrays can be used with generic const and type.
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#![allow(dead_code, unused_variables)]
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/const-types.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
+// Check that deriving debug on struct with const is permitted.
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#[derive(Debug)]
struct X<const N: usize> {
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/derive-debug-array-wrapper.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/different_byref.rs:13:9
+ |
+LL | x = Const::<{ [4] }> {};
+ | ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+ |
+ = note: expected type `[3_usize]`
+ found type `[4_usize]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+error: using `[usize; 1]` as const generic parameters is forbidden
+ --> $DIR/different_byref.rs:8:23
+ |
+LL | struct Const<const V: [usize; 1]> {}
+ | ^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Check that different const types are different.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Const<const V: [usize; 1]> {}
+//[min]~^ using `[usize; 1]` as const generic parameters is forbidden
fn main() {
let mut x = Const::<{ [3] }> {};
x = Const::<{ [4] }> {};
- //~^ ERROR mismatched types
-
+ //[full]~^ ERROR mismatched types
}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/different_byref.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0308]: mismatched types
- --> $DIR/different_byref.rs:8:9
- |
-LL | x = Const::<{ [4] }> {};
- | ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
- |
- = note: expected type `[3_usize]`
- found type `[4_usize]`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/different_byref_simple.rs:12:9
+ |
+LL | u = ConstUsize::<4> {};
+ | ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+ |
+ = note: expected struct `ConstUsize<3_usize>`
+ found struct `ConstUsize<4_usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/different_byref_simple.rs:12:9
+ |
+LL | u = ConstUsize::<4> {};
+ | ^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+ |
+ = note: expected struct `ConstUsize<3_usize>`
+ found struct `ConstUsize<4_usize>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// Check that different const types are different.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
+struct ConstUsize<const V: usize> {}
+
+fn main() {
+ let mut u = ConstUsize::<3> {};
+ u = ConstUsize::<4> {};
+ //~^ ERROR mismatched types
+}
--- /dev/null
+error: using function pointers as const generic parameters is forbidden
+ --> $DIR/fn-const-param-call.rs:12:25
+ |
+LL | struct Wrapper<const F: fn() -> u32>;
+ | ^^^^^^^^^^^
+
+error: using function pointers as const generic parameters is forbidden
+ --> $DIR/fn-const-param-call.rs:14:15
+ |
+LL | impl<const F: fn() -> u32> Wrapper<F> {
+ | ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+error: using function pointers as const generic parameters is forbidden
+ --> $DIR/fn-const-param-call.rs:12:25
+ |
+LL | struct Wrapper<const F: fn() -> u32>;
+ | ^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using function pointers as const generic parameters is forbidden
+ --> $DIR/fn-const-param-call.rs:14:15
+ |
+LL | impl<const F: fn() -> u32> Wrapper<F> {
+ | ^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Check that functions cannot be used as const parameters.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn function() -> u32 {
17
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/fn-const-param-call.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using function pointers as const generic parameters is forbidden
- --> $DIR/fn-const-param-call.rs:8:25
- |
-LL | struct Wrapper<const F: fn() -> u32>;
- | ^^^^^^^^^^^
-
-error: using function pointers as const generic parameters is forbidden
- --> $DIR/fn-const-param-call.rs:10:15
- |
-LL | impl<const F: fn() -> u32> Wrapper<F> {
- | ^^^^^^^^^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
--- /dev/null
+error: using function pointers as const generic parameters is forbidden
+ --> $DIR/fn-const-param-infer.rs:7:25
+ |
+LL | struct Checked<const F: fn(usize) -> bool>;
+ | ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+error: using function pointers as const generic parameters is forbidden
+ --> $DIR/fn-const-param-infer.rs:7:25
+ |
+LL | struct Checked<const F: fn(usize) -> bool>;
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Checked<const F: fn(usize) -> bool>;
//~^ ERROR: using function pointers as const generic parameters
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/fn-const-param-infer.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using function pointers as const generic parameters is forbidden
- --> $DIR/fn-const-param-infer.rs:4:25
- |
-LL | struct Checked<const F: fn(usize) -> bool>;
- | ^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
use std::fmt::Display;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/fn-taking-const-generic-array.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+ --> $DIR/forbid-non-structural_match-types.rs:15:19
+ |
+LL | struct D<const X: C>;
+ | ^ `C` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0741`.
--- /dev/null
+error: using `A` as const generic parameters is forbidden
+ --> $DIR/forbid-non-structural_match-types.rs:10:19
+ |
+LL | struct B<const X: A>; // ok
+ | ^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `C` as const generic parameters is forbidden
+ --> $DIR/forbid-non-structural_match-types.rs:15:19
+ |
+LL | struct D<const X: C>;
+ | ^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
+ --> $DIR/forbid-non-structural_match-types.rs:15:19
+ |
+LL | struct D<const X: C>;
+ | ^ `C` doesn't derive both `PartialEq` and `Eq`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0741`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#[derive(PartialEq, Eq)]
struct A;
struct B<const X: A>; // ok
+//[min]~^ ERROR using `A` as const generic parameters is forbidden
struct C;
struct D<const X: C>; //~ ERROR `C` must be annotated with `#[derive(PartialEq, Eq)]`
+//[min]~^ ERROR using `C` as const generic parameters is forbidden
fn main() {}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/forbid-non-structural_match-types.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
- --> $DIR/forbid-non-structural_match-types.rs:11:19
- |
-LL | struct D<const X: C>;
- | ^ `C` doesn't derive both `PartialEq` and `Eq`
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0741`.
--- /dev/null
+error[E0044]: foreign items may not have const parameters
+ --> $DIR/foreign-item-const-parameter.rs:8:5
+ |
+LL | fn foo<const X: usize>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
+ |
+ = help: replace the const parameters with concrete consts
+
+error[E0044]: foreign items may not have type or const parameters
+ --> $DIR/foreign-item-const-parameter.rs:10:5
+ |
+LL | fn bar<T, const X: usize>(_: T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
+ |
+ = help: replace the type or const parameters with concrete types or consts
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0044`.
--- /dev/null
+error[E0044]: foreign items may not have const parameters
+ --> $DIR/foreign-item-const-parameter.rs:8:5
+ |
+LL | fn foo<const X: usize>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
+ |
+ = help: replace the const parameters with concrete consts
+
+error[E0044]: foreign items may not have type or const parameters
+ --> $DIR/foreign-item-const-parameter.rs:10:5
+ |
+LL | fn bar<T, const X: usize>(_: T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
+ |
+ = help: replace the type or const parameters with concrete types or consts
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0044`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
extern "C" {
fn foo<const X: usize>(); //~ ERROR foreign items may not have const parameters
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/foreign-item-const-parameter.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0044]: foreign items may not have const parameters
- --> $DIR/foreign-item-const-parameter.rs:5:5
- |
-LL | fn foo<const X: usize>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters
- |
- = help: replace the const parameters with concrete consts
-
-error[E0044]: foreign items may not have type or const parameters
- --> $DIR/foreign-item-const-parameter.rs:7:5
- |
-LL | fn bar<T, const X: usize>(_: T);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have type or const parameters
- |
- = help: replace the type or const parameters with concrete types or consts
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0044`.
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct S<const X: u32>;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/impl-const-generic-struct.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0107]: wrong number of const arguments: expected 2, found 1
+ --> $DIR/incorrect-number-of-const-args.rs:12:5
+ |
+LL | foo::<0>();
+ | ^^^^^^^^ expected 2 const arguments
+
+error[E0107]: wrong number of const arguments: expected 2, found 3
+ --> $DIR/incorrect-number-of-const-args.rs:13:17
+ |
+LL | foo::<0, 0, 0>();
+ | ^ unexpected const argument
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
--- /dev/null
+error[E0107]: wrong number of const arguments: expected 2, found 1
+ --> $DIR/incorrect-number-of-const-args.rs:12:5
+ |
+LL | foo::<0>();
+ | ^^^^^^^^ expected 2 const arguments
+
+error[E0107]: wrong number of const arguments: expected 2, found 3
+ --> $DIR/incorrect-number-of-const-args.rs:13:17
+ |
+LL | foo::<0, 0, 0>();
+ | ^ unexpected const argument
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn foo<const X: usize, const Y: usize>() -> usize {
0
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/incorrect-number-of-const-args.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0107]: wrong number of const arguments: expected 2, found 1
- --> $DIR/incorrect-number-of-const-args.rs:9:5
- |
-LL | foo::<0>();
- | ^^^^^^^^ expected 2 const arguments
-
-error[E0107]: wrong number of const arguments: expected 2, found 3
- --> $DIR/incorrect-number-of-const-args.rs:10:17
- |
-LL | foo::<0, 0, 0>();
- | ^ unexpected const argument
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0107`.
// run-pass
//
// see issue #70529
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct A<const N: usize> {
arr: [u8; N],
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/infer_arg_from_pat.rs:4:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// check-pass
//
// see issue #70529
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn as_chunks<const N: usize>() -> [u8; N] {
loop {}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/infer_arr_len_from_pat.rs:4:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// check-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) {
f([1, 2, 3]);
|_| {}
}
-fn main() {}
+fn main() {
+ takes_closure_of_array_3(returns_closure_of_array_3());
+ takes_closure_of_array_3_apit(returns_closure_of_array_3());
+}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error: constant expression depends on a generic parameter
+ --> $DIR/issue-61522-array-len-succ.rs:7:40
+ |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+ --> $DIR/issue-61522-array-len-succ.rs:12:24
+ |
+LL | fn inner(&self) -> &[u8; COUNT + 1] {
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/issue-61522-array-len-succ.rs:7:45
+ |
+LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
+ | ^^^^^ non-trivial anonymous constants must not depend on the parameter `COUNT`
+ |
+ = help: it is currently only allowed to use either `COUNT` or `{ COUNT }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/issue-61522-array-len-succ.rs:12:30
+ |
+LL | fn inner(&self) -> &[u8; COUNT + 1] {
+ | ^^^^^ non-trivial anonymous constants must not depend on the parameter `COUNT`
+ |
+ = help: it is currently only allowed to use either `COUNT` or `{ COUNT }` as generic constants
+
+error: aborting due to 2 previous errors
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
-//~^ ERROR constant expression depends on a generic parameter
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters must not be used
impl<const COUNT: usize> MyArray<COUNT> {
fn inner(&self) -> &[u8; COUNT + 1] {
- //~^ ERROR constant expression depends on a generic parameter
+ //[full]~^ ERROR constant expression depends on a generic parameter
+ //[min]~^^ ERROR generic parameters must not be used
&self.0
}
}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/issue-61522-array-len-succ.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
- --> $DIR/issue-61522-array-len-succ.rs:4:40
- |
-LL | pub struct MyArray<const COUNT: usize>([u8; COUNT + 1]);
- | ^^^^^^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
- --> $DIR/issue-61522-array-len-succ.rs:8:24
- |
-LL | fn inner(&self) -> &[u8; COUNT + 1] {
- | ^^^^^^^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
--- /dev/null
+error: using `&'static str` as const generic parameters is forbidden
+ --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:9:25
+ |
+LL | trait Trait<const NAME: &'static str> {
+ | ^^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
-// check-pass
+//[full] check-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
trait Trait<const NAME: &'static str> {
+//[min]~^ ERROR using `&'static str` as const generic parameters is forbidden
type Assoc;
}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// aux-build:impl-const.rs
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
extern crate impl_const;
// build-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub fn works() {
let array/*: [_; _]*/ = default_array();
// build-pass
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn works() {
let array/*: [u8; _]*/ = default_byte_array();
// check-pass
-#![allow(incomplete_features)]
-#![feature(const_generics)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub trait Foo<const B: bool> {}
pub fn bar<T: Foo<{ true }>>() {}
// run-pass
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
use std::ops::AddAssign;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/mut-ref-const-param-array.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0391]: cycle detected when computing type of `Foo`
+ --> $DIR/nested-type.rs:7:1
+ |
+LL | struct Foo<const N: [u8; {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: ...which requires computing type of `Foo::N`...
+ --> $DIR/nested-type.rs:7:18
+ |
+LL | struct Foo<const N: [u8; {
+ | ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+ --> $DIR/nested-type.rs:11:5
+ |
+LL | struct Foo<const N: usize>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which requires computing the variances for items in this crate...
+ = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/nested-type.rs:3:1
+ |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
+
+error[E0391]: cycle detected when computing type of `Foo`
+ --> $DIR/nested-type.rs:7:1
+ |
+LL | struct Foo<const N: [u8; {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: ...which requires computing type of `Foo::N`...
+ --> $DIR/nested-type.rs:7:18
+ |
+LL | struct Foo<const N: [u8; {
+ | ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+ --> $DIR/nested-type.rs:11:5
+ |
+LL | struct Foo<const N: usize>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which requires computing the variances for items in this crate...
+ = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/nested-type.rs:3:1
+ |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
--- /dev/null
+error: using `[u8; _]` as const generic parameters is forbidden
+ --> $DIR/nested-type.rs:7:21
+ |
+LL | struct Foo<const N: [u8; {
+ | _____________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |__^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error[E0391]: cycle detected when computing type of `Foo`
+ --> $DIR/nested-type.rs:7:1
+ |
+LL | struct Foo<const N: [u8; {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: ...which requires computing type of `Foo::N`...
+ --> $DIR/nested-type.rs:7:18
+ |
+LL | struct Foo<const N: [u8; {
+ | ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+ --> $DIR/nested-type.rs:11:5
+ |
+LL | struct Foo<const N: usize>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which requires computing the variances for items in this crate...
+ = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/nested-type.rs:3:1
+ |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
+
+error[E0391]: cycle detected when computing type of `Foo`
+ --> $DIR/nested-type.rs:7:1
+ |
+LL | struct Foo<const N: [u8; {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: ...which requires computing type of `Foo::N`...
+ --> $DIR/nested-type.rs:7:18
+ |
+LL | struct Foo<const N: [u8; {
+ | ^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires const-evaluating `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires type-checking `Foo::{{constant}}#0`...
+ --> $DIR/nested-type.rs:7:26
+ |
+LL | struct Foo<const N: [u8; {
+ | __________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | Foo::<17>::value()
+LL | | }]>;
+ | |_^
+note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
+ --> $DIR/nested-type.rs:11:5
+ |
+LL | struct Foo<const N: usize>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: ...which requires computing the variances for items in this crate...
+ = note: ...which again requires computing type of `Foo`, completing the cycle
+note: cycle used when collecting item types in top-level module
+ --> $DIR/nested-type.rs:3:1
+ |
+LL | / #![cfg_attr(full, feature(const_generics))]
+LL | | #![cfg_attr(full, allow(incomplete_features))]
+LL | | #![cfg_attr(min, feature(min_const_generics))]
+LL | |
+... |
+LL | |
+LL | | fn main() {}
+ | |____________^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0391`.
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Foo<const N: [u8; {
//~^ ERROR cycle detected
//~| ERROR cycle detected
+//[min]~| ERROR using `[u8; _]` as const generic
struct Foo<const N: usize>;
impl<const N: usize> Foo<N> {
+++ /dev/null
-error[E0391]: cycle detected when computing type of `Foo`
- --> $DIR/nested-type.rs:4:1
- |
-LL | struct Foo<const N: [u8; {
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: ...which requires computing type of `Foo::N`...
- --> $DIR/nested-type.rs:4:18
- |
-LL | struct Foo<const N: [u8; {
- | ^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires const-evaluating `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires type-checking `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
- --> $DIR/nested-type.rs:7:5
- |
-LL | struct Foo<const N: usize>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing the variances for items in this crate...
- = note: ...which again requires computing type of `Foo`, completing the cycle
-note: cycle used when collecting item types in top-level module
- --> $DIR/nested-type.rs:1:1
- |
-LL | / #![feature(const_generics)]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | struct Foo<const N: [u8; {
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
-
-error[E0391]: cycle detected when computing type of `Foo`
- --> $DIR/nested-type.rs:4:1
- |
-LL | struct Foo<const N: [u8; {
- | ^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: ...which requires computing type of `Foo::N`...
- --> $DIR/nested-type.rs:4:18
- |
-LL | struct Foo<const N: [u8; {
- | ^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires const-evaluating `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires type-checking `Foo::{{constant}}#0`...
- --> $DIR/nested-type.rs:4:26
- |
-LL | struct Foo<const N: [u8; {
- | __________________________^
-LL | |
-LL | |
-LL | | struct Foo<const N: usize>;
-... |
-LL | | Foo::<17>::value()
-LL | | }]>;
- | |_^
-note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
- --> $DIR/nested-type.rs:7:5
- |
-LL | struct Foo<const N: usize>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: ...which requires computing the variances for items in this crate...
- = note: ...which again requires computing type of `Foo`, completing the cycle
-note: cycle used when collecting item types in top-level module
- --> $DIR/nested-type.rs:1:1
- |
-LL | / #![feature(const_generics)]
-LL | | #![allow(incomplete_features)]
-LL | |
-LL | | struct Foo<const N: [u8; {
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0391`.
--- /dev/null
+error: type parameters with a default must be trailing
+ --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:12
+ |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+ | ^
+ |
+ = note: using type defaults and const parameters in the same parameter list is currently not permitted
+
+error: constant values inside of type parameter defaults must not depend on generic parameters
+ --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:44
+ |
+LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
+ | ^ the anonymous constant must not depend on the parameter `T`
+
+error: constant values inside of type parameter defaults must not depend on generic parameters
+ --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
+ |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+ | ^ the anonymous constant must not depend on the parameter `N`
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+error: type parameters with a default must be trailing
+ --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:12
+ |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+ | ^
+ |
+ = note: using type defaults and const parameters in the same parameter list is currently not permitted
+
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:44
+ |
+LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
+ | ^ non-trivial anonymous constants must not depend on the parameter `T`
+ |
+ = help: it is currently only allowed to use either `T` or `{ T }` as generic constants
+
+error: constant values inside of type parameter defaults must not depend on generic parameters
+ --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:12:21
+ |
+LL | struct Bar<T = [u8; N], const N: usize>(T);
+ | ^ the anonymous constant must not depend on the parameter `N`
+
+error: aborting due to 3 previous errors
+
-#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-//~^ ERROR constant values inside of type parameter defaults
+//[full]~^ ERROR constant values inside of type parameter defaults
+//[min]~^^ ERROR generic parameters must not be used inside of non trivial
// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults.
struct Bar<T = [u8; N], const N: usize>(T);
+++ /dev/null
-error: type parameters with a default must be trailing
- --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:12
- |
-LL | struct Bar<T = [u8; N], const N: usize>(T);
- | ^
- |
- = note: using type defaults and const parameters in the same parameter list is currently not permitted
-
-error: constant values inside of type parameter defaults must not depend on generic parameters
- --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:3:44
- |
-LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
- | ^ the anonymous constant must not depend on the parameter `T`
-
-error: constant values inside of type parameter defaults must not depend on generic parameters
- --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:7:21
- |
-LL | struct Bar<T = [u8; N], const N: usize>(T);
- | ^ the anonymous constant must not depend on the parameter `N`
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
--- /dev/null
+error: using raw pointers as const generic parameters is forbidden
+ --> $DIR/raw-ptr-const-param-deref.rs:10:23
+ |
+LL | struct Const<const P: *const u32>;
+ | ^^^^^^^^^^
+
+error: using raw pointers as const generic parameters is forbidden
+ --> $DIR/raw-ptr-const-param-deref.rs:12:15
+ |
+LL | impl<const P: *const u32> Const<P> {
+ | ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+error: using raw pointers as const generic parameters is forbidden
+ --> $DIR/raw-ptr-const-param-deref.rs:10:23
+ |
+LL | struct Const<const P: *const u32>;
+ | ^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using raw pointers as const generic parameters is forbidden
+ --> $DIR/raw-ptr-const-param-deref.rs:12:15
+ |
+LL | impl<const P: *const u32> Const<P> {
+ | ^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Checks that pointers must not be used as the type of const params.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
const A: u32 = 3;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/raw-ptr-const-param-deref.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using raw pointers as const generic parameters is forbidden
- --> $DIR/raw-ptr-const-param-deref.rs:6:23
- |
-LL | struct Const<const P: *const u32>;
- | ^^^^^^^^^^
-
-error: using raw pointers as const generic parameters is forbidden
- --> $DIR/raw-ptr-const-param-deref.rs:8:15
- |
-LL | impl<const P: *const u32> Const<P> {
- | ^^^^^^^^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
--- /dev/null
+error: using raw pointers as const generic parameters is forbidden
+ --> $DIR/raw-ptr-const-param.rs:7:23
+ |
+LL | struct Const<const P: *const u32>;
+ | ^^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+error: using raw pointers as const generic parameters is forbidden
+ --> $DIR/raw-ptr-const-param.rs:7:23
+ |
+LL | struct Const<const P: *const u32>;
+ | ^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to previous error
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/raw-ptr-const-param.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: using raw pointers as const generic parameters is forbidden
- --> $DIR/raw-ptr-const-param.rs:4:23
- |
-LL | struct Const<const P: *const u32>;
- | ^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/slice-const-param-mismatch.rs:15:35
+ |
+LL | let _: ConstString<"Hello"> = ConstString::<"World">;
+ | -------------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `ConstString<"Hello">`
+ found struct `ConstString<"World">`
+
+error[E0308]: mismatched types
+ --> $DIR/slice-const-param-mismatch.rs:17:33
+ |
+LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
+ | ------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `ConstString<"ℇ㇈↦">`
+ found struct `ConstString<"ℇ㇈↥">`
+
+error[E0308]: mismatched types
+ --> $DIR/slice-const-param-mismatch.rs:19:33
+ |
+LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
+ | ------------------ ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `ConstBytes<b"AAA">`
+ found struct `ConstBytes<b"BBB">`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+error: using `&'static str` as const generic parameters is forbidden
+ --> $DIR/slice-const-param-mismatch.rs:8:29
+ |
+LL | struct ConstString<const T: &'static str>;
+ | ^^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static [u8]` as const generic parameters is forbidden
+ --> $DIR/slice-const-param-mismatch.rs:10:28
+ |
+LL | struct ConstBytes<const T: &'static [u8]>;
+ | ^^^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+
struct ConstString<const T: &'static str>;
+//[min]~^ ERROR
struct ConstBytes<const T: &'static [u8]>;
+//[min]~^ ERROR
pub fn main() {
let _: ConstString<"Hello"> = ConstString::<"Hello">;
- let _: ConstString<"Hello"> = ConstString::<"World">; //~ ERROR mismatched types
+ let _: ConstString<"Hello"> = ConstString::<"World">; //[full]~ ERROR mismatched types
let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↦">;
- let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //~ ERROR mismatched types
+ let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; //[full]~ ERROR mismatched types
let _: ConstBytes<b"AAA"> = ConstBytes::<{&[0x41, 0x41, 0x41]}>;
- let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //~ ERROR mismatched types
+ let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">; //[full]~ ERROR mismatched types
}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/slice-const-param-mismatch.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0308]: mismatched types
- --> $DIR/slice-const-param-mismatch.rs:9:35
- |
-LL | let _: ConstString<"Hello"> = ConstString::<"World">;
- | -------------------- ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"`
- | |
- | expected due to this
- |
- = note: expected struct `ConstString<"Hello">`
- found struct `ConstString<"World">`
-
-error[E0308]: mismatched types
- --> $DIR/slice-const-param-mismatch.rs:11:33
- |
-LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">;
- | ------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"`
- | |
- | expected due to this
- |
- = note: expected struct `ConstString<"ℇ㇈↦">`
- found struct `ConstString<"ℇ㇈↥">`
-
-error[E0308]: mismatched types
- --> $DIR/slice-const-param-mismatch.rs:13:33
- |
-LL | let _: ConstBytes<b"AAA"> = ConstBytes::<b"BBB">;
- | ------------------ ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"`
- | |
- | expected due to this
- |
- = note: expected struct `ConstBytes<b"AAA">`
- found struct `ConstBytes<b"BBB">`
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+error: using `&'static str` as const generic parameters is forbidden
+ --> $DIR/slice-const-param.rs:8:40
+ |
+LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
+ | ^^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static [u8]` as const generic parameters is forbidden
+ --> $DIR/slice-const-param.rs:13:41
+ |
+LL | pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
+ | ^^^^^^^^^^^^^
+ |
+ = note: the only supported types are integers, `bool` and `char`
+ = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
-// run-pass
+//[full] run-pass
+// revisions: min full
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub fn function_with_str<const STRING: &'static str>() -> &'static str {
+ //[min]~^ ERROR using `&'static str` as const
STRING
}
pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
+ //[min]~^ ERROR using `&'static [u8]` as const
BYTES
}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/slice-const-param.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0573]: expected type, found const parameter `C`
+ --> $DIR/struct-with-invalid-const-param.rs:8:23
+ |
+LL | struct S<const C: u8>(C);
+ | ^ not a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
--- /dev/null
+error[E0573]: expected type, found const parameter `C`
+ --> $DIR/struct-with-invalid-const-param.rs:8:23
+ |
+LL | struct S<const C: u8>(C);
+ | ^ not a type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0573`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Checks that a const param cannot be stored in a struct.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct S<const C: u8>(C); //~ ERROR expected type, found const parameter
// check-pass
-#![allow(incomplete_features)]
-#![feature(const_generics)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct Const<const N: usize>;
trait Foo<const N: usize> {}
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
use std::mem::MaybeUninit;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
// run-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
trait T<const A: usize> {
fn l<const N: bool>() -> usize;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/type_of_anon_const.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/uninferred-consts.rs:14:5
+ |
+LL | Foo.foo();
+ | ^^^^^^^^^
+ |
+ = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
--- /dev/null
+error[E0282]: type annotations needed
+ --> $DIR/uninferred-consts.rs:14:5
+ |
+LL | Foo.foo();
+ | ^^^^^^^^^
+ |
+ = note: unable to infer the value of a const parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Test that we emit an error if we cannot properly infer a constant.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
struct Foo;
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/uninferred-consts.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error[E0282]: type annotations needed
- --> $DIR/uninferred-consts.rs:10:5
- |
-LL | Foo.foo();
- | ^^^^^^^^^
- |
- = note: unable to infer the value of a const parameter
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0282`.
--- /dev/null
+error[E0412]: cannot find type `UnknownStruct` in this scope
+ --> $DIR/unknown_adt.rs:8:12
+ |
+LL | let _: UnknownStruct<7>;
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
--- /dev/null
+error[E0412]: cannot find type `UnknownStruct` in this scope
+ --> $DIR/unknown_adt.rs:8:12
+ |
+LL | let _: UnknownStruct<7>;
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
-#![feature(const_generics)]
-#![allow(incomplete_features)]
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
fn main() {
let _: UnknownStruct<7>;
+++ /dev/null
-error[E0412]: cannot find type `UnknownStruct` in this scope
- --> $DIR/unknown_adt.rs:5:12
- |
-LL | let _: UnknownStruct<7>;
- | ^^^^^^^^^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0412`.
// check-pass
+// revisions: full min
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
struct A<const N: usize>; // ok
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/unused-const-param.rs:3:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-warning: 1 warning emitted
-
--- /dev/null
+// check-pass
+// run-rustfix
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+#![warn(unused_braces)]
+
+
+struct A<const N: usize>;
+
+fn main() {
+ let _: A<7>; // ok
+ let _: A<7>; //~ WARN unnecessary braces
+ let _: A<{ 3 + 5 }>; // ok
+}
--- /dev/null
+warning: unnecessary braces around const expression
+ --> $DIR/unused_braces.rs:15:14
+ |
+LL | let _: A<{ 7 }>;
+ | ^^^^^ help: remove these braces
+ |
+note: the lint level is defined here
+ --> $DIR/unused_braces.rs:8:9
+ |
+LL | #![warn(unused_braces)]
+ | ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
--- /dev/null
+// check-pass
+// run-rustfix
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
+#![warn(unused_braces)]
+
+
+struct A<const N: usize>;
+
+fn main() {
+ let _: A<7>; // ok
+ let _: A<7>; //~ WARN unnecessary braces
+ let _: A<{ 3 + 5 }>; // ok
+}
--- /dev/null
+warning: unnecessary braces around const expression
+ --> $DIR/unused_braces.rs:15:14
+ |
+LL | let _: A<{ 7 }>;
+ | ^^^^^ help: remove these braces
+ |
+note: the lint level is defined here
+ --> $DIR/unused_braces.rs:8:9
+ |
+LL | #![warn(unused_braces)]
+ | ^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
// check-pass
// run-rustfix
+// revisions: full min
-#![allow(incomplete_features)]
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
#![warn(unused_braces)]
-#![feature(const_generics)]
struct A<const N: usize>;
+++ /dev/null
-warning: unnecessary braces around const expression
- --> $DIR/unused_braces.rs:13:14
- |
-LL | let _: A<{ 7 }>;
- | ^^^^^ help: remove these braces
- |
-note: the lint level is defined here
- --> $DIR/unused_braces.rs:5:9
- |
-LL | #![warn(unused_braces)]
- | ^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-
--- /dev/null
+error: constant expression depends on a generic parameter
+ --> $DIR/wf-misc.rs:9:12
+ |
+LL | let _: [u8; N + 1];
+ | ^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+ --> $DIR/wf-misc.rs:17:12
+ |
+LL | let _: Const::<{N + 1}>;
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/wf-misc.rs:9:17
+ |
+LL | let _: [u8; N + 1];
+ | ^ non-trivial anonymous constants must not depend on the parameter `N`
+ |
+ = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+ --> $DIR/wf-misc.rs:17:21
+ |
+LL | let _: Const::<{N + 1}>;
+ | ^ non-trivial anonymous constants must not depend on the parameter `N`
+ |
+ = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 2 previous errors
+
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// Tests miscellaneous well-formedness examples.
+// revisions: full min
+
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(full, allow(incomplete_features))]
+#![cfg_attr(min, feature(min_const_generics))]
pub fn arr_len<const N: usize>() {
let _: [u8; N + 1];
- //~^ ERROR constant expression depends on a generic parameter
+ //[full]~^ ERROR constant expression depends on a generic parameter
+ //[min]~^^ ERROR generic parameters must not be used inside of non trivial
}
struct Const<const N: usize>;
pub fn func_call<const N: usize>() {
let _: Const::<{N + 1}>;
- //~^ ERROR constant expression depends on a generic parameter
+ //[full]~^ ERROR constant expression depends on a generic parameter
+ //[min]~^^ ERROR generic parameters must not be used inside of non trivial
}
fn main() {}
+++ /dev/null
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/wf-misc.rs:1:12
- |
-LL | #![feature(const_generics)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-
-error: constant expression depends on a generic parameter
- --> $DIR/wf-misc.rs:5:12
- |
-LL | let _: [u8; N + 1];
- | ^^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: constant expression depends on a generic parameter
- --> $DIR/wf-misc.rs:12:12
- |
-LL | let _: Const::<{N + 1}>;
- | ^^^^^^^^^^^^^^^^
- |
- = note: this may fail depending on what value the parameter takes
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
--> $DIR/E0225.rs:6:36
|
LL | let _: Box<dyn std::io::Read + std::io::Write>;
- | ------------- ^^^^^^^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ------------- ^^^^^^^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/E0225.rs:8:20
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error: aborting due to 2 previous errors
fn foo() {
self.bar(); //~ ERROR E0424
}
+
+ fn baz(_: i32) {
+ self.bar(); //~ ERROR E0424
+ }
}
fn main () {
error[E0424]: expected value, found module `self`
--> $DIR/E0424.rs:7:9
|
-LL | / fn foo() {
-LL | | self.bar();
- | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-LL | | }
- | |_____- this function doesn't have a `self` parameter
+LL | fn foo() {
+ | --- this function doesn't have a `self` parameter
+LL | self.bar();
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+ |
+help: add a `self` receiver parameter to make the associated `fn` a method
+ |
+LL | fn foo(&self) {
+ | ^^^^^
+
+error[E0424]: expected value, found module `self`
+ --> $DIR/E0424.rs:11:9
+ |
+LL | fn baz(_: i32) {
+ | --- this function doesn't have a `self` parameter
+LL | self.bar();
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+ |
+help: add a `self` receiver parameter to make the associated `fn` a method
+ |
+LL | fn baz(&self, _: i32) {
+ | ^^^^^^
error[E0424]: expected unit struct, unit variant or constant, found module `self`
- --> $DIR/E0424.rs:12:9
+ --> $DIR/E0424.rs:16:9
|
-LL | / fn main () {
-LL | | let self = "self";
- | | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
-LL | | }
- | |_- this function doesn't have a `self` parameter
+LL | fn main () {
+ | ---- this function can't have a `self` parameter
+LL | let self = "self";
+ | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0424`.
--- /dev/null
+// Previously this ICE'd because `fn g()` would be lowered, but the block associated with `fn f()`
+// wasn't.
+
+// compile-flags: --crate-type=lib
+
+extern "C" {
+ fn f() {
+ //~^ incorrect function inside `extern` block
+ fn g() {}
+ }
+}
--- /dev/null
+error: incorrect function inside `extern` block
+ --> $DIR/issue-74120-lowering-of-ffi-block-bodies.rs:7:8
+ |
+LL | extern "C" {
+ | ---------- `extern` blocks define existing foreign functions and functions inside of them cannot have a body
+LL | fn f() {
+ | ________^___-
+ | | |
+ | | cannot have a body
+LL | |
+LL | | fn g() {}
+LL | | }
+ | |_____- help: remove the invalid body: `;`
+ |
+ = help: you might have meant to write a function accessible through FFI, which can be done by writing `extern fn` outside of the `extern` block
+ = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html
+
+error: aborting due to previous error
+
--> $DIR/issue-22560.rs:9:23
|
LL | type Test = dyn Add + Sub;
- | --- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | --- ^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add<[type error]> + Sub<[type error]> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified
--> $DIR/issue-22560.rs:9:17
--> $DIR/issue-32963.rs:8:31
|
LL | size_of_copy::<dyn Misc + Copy>();
- | ---- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ---- ^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + std::marker::Copy {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/issue-32963.rs:8:31
|
LL | size_of_copy::<dyn Misc + Copy>();
- | ---- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ---- ^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + std::marker::Copy {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
--> $DIR/issue-32963.rs:8:5
-trait B < A > { fn a() -> A { this.a } } //~ ERROR cannot find value `this` in this scope
+trait B <A> {
+ fn a() -> A {
+ this.a //~ ERROR cannot find value `this` in this scope
+ }
+ fn b(x: i32) {
+ this.b(x); //~ ERROR cannot find value `this` in this scope
+ }
+}
fn main() {}
error[E0425]: cannot find value `this` in this scope
- --> $DIR/issue-5099.rs:1:31
+ --> $DIR/issue-5099.rs:3:9
|
-LL | trait B < A > { fn a() -> A { this.a } }
- | ^^^^ not found in this scope
+LL | this.a
+ | ^^^^ not found in this scope
+ |
+help: you might have meant to use `self` here instead
+ |
+LL | self.a
+ | ^^^^
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+ |
+LL | fn a(&self) -> A {
+ | ^^^^^
+
+error[E0425]: cannot find value `this` in this scope
+ --> $DIR/issue-5099.rs:6:9
+ |
+LL | this.b(x);
+ | ^^^^ not found in this scope
+ |
+help: you might have meant to use `self` here instead
+ |
+LL | self.b(x);
+ | ^^^^
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+ |
+LL | fn b(&self, x: i32) {
+ | ^^^^^^
-error: aborting due to previous error
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0425`.
--- /dev/null
+// Regression test for #66768.
+// check-pass
+#![allow(dead_code)]
+//-^ "dead code" is needed to reproduce the issue.
+
+use std::marker::PhantomData;
+use std::ops::{Add, Mul};
+
+fn problematic_function<Space>(material_surface_element: Edge2dElement)
+where
+ DefaultAllocator: FiniteElementAllocator<DimU1, Space>,
+{
+ let _: Point2<f64> = material_surface_element.map_reference_coords().into();
+}
+
+impl<T> ArrayLength<T> for UTerm {
+ type ArrayType = ();
+}
+impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B0> {
+ type ArrayType = GenericArrayImplEven<T, N>;
+}
+impl<T, N: ArrayLength<T>> ArrayLength<T> for UInt<N, B1> {
+ type ArrayType = GenericArrayImplOdd<T, N>;
+}
+impl<U> Add<U> for UTerm {
+ type Output = U;
+ fn add(self, _: U) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl<Ul, Ur> Add<UInt<Ur, B1>> for UInt<Ul, B0>
+where
+ Ul: Add<Ur>,
+{
+ type Output = UInt<Sum<Ul, Ur>, B1>;
+ fn add(self, _: UInt<Ur, B1>) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl<U> Mul<U> for UTerm {
+ type Output = UTerm;
+ fn mul(self, _: U) -> Self {
+ unimplemented!()
+ }
+}
+impl<Ul, B, Ur> Mul<UInt<Ur, B>> for UInt<Ul, B0>
+where
+ Ul: Mul<UInt<Ur, B>>,
+{
+ type Output = UInt<Prod<Ul, UInt<Ur, B>>, B0>;
+ fn mul(self, _: UInt<Ur, B>) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl<Ul, B, Ur> Mul<UInt<Ur, B>> for UInt<Ul, B1>
+where
+ Ul: Mul<UInt<Ur, B>>,
+ UInt<Prod<Ul, UInt<Ur, B>>, B0>: Add<UInt<Ur, B>>,
+{
+ type Output = Sum<UInt<Prod<Ul, UInt<Ur, B>>, B0>, UInt<Ur, B>>;
+ fn mul(self, _: UInt<Ur, B>) -> Self::Output {
+ unimplemented!()
+ }
+}
+impl<N, R, C> Allocator<N, R, C> for DefaultAllocator
+where
+ R: DimName,
+ C: DimName,
+ R::Value: Mul<C::Value>,
+ Prod<R::Value, C::Value>: ArrayLength<N>,
+{
+ type Buffer = ArrayStorage<N, R, C>;
+ fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
+ unimplemented!()
+ }
+ fn allocate_from_iterator<I>(_: R, _: C, _: I) -> Self::Buffer {
+ unimplemented!()
+ }
+}
+impl<N, C> Allocator<N, Dynamic, C> for DefaultAllocator {
+ type Buffer = VecStorage<N, Dynamic, C>;
+ fn allocate_uninitialized(_: Dynamic, _: C) -> Self::Buffer {
+ unimplemented!()
+ }
+ fn allocate_from_iterator<I>(_: Dynamic, _: C, _: I) -> Self::Buffer {
+ unimplemented!()
+ }
+}
+impl DimName for DimU1 {
+ type Value = U1;
+ fn name() -> Self {
+ unimplemented!()
+ }
+}
+impl DimName for DimU2 {
+ type Value = U2;
+ fn name() -> Self {
+ unimplemented!()
+ }
+}
+impl<N, D> From<VectorN<N, D>> for Point<N, D>
+where
+ DefaultAllocator: Allocator<N, D>,
+{
+ fn from(_: VectorN<N, D>) -> Self {
+ unimplemented!()
+ }
+}
+impl<GeometryDim, NodalDim> FiniteElementAllocator<GeometryDim, NodalDim> for DefaultAllocator where
+ DefaultAllocator: Allocator<f64, GeometryDim> + Allocator<f64, NodalDim>
+{
+}
+impl ReferenceFiniteElement for Edge2dElement {
+ type NodalDim = DimU1;
+}
+impl FiniteElement<DimU2> for Edge2dElement {
+ fn map_reference_coords(&self) -> Vector2<f64> {
+ unimplemented!()
+ }
+}
+
+type Owned<N, R, C> = <DefaultAllocator as Allocator<N, R, C>>::Buffer;
+type MatrixMN<N, R, C> = Matrix<N, R, C, Owned<N, R, C>>;
+type VectorN<N, D> = MatrixMN<N, D, DimU1>;
+type Vector2<N> = VectorN<N, DimU2>;
+type Point2<N> = Point<N, DimU2>;
+type U1 = UInt<UTerm, B1>;
+type U2 = UInt<UInt<UTerm, B1>, B0>;
+type Sum<A, B> = <A as Add<B>>::Output;
+type Prod<A, B> = <A as Mul<B>>::Output;
+
+struct GenericArray<T, U: ArrayLength<T>> {
+ _data: U::ArrayType,
+}
+struct GenericArrayImplEven<T, U> {
+ _parent2: U,
+ _marker: T,
+}
+struct GenericArrayImplOdd<T, U> {
+ _parent2: U,
+ _data: T,
+}
+struct B0;
+struct B1;
+struct UTerm;
+struct UInt<U, B> {
+ _marker: PhantomData<(U, B)>,
+}
+struct DefaultAllocator;
+struct Dynamic;
+struct DimU1;
+struct DimU2;
+struct Matrix<N, R, C, S> {
+ _data: S,
+ _phantoms: PhantomData<(N, R, C)>,
+}
+struct ArrayStorage<N, R, C>
+where
+ R: DimName,
+ C: DimName,
+ R::Value: Mul<C::Value>,
+ Prod<R::Value, C::Value>: ArrayLength<N>,
+{
+ _data: GenericArray<N, Prod<R::Value, C::Value>>,
+}
+struct VecStorage<N, R, C> {
+ _data: N,
+ _nrows: R,
+ _ncols: C,
+}
+struct Point<N, D>
+where
+ DefaultAllocator: Allocator<N, D>,
+{
+ _coords: VectorN<N, D>,
+}
+struct Edge2dElement;
+
+trait ArrayLength<T> {
+ type ArrayType;
+}
+trait Allocator<Scalar, R, C = DimU1> {
+ type Buffer;
+ fn allocate_uninitialized(nrows: R, ncols: C) -> Self::Buffer;
+ fn allocate_from_iterator<I>(nrows: R, ncols: C, iter: I) -> Self::Buffer;
+}
+trait DimName {
+ type Value;
+ fn name() -> Self;
+}
+trait FiniteElementAllocator<GeometryDim, NodalDim>:
+ Allocator<f64, GeometryDim> + Allocator<f64, NodalDim>
+{
+}
+trait ReferenceFiniteElement {
+ type NodalDim;
+}
+trait FiniteElement<GeometryDim>: ReferenceFiniteElement
+where
+ DefaultAllocator: FiniteElementAllocator<GeometryDim, Self::NodalDim>,
+{
+ fn map_reference_coords(&self) -> VectorN<f64, GeometryDim>;
+}
+
+fn main() {}
--- /dev/null
+fn main() {
+ format!(r"{}{}{}", named_arg=1); //~ ERROR invalid reference to positional arguments 1 and 2
+}
--- /dev/null
+error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
+ --> $DIR/issue-75307.rs:2:13
+ |
+LL | format!(r"{}{}{}", named_arg=1);
+ | ^^^^^^^^^
+ |
+ = note: positional arguments are zero-based
+
+error: aborting due to previous error
+
--- /dev/null
+// build-pass
+
+// This used to fail MIR validation due to the types on both sides of
+// an assignment not being equal.
+// The failure doesn't occur with a check-only build.
+
+fn iter_slice<'a, T>(xs: &'a [T]) -> impl Iterator<Item = &'a T> {
+ xs.iter()
+}
+
+fn main() {
+ iter_slice::<()> as fn(_) -> _;
+}
--- /dev/null
+// This is not autofixable because we give extra suggestions to end the first expression with `;`.
+fn foo(a: Option<u32>, b: Option<u32>) -> bool {
+ if let Some(x) = a { true } else { false }
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ && //~ ERROR mismatched types
+ if let Some(y) = a { true } else { false }
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt-2.rs:3:26
+ |
+LL | if let Some(x) = a { true } else { false }
+ | ---------------------^^^^------------------ help: consider using a semicolon here
+ | | |
+ | | expected `()`, found `bool`
+ | expected this to be `()`
+
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt-2.rs:3:40
+ |
+LL | if let Some(x) = a { true } else { false }
+ | -----------------------------------^^^^^--- help: consider using a semicolon here
+ | | |
+ | | expected `()`, found `bool`
+ | expected this to be `()`
+
+error[E0308]: mismatched types
+ --> $DIR/expr-as-stmt-2.rs:6:5
+ |
+LL | fn foo(a: Option<u32>, b: Option<u32>) -> bool {
+ | ---- expected `bool` because of return type
+LL | if let Some(x) = a { true } else { false }
+ | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
+...
+LL | / &&
+LL | | if let Some(y) = a { true } else { false }
+ | |______________________________________________^ expected `bool`, found `&&bool`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
//~^ ERROR mismatched types
}
-fn qux(a: Option<u32>, b: Option<u32>) -> bool {
- (if let Some(x) = a { true } else { false })
- && //~ ERROR expected expression
- if let Some(y) = a { true } else { false }
-}
-
fn moo(x: u32) -> bool {
(match x {
_ => 1,
//~^ ERROR mismatched types
}
-fn qux(a: Option<u32>, b: Option<u32>) -> bool {
- if let Some(x) = a { true } else { false }
- && //~ ERROR expected expression
- if let Some(y) = a { true } else { false }
-}
-
fn moo(x: u32) -> bool {
match x {
_ => 1,
| |
| help: parentheses are required to parse this as an expression: `({ 42 })`
-error: expected expression, found `&&`
- --> $DIR/expr-as-stmt.rs:30:5
- |
-LL | if let Some(x) = a { true } else { false }
- | ------------------------------------------ help: parentheses are required to parse this as an expression: `(if let Some(x) = a { true } else { false })`
-LL | &&
- | ^^ expected expression
-
error: expected expression, found `>`
- --> $DIR/expr-as-stmt.rs:37:7
+ --> $DIR/expr-as-stmt.rs:31:7
|
LL | } > 0
| ^ expected expression
| |
| help: parentheses are required to parse this as an expression: `({ 3 })`
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
Some errors have detailed explanations: E0308, E0614.
For more information about an error, try `rustc --explain E0308`.
foo: T,
trait T { //~ ERROR expected identifier, found keyword `trait`
-//~^ ERROR expected `:`, found `T`
fn foo(&self);
}
error: this file contains an unclosed delimiter
- --> $DIR/missing-close-brace-in-struct.rs:14:65
+ --> $DIR/missing-close-brace-in-struct.rs:13:65
|
LL | pub(crate) struct Bar<T> {
| - unclosed delimiter
LL | trait T {
| ^^^^^ expected identifier, found keyword
-error: expected `:`, found `T`
- --> $DIR/missing-close-brace-in-struct.rs:4:7
- |
-LL | trait T {
- | ^ expected `:`
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
struct S {
let foo: (),
//~^ ERROR expected identifier, found keyword `let`
- //~^^ ERROR expected `:`, found `foo`
}
fn main() {}
LL | let foo: (),
| ^^^ expected identifier, found keyword
-error: expected `:`, found `foo`
- --> $DIR/removed-syntax-field-let.rs:2:9
- |
-LL | let foo: (),
- | ^^^ expected `:`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
--> $DIR/trait-object-trait-parens.rs:8:35
|
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
- | ----- ^^^^^^^^^^^^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ----- ^^^^^^^^^^^^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + for<'a> Trait<'a> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:12:49
|
LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
- | ------------------- ^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ------------------- ^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:16:38
|
LL | let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
- | ----------------- ^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ----------------- ^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error: aborting due to 6 previous errors; 3 warnings emitted
bar::<I>()
}
+#[rustc_polymorphize_error]
+fn baz<I, T>(_: I)
+where
+ std::iter::Repeat<I>: Iterator<Item = T>,
+{
+ bar::<I>()
+}
+
+// In addition, check that `I` is considered used in `next::{{closure}}`, because `T` is used and
+// `T` is really just `I::Item`. `E` is used due to the fixed-point marking of predicates.
+
+pub(crate) struct Foo<'a, I, E>(I, &'a E);
+
+impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+where
+ I: Iterator<Item = &'a (T, E)>,
+{
+ type Item = T;
+
+ #[rustc_polymorphize_error]
+ fn next(&mut self) -> Option<Self::Item> {
+ self.find(|_| true)
+ }
+}
+
+// Furthermore, check that `B` is considered used because `C` is used, and that `A` is considered
+// used because `B` is now used.
+
+trait Baz<Z> {}
+
+impl Baz<u16> for u8 {}
+impl Baz<u32> for u16 {}
+
+#[rustc_polymorphize_error]
+fn quux<A, B, C: Default>() -> usize
+where
+ A: Baz<B>,
+ B: Baz<C>,
+{
+ std::mem::size_of::<C>()
+}
+
fn main() {
let x = &[2u32];
foo(x.iter());
+ baz(x.iter());
+
+ let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
+ let _ = a.next();
+
+ let _ = quux::<u8, u16, u32>();
}
--- /dev/null
+// build-pass
+// compile-flags: -Zpolymorphize=on -Zsymbol-mangling-version=v0
+
+pub(crate) struct Foo<'a, I, E>(I, &'a E);
+
+impl<'a, I, T: 'a, E> Iterator for Foo<'a, I, E>
+where
+ I: Iterator<Item = &'a (T, E)>,
+{
+ type Item = T;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.find(|_| true)
+ }
+}
+
+fn main() {
+ let mut a = Foo([(1u32, 1u16)].iter(), &1u16);
+ let mut b = Foo([(1u16, 1u32)].iter(), &1u32);
+ let _ = a.next();
+ let _ = b.next();
+}
error[E0424]: expected value, found module `self`
--> $DIR/issue-2356.rs:65:8
|
-LL | / fn meow() {
-LL | | if self.whiskers > 3 {
- | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-LL | |
-LL | | println!("MEOW");
-LL | | }
-LL | | }
- | |___- this function doesn't have a `self` parameter
+LL | fn meow() {
+ | ---- this function doesn't have a `self` parameter
+LL | if self.whiskers > 3 {
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+ |
+help: add a `self` receiver parameter to make the associated `fn` a method
+ |
+LL | fn meow(&self) {
+ | ^^^^^
error[E0425]: cannot find function `grow_older` in this scope
--> $DIR/issue-2356.rs:72:5
error[E0424]: expected value, found module `self`
--> $DIR/issue-2356.rs:92:5
|
-LL | / fn main() {
-LL | | self += 1;
- | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-LL | |
-LL | | }
- | |_- this function doesn't have a `self` parameter
+LL | fn main() {
+ | ---- this function can't have a `self` parameter
+LL | self += 1;
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
error: aborting due to 17 previous errors
//~| ERROR missing lifetime specifier
//~| ERROR missing lifetime specifier
//~| ERROR missing lifetime specifier
- //~| ERROR the lifetime bound for this object type cannot be deduced from context
- //~| ERROR the lifetime bound for this object type cannot be deduced from context
}
thread_local! {
static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
//~| ERROR missing lifetime specifier
//~| ERROR missing lifetime specifier
//~| ERROR missing lifetime specifier
- //~| ERROR the lifetime bound for this object type cannot be deduced from context
- //~| ERROR the lifetime bound for this object type cannot be deduced from context
}
thread_local! {
}
thread_local! {
static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
- //~^ ERROR the lifetime bound for this object type cannot be deduced from context
- //~| ERROR the lifetime bound for this object type cannot be deduced from context
- //~| ERROR wrong number of lifetime arguments: expected 2, found 1
+ //~^ ERROR wrong number of lifetime arguments: expected 2, found 1
//~| ERROR wrong number of lifetime arguments: expected 2, found 1
//~| ERROR wrong number of lifetime arguments: expected 2, found 1
//~| ERROR wrong number of lifetime arguments: expected 2, found 1
| ^^^^^^^^^^^^^^^^^^^^^
error[E0106]: missing lifetime specifiers
- --> $DIR/missing-lifetime-specifier.rs:32:48
+ --> $DIR/missing-lifetime-specifier.rs:30:48
|
LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
| ^ expected 2 lifetime parameters
| ^^^^^^^^^^^^^^^^^
error[E0106]: missing lifetime specifiers
- --> $DIR/missing-lifetime-specifier.rs:32:48
+ --> $DIR/missing-lifetime-specifier.rs:30:48
|
LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new());
| ^ expected 2 lifetime parameters
| ^^^^^^^^^^^^^^^^^
error[E0106]: missing lifetime specifier
- --> $DIR/missing-lifetime-specifier.rs:37:44
+ --> $DIR/missing-lifetime-specifier.rs:35:44
|
LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
| ^ expected named lifetime parameter
| ^^^^^^^^
error[E0106]: missing lifetime specifiers
- --> $DIR/missing-lifetime-specifier.rs:37:49
+ --> $DIR/missing-lifetime-specifier.rs:35:49
|
LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
| ^ expected 2 lifetime parameters
| ^^^^^^^^^^^^^^^^^
error[E0106]: missing lifetime specifier
- --> $DIR/missing-lifetime-specifier.rs:37:44
+ --> $DIR/missing-lifetime-specifier.rs:35:44
|
LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
| ^ expected named lifetime parameter
| ^^^^^^^^
error[E0106]: missing lifetime specifiers
- --> $DIR/missing-lifetime-specifier.rs:37:49
+ --> $DIR/missing-lifetime-specifier.rs:35:49
|
LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
| ^ expected 2 lifetime parameters
| ^^^^^^^^^^^^^^^^^
error[E0106]: missing lifetime specifier
- --> $DIR/missing-lifetime-specifier.rs:54:44
+ --> $DIR/missing-lifetime-specifier.rs:50:44
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^ expected named lifetime parameter
| ^^^^^^^^
error[E0106]: missing lifetime specifier
- --> $DIR/missing-lifetime-specifier.rs:54:44
+ --> $DIR/missing-lifetime-specifier.rs:50:44
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^ expected named lifetime parameter
LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/missing-lifetime-specifier.rs:23:45
- |
-LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
- | ^^^
-
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/missing-lifetime-specifier.rs:23:45
- |
-LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new());
- | ^^^
-
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/missing-lifetime-specifier.rs:37:45
- |
-LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
- | ^^^^^^^^
-
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/missing-lifetime-specifier.rs:37:45
- |
-LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new());
- | ^^^^^^^^
-
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:47:44
+ --> $DIR/missing-lifetime-specifier.rs:43:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:47:44
+ --> $DIR/missing-lifetime-specifier.rs:43:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:47:44
+ --> $DIR/missing-lifetime-specifier.rs:43:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:47:44
+ --> $DIR/missing-lifetime-specifier.rs:43:44
|
LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:54:45
+ --> $DIR/missing-lifetime-specifier.rs:50:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:54:45
+ --> $DIR/missing-lifetime-specifier.rs:50:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/missing-lifetime-specifier.rs:54:45
- |
-LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
- | ^^^^^^^^^^^^^^^^^
-
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:54:45
+ --> $DIR/missing-lifetime-specifier.rs:50:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
-error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
- --> $DIR/missing-lifetime-specifier.rs:54:45
- |
-LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
- | ^^^^^^^^^^^^^^^^^
-
error[E0107]: wrong number of lifetime arguments: expected 2, found 1
- --> $DIR/missing-lifetime-specifier.rs:54:45
+ --> $DIR/missing-lifetime-specifier.rs:50:45
|
LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new());
| ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments
-error: aborting due to 28 previous errors
+error: aborting due to 22 previous errors
-Some errors have detailed explanations: E0106, E0107, E0228.
+Some errors have detailed explanations: E0106, E0107.
For more information about an error, try `rustc --explain E0106`.
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:19:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:22:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:25:23
| --- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:28:22
| -- referenced here (first use)
...
LL | type _T04 = dyn _1 + Obj;
- | -- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:37:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:40:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:43:23
| --- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:46:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:49:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:52:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:55:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:58:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:65:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:68:23
| --- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:71:22
| --- first non-auto trait
...
LL | type _T22 = dyn _5 + Obj;
- | -- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:74:36
| --- first non-auto trait
...
LL | type _T23 = dyn _5 + Send + Sync + Obj;
- | -- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:81:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:84:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:87:24
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:95:22
| -- referenced here (first use)
LL |
LL | type _T40 = dyn _8 + Obj;
- | -- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:98:23
| --- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:101:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:104:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:107:36
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:117:22
| -- ^^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-duplicates.rs:123:23
| --- ^^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error: aborting due to 27 previous errors
| ---- first non-auto trait
...
LL | type _T00 = dyn _0 + ObjB;
- | -- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:19:24
| ---- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:22:24
| ---- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:25:22
| -- referenced here (first use)
...
LL | type _T03 = dyn _1 + ObjB;
- | -- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:34:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:37:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:40:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:43:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:50:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:53:22
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:56:22
| ---- first non-auto trait
...
LL | type _T22 = dyn _5 + ObjA;
- | -- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:59:24
| ---- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:62:29
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:65:29
| -- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:68:36
| ---- first non-auto trait
...
LL | type _T26 = dyn Sync + Send + _5 + ObjA;
- | -- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | -- ^^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:71:38
| ---- ^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:80:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:83:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:86:24
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:89:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:92:17
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:95:24
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:103:23
| -- referenced here (first use)
LL |
LL | type _T40 = dyn _10 + ObjA;
- | --- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | --- ^^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:106:24
| ---- ^^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:109:23
| --- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:112:37
| -- referenced here (first use)
...
LL | type _T43 = dyn Send + _10 + Sync + ObjA;
- | --- ^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | --- ^^^^ additional non-auto trait
+ | |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:115:24
| ---- ^^^ trait alias used in trait object type (additional use)
| |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-alias-no-extra-traits.rs:118:37
| --- ^^ trait alias used in trait object type (additional use)
| |
| trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error: aborting due to 28 previous errors
--> $DIR/wf-trait-object-no-duplicates.rs:8:21
|
LL | type _0 = dyn Obj + Obj;
- | --- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | --- ^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/wf-trait-object-no-duplicates.rs:13:28
|
LL | type _1 = dyn Send + Obj + Obj;
- | --- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | --- ^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/wf-trait-object-no-duplicates.rs:16:28
|
LL | type _2 = dyn Obj + Send + Obj;
- | --- ^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | --- ^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + Obj {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/wf-trait-object-no-duplicates.rs:26:34
|
LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>;
- | ---------------- ^^^^^^^^^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/wf-trait-object-no-duplicates.rs:30:42
|
LL | type _5 = dyn ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)>;
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^
- | | |
- | | additional non-auto trait
- | | trait alias used in trait object type (additional use)
+ | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait
+ | |
| first non-auto trait
- | trait alias used in trait object type (first use)
+ |
+ = help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}`
+ = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
error: aborting due to 5 previous errors
--- /dev/null
+// compile-flags: -Cllvm-args=-not-a-real-llvm-arg
+// normalize-stderr-test "--help" -> "-help"
+// normalize-stderr-test "\n(\n|.)*" -> ""
+
+// I'm seeing "--help" locally, but "-help" in CI, so I'm normalizing it to just "-help".
+
+// Note that the rustc-supplied "program name", given when invoking LLVM, is used by LLVM to
+// generate user-facing error messages and a usage (--help) messages. If the program name is
+// `rustc`, the usage message in response to `--llvm-args="--help"` starts with:
+// ```
+// USAGE: rustc [options]
+// ```
+// followed by the list of options not to `rustc` but to `llvm`.
+//
+// On the other hand, if the program name is set to `rustc -Cllvm-args="..." with`, the usage
+// message is more clear:
+// ```
+// USAGE: rustc -Cllvm-args="..." with [options]
+// ```
+// This test captures the effect of the current program name setting on LLVM command line
+// error messages.
+fn main() {}
--- /dev/null
+rustc -Cllvm-args="..." with: Unknown command line argument '-not-a-real-llvm-arg'. Try: 'rustc -Cllvm-args="..." with -help'
\ No newline at end of file
let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets);
package("rustc", HOSTS);
package("rustc-dev", HOSTS);
+ package("rustc-docs", HOSTS);
package("cargo", HOSTS);
package("rust-mingw", MINGW);
package("rust-std", TARGETS);
// for users to install the additional component manually, if needed.
if self.rust_release == "nightly" {
self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]);
+ self.extend_profile("complete", &mut manifest.profiles, &["rustc-docs"]);
}
}
.map(|target| Component::from_str("rust-std", target)),
);
extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-dev", target)));
+ extensions.extend(HOSTS.iter().map(|target| Component::from_str("rustc-docs", target)));
extensions.push(Component::from_str("rust-src", "*"));
// If the components/extensions don't actually exist for this
mess,
|diag| {
if let Some(local_def_id) = impl_id.as_local() {
- let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
diag.span_note(
cx.tcx.hir().span(hir_id),
"`PartialEq` implemented here"
mess,
|diag| {
if let Some(local_def_id) = impl_id.as_local() {
- let hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
diag.span_note(
cx.tcx.hir().span(hir_id),
"`PartialOrd` implemented here"
ty: Ty<'tcx>,
) {
fn item_from_def_id<'tcx>(cx: &LateContext<'tcx>, def_id: DefId) -> &'tcx Item<'tcx> {
- let hir_id = cx.tcx.hir().as_local_hir_id(def_id.expect_local());
+ let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
cx.tcx.hir().expect_item(hir_id)
}
if match_path(&trait_ref.path, &paths::SERDE_DESERIALIZE);
if let ty::Adt(def, _) = ty.kind;
if let Some(local_def_id) = def.did.as_local();
- let adt_hir_id = cx.tcx.hir().as_local_hir_id(local_def_id);
+ let adt_hir_id = cx.tcx.hir().local_def_id_to_hir_id(local_def_id);
if !is_allowed(cx, UNSAFE_DERIVE_DESERIALIZE, adt_hir_id);
if cx.tcx.inherent_impls(def.did)
.iter()
cx.tcx.for_each_impl(default_trait_id, |d| {
if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
if let Some(local_def_id) = ty_def.did.as_local() {
- impls.insert(cx.tcx.hir().as_local_hir_id(local_def_id));
+ impls.insert(cx.tcx.hir().local_def_id_to_hir_id(local_def_id));
}
}
});
diff = "0.1.10"
env_logger = { version = "0.7", default-features = false }
getopts = "0.2"
-log = { package = "tracing", version = "0.1" }
+tracing = "0.1"
regex = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
use std::str::FromStr;
use lazy_static::lazy_static;
-use log::*;
use regex::Regex;
+use tracing::*;
#[derive(Clone, Debug, PartialEq)]
pub enum ErrorKind {
use std::io::BufReader;
use std::path::{Path, PathBuf};
-use log::*;
+use tracing::*;
use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode};
use crate::extract_gdb_version;
use crate::common::{CompareMode, Config, Debugger, Mode, PassMode, Pretty, TestPaths};
use crate::util::logv;
use getopts::Options;
-use log::*;
use std::env;
use std::ffi::OsString;
use std::fs;
use std::process::Command;
use std::time::SystemTime;
use test::ColorConfig;
+use tracing::*;
use walkdir::WalkDir;
use self::header::EarlyProps;
use glob::glob;
use lazy_static::lazy_static;
-use log::*;
+use tracing::*;
use crate::extract_gdb_version;
use crate::is_android_gdb_target;
use std::ffi::OsStr;
use std::path::PathBuf;
-use log::*;
+use tracing::*;
#[cfg(test)]
mod tests;
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-fuchsia",
+ "x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
&["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] =
- &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"];
+ &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
-pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] =
- &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] = &[
+ "aarch64-unknown-linux-gnu",
+ "x86_64-apple-darwin",
+ "x86_64-unknown-freebsd",
+ "x86_64-unknown-linux-gnu",
+];
const BIG_ENDIAN: &'static [&'static str] = &[
"armebv7r",
- Needs `I-nominated`?
"""
message_on_remove = "Issue #{number}'s prioritization request has been removed."
-
-[notify-zulip."I-nominated"]
-required_labels = ["T-compiler"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "I-nominated #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* #{number} has been nominated for discussion in `T-compiler` meeting.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-i-nominated-issues)
-- Already discussed?
-- Worth the meeting time?
-- Add agenda entry:
- - Why nominated?
- - Assignee?
- - Issue? PR? What's the status?
- - Summary and important details?
-"""
-message_on_remove = "#{number}'s nomination has been removed."
-
-[notify-zulip."beta-nominated"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "Backport #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* PR #{number} has been requested for beta backport.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
-Prepare agenda entry:
-- Why nominated?
-- Author, assignee?
-- Important details?
-"""
-message_on_remove = "PR #{number}'s beta backport request has been removed."
-
-[notify-zulip."stable-nominated"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "Backport #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* PR #{number} has been requested for stable backport.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-stablebeta-nominations)
-Prepare agenda entry:
-- Why nominated?
-- Author, assignee?
-- Important details?
-"""
-message_on_remove = "PR #{number}'s stable backport request has been removed."
-
-[notify-zulip."S-waiting-on-team"]
-required_labels = ["T-compiler"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "S-waiting-on-team #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* PR #{number} is waiting on `T-compiler`.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-prs-waiting-on-team)
-- Prepare agenda entry:
- - What is it waiting for?
- - Important details?
-- Could be resolved quickly? Tag `I-nominated`.
-"""
-message_on_remove = "PR #{number}'s is no longer waiting on `T-compiler`."
-
-[notify-zulip."P-critical"]
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "P-critical #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* issue #{number} has been assigned `P-critical`.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions)
-- Notify people/groups?
-- Assign if possible?
-- Add to agenda:
- - Assignee?
- - Summary and important details?
-- Other actions to move forward?
-"""
-
-[notify-zulip."P-high"]
-required_labels = ["regression-from-stable-to-[bn]*"] # only nightly and beta regressions
-zulip_stream = 245100 # #t-compiler/wg-prioritization/alerts
-topic = "P-high regression #{number} {title}"
-message_on_add = """\
-@*WG-prioritization/alerts* issue #{number} has been assigned `P-high` and is a regression.
-
-# [Procedure](https://forge.rust-lang.org/compiler/prioritization/procedure.html#summarize-p-critical-and-unassigned-p-high-regressions)
-Is issue assigned? If not:
-- Try to find an assignee?
-- Otherwise add to agenda:
- - Mark as unassigned.
- - Summary and important details?
-"""