Skip to content

Commit

Permalink
MiniSet introduced, a simple SSO set
Browse files Browse the repository at this point in the history
  • Loading branch information
VFLashM committed May 22, 2020
1 parent 9bff6fc commit 59eaf07
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 15 deletions.
11 changes: 9 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ dependencies = [
"nodrop",
]

[[package]]
name = "arrayvec"
version = "0.5.1"
source = "registry+/~https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"

[[package]]
name = "atty"
version = "0.2.11"
Expand Down Expand Up @@ -175,7 +181,7 @@ version = "0.2.18"
source = "registry+/~https://github.com/rust-lang/crates.io-index"
checksum = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
dependencies = [
"arrayvec",
"arrayvec 0.4.7",
"constant_time_eq",
]

Expand Down Expand Up @@ -804,7 +810,7 @@ version = "0.7.2"
source = "registry+/~https://github.com/rust-lang/crates.io-index"
checksum = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
dependencies = [
"arrayvec",
"arrayvec 0.4.7",
"cfg-if",
"crossbeam-utils 0.6.5",
"lazy_static 1.4.0",
Expand Down Expand Up @@ -4082,6 +4088,7 @@ name = "rustc_middle"
version = "0.0.0"
dependencies = [
"arena",
"arrayvec 0.5.1",
"bitflags",
"byteorder",
"chalk-ir",
Expand Down
10 changes: 5 additions & 5 deletions src/librustc_infer/infer/outlives/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::{GenericKind, VerifyBound};
use crate::traits;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::walk::MiniSet;
use rustc_middle::ty::{self, Ty, TyCtxt};

/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
Expand Down Expand Up @@ -33,7 +33,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
/// Returns a "verify bound" that encodes what we know about
/// `generic` and the regions it outlives.
pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
let mut visited = FxHashSet::default();
let mut visited = MiniSet::new();
match generic {
GenericKind::Param(param_ty) => self.param_bound(param_ty),
GenericKind::Projection(projection_ty) => {
Expand All @@ -45,7 +45,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
fn type_bound(
&self,
ty: Ty<'tcx>,
visited: &mut FxHashSet<GenericArg<'tcx>>,
visited: &mut MiniSet<GenericArg<'tcx>>,
) -> VerifyBound<'tcx> {
match ty.kind {
ty::Param(p) => self.param_bound(p),
Expand Down Expand Up @@ -149,7 +149,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
pub fn projection_bound(
&self,
projection_ty: ty::ProjectionTy<'tcx>,
visited: &mut FxHashSet<GenericArg<'tcx>>,
visited: &mut MiniSet<GenericArg<'tcx>>,
) -> VerifyBound<'tcx> {
debug!("projection_bound(projection_ty={:?})", projection_ty);

Expand Down Expand Up @@ -187,7 +187,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
fn recursive_bound(
&self,
parent: GenericArg<'tcx>,
visited: &mut FxHashSet<GenericArg<'tcx>>,
visited: &mut MiniSet<GenericArg<'tcx>>,
) -> VerifyBound<'tcx> {
let mut bounds = parent
.walk_shallow(visited)
Expand Down
1 change: 1 addition & 0 deletions src/librustc_middle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ rustc_span = { path = "../librustc_span" }
byteorder = { version = "1.3" }
chalk-ir = "0.10.0"
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
arrayvec = { version = "0.5.1", default-features = false }
measureme = "0.7.1"
rustc_session = { path = "../librustc_session" }
10 changes: 5 additions & 5 deletions src/librustc_middle/ty/outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use crate::ty::subst::{GenericArg, GenericArgKind};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_data_structures::fx::FxHashSet;
use crate::ty::walk::MiniSet;
use smallvec::SmallVec;

#[derive(Debug)]
Expand Down Expand Up @@ -51,7 +51,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Push onto `out` all the things that must outlive `'a` for the condition
/// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
pub fn push_outlives_components(self, ty0: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
let mut visited = FxHashSet::default();
let mut visited = MiniSet::new();
compute_components(self, ty0, out, &mut visited);
debug!("components({:?}) = {:?}", ty0, out);
}
Expand All @@ -61,7 +61,7 @@ fn compute_components(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
out: &mut SmallVec<[Component<'tcx>; 4]>,
visited: &mut FxHashSet<GenericArg<'tcx>>,
visited: &mut MiniSet<GenericArg<'tcx>>,
) {
// Descend through the types, looking for the various "base"
// components and collecting them into `out`. This is not written
Expand Down Expand Up @@ -142,7 +142,7 @@ fn compute_components(
// OutlivesProjectionComponents. Continue walking
// through and constrain Pi.
let mut subcomponents = smallvec![];
let mut subvisited = FxHashSet::default();
let mut subvisited = MiniSet::new();
compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
out.push(Component::EscapingProjection(subcomponents.into_iter().collect()));
}
Expand Down Expand Up @@ -194,7 +194,7 @@ fn compute_components_recursive(
tcx: TyCtxt<'tcx>,
parent: GenericArg<'tcx>,
out: &mut SmallVec<[Component<'tcx>; 4]>,
visited: &mut FxHashSet<GenericArg<'tcx>>,
visited: &mut MiniSet<GenericArg<'tcx>>,
) {
for child in parent.walk_shallow(visited) {
match child.unpack() {
Expand Down
41 changes: 38 additions & 3 deletions src/librustc_middle/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@ use crate::ty;
use crate::ty::subst::{GenericArg, GenericArgKind};
use rustc_data_structures::fx::FxHashSet;
use smallvec::{self, SmallVec};
use arrayvec::ArrayVec;
use std::hash::Hash;

pub enum MiniSet<T> {
Array(ArrayVec<[T; 64]>),
Set(FxHashSet<T>),
}

impl<T: Eq + Hash + Copy> MiniSet<T> {
pub fn new() -> Self {
MiniSet::Array(ArrayVec::new())
}

pub fn insert(&mut self, elem: T) -> bool {
match self {
MiniSet::Array(array) => {
if array.iter().any(|e| *e == elem) {
false
} else {
if !array.is_full() {
unsafe {
array.push_unchecked(elem);
}
} else {
let mut set: FxHashSet<T> = array.iter().copied().collect();
set.insert(elem);
*self = MiniSet::Set(set);
}
true
}
},
MiniSet::Set(set) => set.insert(elem)
}
}
}

// The TypeWalker's stack is hot enough that it's worth going to some effort to
// avoid heap allocations.
Expand All @@ -13,7 +48,7 @@ type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
pub struct TypeWalker<'tcx> {
stack: TypeWalkerStack<'tcx>,
last_subtree: usize,
visited: FxHashSet<GenericArg<'tcx>>,
visited: MiniSet<GenericArg<'tcx>>,
}

/// An iterator for walking the type tree.
Expand All @@ -26,7 +61,7 @@ pub struct TypeWalker<'tcx> {
/// skips any types that are already there.
impl<'tcx> TypeWalker<'tcx> {
pub fn new(root: GenericArg<'tcx>) -> Self {
Self { stack: smallvec![root], last_subtree: 1, visited: FxHashSet::default() }
Self { stack: smallvec![root], last_subtree: 1, visited: MiniSet::new() }
}

/// Skips the subtree corresponding to the last type
Expand Down Expand Up @@ -87,7 +122,7 @@ impl GenericArg<'tcx> {
/// and skips any types that are already there.
pub fn walk_shallow(
self,
visited: &mut FxHashSet<GenericArg<'tcx>>,
visited: &mut MiniSet<GenericArg<'tcx>>,
) -> impl Iterator<Item = GenericArg<'tcx>> {
let mut stack = SmallVec::new();
push_inner(&mut stack, self);
Expand Down

0 comments on commit 59eaf07

Please sign in to comment.