mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Auto merge of #124831 - nnethercote:rustc_data_structures-cleanups, r=michaelwoerister
`rustc_data_structures` cleanups Some improvements I found while looking through this code. r? `@michaelwoerister`
This commit is contained in:
commit
37dc766378
@ -1,4 +1,3 @@
|
|||||||
use rustc_data_structures::vec_linked_list as vll;
|
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc_middle::mir::{Body, Local, Location};
|
use rustc_middle::mir::{Body, Local, Location};
|
||||||
@ -37,9 +36,12 @@ pub(crate) struct LocalUseMap {
|
|||||||
/// we add for each local variable.
|
/// we add for each local variable.
|
||||||
first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
|
first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
|
||||||
|
|
||||||
appearances: IndexVec<AppearanceIndex, Appearance>,
|
appearances: Appearances,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The `Appearance::next` field effectively embeds a linked list within `Appearances`.
|
||||||
|
type Appearances = IndexVec<AppearanceIndex, Appearance>;
|
||||||
|
|
||||||
struct Appearance {
|
struct Appearance {
|
||||||
point_index: PointIndex,
|
point_index: PointIndex,
|
||||||
next: Option<AppearanceIndex>,
|
next: Option<AppearanceIndex>,
|
||||||
@ -49,14 +51,34 @@ rustc_index::newtype_index! {
|
|||||||
pub struct AppearanceIndex {}
|
pub struct AppearanceIndex {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl vll::LinkElem for Appearance {
|
fn appearances_iter(
|
||||||
type LinkIndex = AppearanceIndex;
|
first: Option<AppearanceIndex>,
|
||||||
|
appearances: &Appearances,
|
||||||
|
) -> impl Iterator<Item = AppearanceIndex> + '_ {
|
||||||
|
AppearancesIter { appearances, current: first }
|
||||||
|
}
|
||||||
|
|
||||||
fn next(elem: &Self) -> Option<AppearanceIndex> {
|
// Iterates over `Appearances` by following `next` fields.
|
||||||
elem.next
|
struct AppearancesIter<'a> {
|
||||||
|
appearances: &'a Appearances,
|
||||||
|
current: Option<AppearanceIndex>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for AppearancesIter<'a> {
|
||||||
|
type Item = AppearanceIndex;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<AppearanceIndex> {
|
||||||
|
if let Some(c) = self.current {
|
||||||
|
self.current = self.appearances[c].next;
|
||||||
|
Some(c)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
impl LocalUseMap {
|
impl LocalUseMap {
|
||||||
pub(crate) fn build(
|
pub(crate) fn build(
|
||||||
live_locals: &[Local],
|
live_locals: &[Local],
|
||||||
@ -86,17 +108,17 @@ impl LocalUseMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
pub(crate) fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
||||||
vll::iter(self.first_def_at[local], &self.appearances)
|
appearances_iter(self.first_def_at[local], &self.appearances)
|
||||||
.map(move |aa| self.appearances[aa].point_index)
|
.map(move |aa| self.appearances[aa].point_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
pub(crate) fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
||||||
vll::iter(self.first_use_at[local], &self.appearances)
|
appearances_iter(self.first_use_at[local], &self.appearances)
|
||||||
.map(move |aa| self.appearances[aa].point_index)
|
.map(move |aa| self.appearances[aa].point_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
pub(crate) fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
|
||||||
vll::iter(self.first_drop_at[local], &self.appearances)
|
appearances_iter(self.first_drop_at[local], &self.appearances)
|
||||||
.map(move |aa| self.appearances[aa].point_index)
|
.map(move |aa| self.appearances[aa].point_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +168,7 @@ impl LocalUseMapBuild<'_> {
|
|||||||
fn insert(
|
fn insert(
|
||||||
elements: &DenseLocationMap,
|
elements: &DenseLocationMap,
|
||||||
first_appearance: &mut Option<AppearanceIndex>,
|
first_appearance: &mut Option<AppearanceIndex>,
|
||||||
appearances: &mut IndexVec<AppearanceIndex, Appearance>,
|
appearances: &mut Appearances,
|
||||||
location: Location,
|
location: Location,
|
||||||
) {
|
) {
|
||||||
let point_index = elements.point_from_location(location);
|
let point_index = elements.point_from_location(location);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::stable_hasher::impl_stable_traits_for_trivial_type;
|
||||||
use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult};
|
use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult};
|
||||||
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
@ -2,6 +2,7 @@ use std::fs::{File, OpenOptions};
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::os::windows::prelude::*;
|
use std::os::windows::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
use windows::{
|
use windows::{
|
||||||
Win32::Foundation::{ERROR_INVALID_FUNCTION, HANDLE},
|
Win32::Foundation::{ERROR_INVALID_FUNCTION, HANDLE},
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::graph::implementation::*;
|
use crate::graph::implementation::*;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
type TestGraph = Graph<&'static str, &'static str>;
|
type TestGraph = Graph<&'static str, &'static str>;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ use crate::graph::vec_graph::VecGraph;
|
|||||||
use crate::graph::{DirectedGraph, NumEdges, Successors};
|
use crate::graph::{DirectedGraph, NumEdges, Successors};
|
||||||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -42,12 +42,52 @@
|
|||||||
#![feature(unwrap_infallible)]
|
#![feature(unwrap_infallible)]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
|
||||||
#[macro_use]
|
pub use atomic_ref::AtomicRef;
|
||||||
extern crate tracing;
|
pub use ena::snapshot_vec;
|
||||||
|
pub use ena::undo_log;
|
||||||
|
pub use ena::unify;
|
||||||
|
pub use rustc_index::static_assert_size;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub use rustc_index::static_assert_size;
|
pub mod aligned;
|
||||||
|
pub mod base_n;
|
||||||
|
pub mod binary_search_util;
|
||||||
|
pub mod captures;
|
||||||
|
pub mod fingerprint;
|
||||||
|
pub mod flat_map_in_place;
|
||||||
|
pub mod flock;
|
||||||
|
pub mod frozen;
|
||||||
|
pub mod fx;
|
||||||
|
pub mod graph;
|
||||||
|
pub mod intern;
|
||||||
|
pub mod jobserver;
|
||||||
|
pub mod marker;
|
||||||
|
pub mod memmap;
|
||||||
|
pub mod obligation_forest;
|
||||||
|
pub mod owned_slice;
|
||||||
|
pub mod packed;
|
||||||
|
pub mod profiling;
|
||||||
|
pub mod sharded;
|
||||||
|
pub mod sip128;
|
||||||
|
pub mod small_c_str;
|
||||||
|
pub mod snapshot_map;
|
||||||
|
pub mod sorted_map;
|
||||||
|
pub mod sso;
|
||||||
|
pub mod stable_hasher;
|
||||||
|
pub mod stack;
|
||||||
|
pub mod steal;
|
||||||
|
pub mod svh;
|
||||||
|
pub mod sync;
|
||||||
|
pub mod tagged_ptr;
|
||||||
|
pub mod temp_dir;
|
||||||
|
pub mod transitive_relation;
|
||||||
|
pub mod unhash;
|
||||||
|
pub mod unord;
|
||||||
|
pub mod work_queue;
|
||||||
|
|
||||||
|
mod atomic_ref;
|
||||||
|
mod hashes;
|
||||||
|
|
||||||
/// This calls the passed function while ensuring it won't be inlined into the caller.
|
/// This calls the passed function while ensuring it won't be inlined into the caller.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
@ -56,53 +96,6 @@ pub fn outline<F: FnOnce() -> R, R>(f: F) -> R {
|
|||||||
f()
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod base_n;
|
|
||||||
pub mod binary_search_util;
|
|
||||||
pub mod captures;
|
|
||||||
pub mod flat_map_in_place;
|
|
||||||
pub mod flock;
|
|
||||||
pub mod fx;
|
|
||||||
pub mod graph;
|
|
||||||
pub mod intern;
|
|
||||||
pub mod jobserver;
|
|
||||||
pub mod macros;
|
|
||||||
pub mod obligation_forest;
|
|
||||||
pub mod sip128;
|
|
||||||
pub mod small_c_str;
|
|
||||||
pub mod snapshot_map;
|
|
||||||
pub mod svh;
|
|
||||||
pub use ena::snapshot_vec;
|
|
||||||
pub mod memmap;
|
|
||||||
pub mod sorted_map;
|
|
||||||
#[macro_use]
|
|
||||||
pub mod stable_hasher;
|
|
||||||
mod atomic_ref;
|
|
||||||
pub mod fingerprint;
|
|
||||||
pub mod marker;
|
|
||||||
pub mod profiling;
|
|
||||||
pub mod sharded;
|
|
||||||
pub mod stack;
|
|
||||||
pub mod sync;
|
|
||||||
pub mod tiny_list;
|
|
||||||
pub mod transitive_relation;
|
|
||||||
pub mod vec_linked_list;
|
|
||||||
pub mod work_queue;
|
|
||||||
pub use atomic_ref::AtomicRef;
|
|
||||||
pub mod aligned;
|
|
||||||
pub mod frozen;
|
|
||||||
mod hashes;
|
|
||||||
pub mod owned_slice;
|
|
||||||
pub mod packed;
|
|
||||||
pub mod sso;
|
|
||||||
pub mod steal;
|
|
||||||
pub mod tagged_ptr;
|
|
||||||
pub mod temp_dir;
|
|
||||||
pub mod unhash;
|
|
||||||
pub mod unord;
|
|
||||||
|
|
||||||
pub use ena::undo_log;
|
|
||||||
pub use ena::unify;
|
|
||||||
|
|
||||||
/// Returns a structure that calls `f` when dropped.
|
/// Returns a structure that calls `f` when dropped.
|
||||||
pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
|
pub fn defer<F: FnOnce()>(f: F) -> OnDrop<F> {
|
||||||
OnDrop(Some(f))
|
OnDrop(Some(f))
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
#[macro_export]
|
|
||||||
macro_rules! enum_from_u32 {
|
|
||||||
($(#[$attr:meta])* pub enum $name:ident {
|
|
||||||
$($(#[$var_attr:meta])* $variant:ident = $e:expr,)*
|
|
||||||
}) => {
|
|
||||||
$(#[$attr])*
|
|
||||||
pub enum $name {
|
|
||||||
$($(#[$var_attr])* $variant = $e),*
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $name {
|
|
||||||
pub fn from_u32(u: u32) -> Option<$name> {
|
|
||||||
$(if u == $name::$variant as u32 {
|
|
||||||
return Some($name::$variant)
|
|
||||||
})*
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($(#[$attr:meta])* pub enum $name:ident {
|
|
||||||
$($(#[$var_attr:meta])* $variant:ident,)*
|
|
||||||
}) => {
|
|
||||||
$(#[$attr])*
|
|
||||||
pub enum $name {
|
|
||||||
$($(#[$var_attr])* $variant,)*
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $name {
|
|
||||||
pub fn from_u32(u: u32) -> Option<$name> {
|
|
||||||
$(if u == $name::$variant as u32 {
|
|
||||||
return Some($name::$variant)
|
|
||||||
})*
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -70,12 +70,12 @@
|
|||||||
//! aren't needed anymore.
|
//! aren't needed anymore.
|
||||||
|
|
||||||
use crate::fx::{FxHashMap, FxHashSet};
|
use crate::fx::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
mod graphviz;
|
mod graphviz;
|
||||||
|
|
||||||
|
@ -3,8 +3,10 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[repr(packed(8))]
|
/// A packed 128-bit integer. Useful for reducing the size of structures in
|
||||||
|
/// some cases.
|
||||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(packed(8))]
|
||||||
pub struct Pu128(pub u128);
|
pub struct Pu128(pub u128);
|
||||||
|
|
||||||
impl Pu128 {
|
impl Pu128 {
|
||||||
|
@ -99,6 +99,7 @@ pub use measureme::EventId;
|
|||||||
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
|
use measureme::{EventIdBuilder, Profiler, SerializableString, StringId};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use tracing::warn;
|
||||||
|
|
||||||
bitflags::bitflags! {
|
bitflags::bitflags! {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -296,6 +296,8 @@ macro_rules! impl_stable_traits_for_trivial_type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) use impl_stable_traits_for_trivial_type;
|
||||||
|
|
||||||
impl_stable_traits_for_trivial_type!(i8);
|
impl_stable_traits_for_trivial_type!(i8);
|
||||||
impl_stable_traits_for_trivial_type!(i16);
|
impl_stable_traits_for_trivial_type!(i16);
|
||||||
impl_stable_traits_for_trivial_type!(i32);
|
impl_stable_traits_for_trivial_type!(i32);
|
||||||
|
@ -1,80 +0,0 @@
|
|||||||
//! A singly-linked list.
|
|
||||||
//!
|
|
||||||
//! Using this data structure only makes sense under very specific
|
|
||||||
//! circumstances:
|
|
||||||
//!
|
|
||||||
//! - If you have a list that rarely stores more than one element, then this
|
|
||||||
//! data-structure can store the element without allocating and only uses as
|
|
||||||
//! much space as an `Option<(T, usize)>`. If T can double as the `Option`
|
|
||||||
//! discriminant, it will even only be as large as `T, usize`.
|
|
||||||
//!
|
|
||||||
//! If you expect to store more than 1 element in the common case, steer clear
|
|
||||||
//! and use a `Vec<T>`, `Box<[T]>`, or a `SmallVec<T>`.
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct TinyList<T> {
|
|
||||||
head: Option<Element<T>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> TinyList<T> {
|
|
||||||
#[inline]
|
|
||||||
pub fn new() -> TinyList<T> {
|
|
||||||
TinyList { head: None }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn new_single(data: T) -> TinyList<T> {
|
|
||||||
TinyList { head: Some(Element { data, next: None }) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn insert(&mut self, data: T) {
|
|
||||||
self.head = Some(Element { data, next: self.head.take().map(Box::new) });
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn remove(&mut self, data: &T) -> bool {
|
|
||||||
self.head = match &mut self.head {
|
|
||||||
Some(head) if head.data == *data => head.next.take().map(|x| *x),
|
|
||||||
Some(head) => return head.remove_next(data),
|
|
||||||
None => return false,
|
|
||||||
};
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn contains(&self, data: &T) -> bool {
|
|
||||||
let mut elem = self.head.as_ref();
|
|
||||||
while let Some(e) = elem {
|
|
||||||
if &e.data == data {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
elem = e.next.as_deref();
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Element<T> {
|
|
||||||
data: T,
|
|
||||||
next: Option<Box<Element<T>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq> Element<T> {
|
|
||||||
fn remove_next(mut self: &mut Self, data: &T) -> bool {
|
|
||||||
loop {
|
|
||||||
match self.next {
|
|
||||||
Some(ref mut next) if next.data == *data => {
|
|
||||||
self.next = next.next.take();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Some(ref mut next) => self = next,
|
|
||||||
None => return false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
use super::*;
|
|
||||||
|
|
||||||
extern crate test;
|
|
||||||
use test::{black_box, Bencher};
|
|
||||||
|
|
||||||
impl<T> TinyList<T> {
|
|
||||||
fn len(&self) -> usize {
|
|
||||||
let (mut elem, mut count) = (self.head.as_ref(), 0);
|
|
||||||
while let Some(e) = elem {
|
|
||||||
count += 1;
|
|
||||||
elem = e.next.as_deref();
|
|
||||||
}
|
|
||||||
count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_contains_and_insert() {
|
|
||||||
fn do_insert(i: u32) -> bool {
|
|
||||||
i % 2 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut list = TinyList::new();
|
|
||||||
|
|
||||||
for i in 0..10 {
|
|
||||||
for j in 0..i {
|
|
||||||
if do_insert(j) {
|
|
||||||
assert!(list.contains(&j));
|
|
||||||
} else {
|
|
||||||
assert!(!list.contains(&j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(!list.contains(&i));
|
|
||||||
|
|
||||||
if do_insert(i) {
|
|
||||||
list.insert(i);
|
|
||||||
assert!(list.contains(&i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_first() {
|
|
||||||
let mut list = TinyList::new();
|
|
||||||
list.insert(1);
|
|
||||||
list.insert(2);
|
|
||||||
list.insert(3);
|
|
||||||
list.insert(4);
|
|
||||||
assert_eq!(list.len(), 4);
|
|
||||||
|
|
||||||
assert!(list.remove(&4));
|
|
||||||
assert!(!list.contains(&4));
|
|
||||||
|
|
||||||
assert_eq!(list.len(), 3);
|
|
||||||
assert!(list.contains(&1));
|
|
||||||
assert!(list.contains(&2));
|
|
||||||
assert!(list.contains(&3));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_last() {
|
|
||||||
let mut list = TinyList::new();
|
|
||||||
list.insert(1);
|
|
||||||
list.insert(2);
|
|
||||||
list.insert(3);
|
|
||||||
list.insert(4);
|
|
||||||
assert_eq!(list.len(), 4);
|
|
||||||
|
|
||||||
assert!(list.remove(&1));
|
|
||||||
assert!(!list.contains(&1));
|
|
||||||
|
|
||||||
assert_eq!(list.len(), 3);
|
|
||||||
assert!(list.contains(&2));
|
|
||||||
assert!(list.contains(&3));
|
|
||||||
assert!(list.contains(&4));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_middle() {
|
|
||||||
let mut list = TinyList::new();
|
|
||||||
list.insert(1);
|
|
||||||
list.insert(2);
|
|
||||||
list.insert(3);
|
|
||||||
list.insert(4);
|
|
||||||
assert_eq!(list.len(), 4);
|
|
||||||
|
|
||||||
assert!(list.remove(&2));
|
|
||||||
assert!(!list.contains(&2));
|
|
||||||
|
|
||||||
assert_eq!(list.len(), 3);
|
|
||||||
assert!(list.contains(&1));
|
|
||||||
assert!(list.contains(&3));
|
|
||||||
assert!(list.contains(&4));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_single() {
|
|
||||||
let mut list = TinyList::new();
|
|
||||||
list.insert(1);
|
|
||||||
assert_eq!(list.len(), 1);
|
|
||||||
|
|
||||||
assert!(list.remove(&1));
|
|
||||||
assert!(!list.contains(&1));
|
|
||||||
|
|
||||||
assert_eq!(list.len(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_insert_empty(b: &mut Bencher) {
|
|
||||||
b.iter(|| {
|
|
||||||
let mut list = black_box(TinyList::new());
|
|
||||||
list.insert(1);
|
|
||||||
list
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_insert_one(b: &mut Bencher) {
|
|
||||||
b.iter(|| {
|
|
||||||
let mut list = black_box(TinyList::new_single(0));
|
|
||||||
list.insert(1);
|
|
||||||
list
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_contains_empty(b: &mut Bencher) {
|
|
||||||
b.iter(|| black_box(TinyList::new()).contains(&1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_contains_unknown(b: &mut Bencher) {
|
|
||||||
b.iter(|| black_box(TinyList::new_single(0)).contains(&1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_contains_one(b: &mut Bencher) {
|
|
||||||
b.iter(|| black_box(TinyList::new_single(1)).contains(&1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_remove_empty(b: &mut Bencher) {
|
|
||||||
b.iter(|| black_box(TinyList::new()).remove(&1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_remove_unknown(b: &mut Bencher) {
|
|
||||||
b.iter(|| black_box(TinyList::new_single(0)).remove(&1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[bench]
|
|
||||||
fn bench_remove_one(b: &mut Bencher) {
|
|
||||||
b.iter(|| black_box(TinyList::new_single(1)).remove(&1));
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
use rustc_index::{Idx, IndexVec};
|
|
||||||
|
|
||||||
pub fn iter<Ls>(
|
|
||||||
first: Option<Ls::LinkIndex>,
|
|
||||||
links: &Ls,
|
|
||||||
) -> impl Iterator<Item = Ls::LinkIndex> + '_
|
|
||||||
where
|
|
||||||
Ls: Links,
|
|
||||||
{
|
|
||||||
VecLinkedListIterator { links, current: first }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VecLinkedListIterator<Ls>
|
|
||||||
where
|
|
||||||
Ls: Links,
|
|
||||||
{
|
|
||||||
links: Ls,
|
|
||||||
current: Option<Ls::LinkIndex>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Ls> Iterator for VecLinkedListIterator<Ls>
|
|
||||||
where
|
|
||||||
Ls: Links,
|
|
||||||
{
|
|
||||||
type Item = Ls::LinkIndex;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Ls::LinkIndex> {
|
|
||||||
if let Some(c) = self.current {
|
|
||||||
self.current = <Ls as Links>::next(&self.links, c);
|
|
||||||
Some(c)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Links {
|
|
||||||
type LinkIndex: Copy;
|
|
||||||
|
|
||||||
fn next(links: &Self, index: Self::LinkIndex) -> Option<Self::LinkIndex>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Ls> Links for &Ls
|
|
||||||
where
|
|
||||||
Ls: Links,
|
|
||||||
{
|
|
||||||
type LinkIndex = Ls::LinkIndex;
|
|
||||||
|
|
||||||
fn next(links: &Self, index: Ls::LinkIndex) -> Option<Ls::LinkIndex> {
|
|
||||||
<Ls as Links>::next(links, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait LinkElem {
|
|
||||||
type LinkIndex: Copy;
|
|
||||||
|
|
||||||
fn next(elem: &Self) -> Option<Self::LinkIndex>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<L, E> Links for IndexVec<L, E>
|
|
||||||
where
|
|
||||||
E: LinkElem<LinkIndex = L>,
|
|
||||||
L: Idx,
|
|
||||||
{
|
|
||||||
type LinkIndex = L;
|
|
||||||
|
|
||||||
fn next(links: &Self, index: L) -> Option<L> {
|
|
||||||
<E as LinkElem>::next(&links[index])
|
|
||||||
}
|
|
||||||
}
|
|
@ -55,21 +55,27 @@ macro_rules! language_item_table {
|
|||||||
(
|
(
|
||||||
$( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
|
$( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
|
||||||
) => {
|
) => {
|
||||||
|
|
||||||
rustc_data_structures::enum_from_u32! {
|
|
||||||
/// A representation of all the valid lang items in Rust.
|
/// A representation of all the valid lang items in Rust.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||||
pub enum LangItem {
|
pub enum LangItem {
|
||||||
$(
|
$(
|
||||||
#[doc = concat!("The `", stringify!($name), "` lang item.")]
|
#[doc = concat!("The `", stringify!($name), "` lang item.")]
|
||||||
///
|
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
$variant,
|
$variant,
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl LangItem {
|
impl LangItem {
|
||||||
|
fn from_u32(u: u32) -> Option<LangItem> {
|
||||||
|
// This implementation is clumsy, but makes no assumptions
|
||||||
|
// about how discriminant tags are allocated within the
|
||||||
|
// range `0 .. std::mem::variant_count::<LangItem>()`.
|
||||||
|
$(if u == LangItem::$variant as u32 {
|
||||||
|
return Some(LangItem::$variant)
|
||||||
|
})*
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the `name` symbol in `#[lang = "$name"]`.
|
/// Returns the `name` symbol in `#[lang = "$name"]`.
|
||||||
/// For example, [`LangItem::PartialEq`]`.name()`
|
/// For example, [`LangItem::PartialEq`]`.name()`
|
||||||
/// would result in [`sym::eq`] since it is `#[lang = "eq"]`.
|
/// would result in [`sym::eq`] since it is `#[lang = "eq"]`.
|
||||||
@ -147,7 +153,7 @@ language_item_table! {
|
|||||||
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
|
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
|
||||||
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
|
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||||
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
|
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
|
||||||
/// The associated item of the [`DiscriminantKind`] trait.
|
/// The associated item of the `DiscriminantKind` trait.
|
||||||
Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
|
Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
|
||||||
|
|
||||||
PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
|
PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
|
||||||
|
@ -125,10 +125,11 @@ use std::io::{Read, Write};
|
|||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
use std::sync::atomic::{AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
|
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
use rustc_ast::LitKind;
|
use rustc_ast::LitKind;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::{HashMapExt, Lock};
|
use rustc_data_structures::sync::{HashMapExt, Lock};
|
||||||
use rustc_data_structures::tiny_list::TinyList;
|
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||||
@ -266,8 +267,8 @@ type DecodingSessionId = NonZero<u32>;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum State {
|
enum State {
|
||||||
Empty,
|
Empty,
|
||||||
InProgressNonAlloc(TinyList<DecodingSessionId>),
|
InProgressNonAlloc(SmallVec<[DecodingSessionId; 1]>),
|
||||||
InProgress(TinyList<DecodingSessionId>, AllocId),
|
InProgress(SmallVec<[DecodingSessionId; 1]>, AllocId),
|
||||||
Done(AllocId),
|
Done(AllocId),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,8 +338,7 @@ impl<'s> AllocDecodingSession<'s> {
|
|||||||
// If this is an allocation, we need to reserve an
|
// If this is an allocation, we need to reserve an
|
||||||
// `AllocId` so we can decode cyclic graphs.
|
// `AllocId` so we can decode cyclic graphs.
|
||||||
let alloc_id = decoder.interner().reserve_alloc_id();
|
let alloc_id = decoder.interner().reserve_alloc_id();
|
||||||
*entry =
|
*entry = State::InProgress(smallvec![self.session_id], alloc_id);
|
||||||
State::InProgress(TinyList::new_single(self.session_id), alloc_id);
|
|
||||||
Some(alloc_id)
|
Some(alloc_id)
|
||||||
}
|
}
|
||||||
AllocDiscriminant::Fn
|
AllocDiscriminant::Fn
|
||||||
@ -346,8 +346,7 @@ impl<'s> AllocDecodingSession<'s> {
|
|||||||
| AllocDiscriminant::VTable => {
|
| AllocDiscriminant::VTable => {
|
||||||
// Fns and statics cannot be cyclic, and their `AllocId`
|
// Fns and statics cannot be cyclic, and their `AllocId`
|
||||||
// is determined later by interning.
|
// is determined later by interning.
|
||||||
*entry =
|
*entry = State::InProgressNonAlloc(smallvec![self.session_id]);
|
||||||
State::InProgressNonAlloc(TinyList::new_single(self.session_id));
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,7 +356,7 @@ impl<'s> AllocDecodingSession<'s> {
|
|||||||
bug!("this should be unreachable");
|
bug!("this should be unreachable");
|
||||||
} else {
|
} else {
|
||||||
// Start decoding concurrently.
|
// Start decoding concurrently.
|
||||||
sessions.insert(self.session_id);
|
sessions.push(self.session_id);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -367,7 +366,7 @@ impl<'s> AllocDecodingSession<'s> {
|
|||||||
return alloc_id;
|
return alloc_id;
|
||||||
} else {
|
} else {
|
||||||
// Start decoding concurrently.
|
// Start decoding concurrently.
|
||||||
sessions.insert(self.session_id);
|
sessions.push(self.session_id);
|
||||||
Some(alloc_id)
|
Some(alloc_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user