Skip to content

Commit

Permalink
Remove ordering traits from chalk_ir::interner::DefId
Browse files Browse the repository at this point in the history
Use `indexmap` to obviate need for ordering `DefId`s.

In specialization forest, use a map of ImplIds to node indices
to avoid duplicate nodes.
  • Loading branch information
pierwill committed Dec 23, 2021
1 parent 1571806 commit f6f1d1b
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 64 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions chalk-integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ chalk-solve = { version = "0.76.0-dev.0", path = "../chalk-solve" }
chalk-recursive = { version = "0.76.0-dev.0", path = "../chalk-recursive" }
chalk-engine = { version = "0.76.0-dev.0", path = "../chalk-engine" }
chalk-parse = { version = "0.76.0-dev.0", path = "../chalk-parse" }
indexmap = "1.7.0"
6 changes: 3 additions & 3 deletions chalk-ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ use std::sync::Arc;
/// (e.g., `SourceI` and `TargetI`) -- even if those type parameters
/// wind up being mapped to the same underlying type families in the
/// end.
pub trait Interner: Debug + Copy + Eq + Ord + Hash + Sized {
pub trait Interner: Debug + Copy + Eq + Hash + Sized {
/// "Interned" representation of types. In normal user code,
/// `Self::InternedType` is not referenced. Instead, we refer to
/// `Ty<Self>`, which wraps this type.
Expand Down Expand Up @@ -188,10 +188,10 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash + Sized {
type InternedVariances: Debug + Clone + Eq + Hash;

/// The core "id" type used for trait-ids and the like.
type DefId: Debug + Copy + Eq + Ord + Hash;
type DefId: Debug + Copy + Eq + Hash;

/// The ID type for ADTs
type InternedAdtId: Debug + Copy + Eq + Ord + Hash;
type InternedAdtId: Debug + Copy + Eq + Hash;

/// Representation of identifiers.
type Identifier: Debug + Clone + Eq + Hash;
Expand Down
1 change: 1 addition & 0 deletions chalk-solve/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ rustc-hash = { version = "1.1.0" }

chalk-derive = { version = "0.76.0-dev.0", path = "../chalk-derive" }
chalk-ir = { version = "0.76.0-dev.0", path = "../chalk-ir" }
indexmap = "1.7.0"

[dev-dependencies]
chalk-integration = { path = "../chalk-integration" }
Expand Down
28 changes: 17 additions & 11 deletions chalk-solve/src/coherence.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use petgraph::prelude::*;
use rustc_hash::FxHashMap;

use crate::solve::Solver;
use crate::RustIrDatabase;
use chalk_ir::interner::Interner;
use chalk_ir::{self, ImplId, TraitId};
use std::collections::BTreeMap;
use std::fmt;
use std::sync::Arc;

use indexmap::IndexMap;

pub mod orphan;
mod solve;

Expand Down Expand Up @@ -42,13 +44,13 @@ impl<I: Interner> std::error::Error for CoherenceError<I> {}
/// This basically encodes which impls specialize one another.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SpecializationPriorities<I: Interner> {
map: BTreeMap<ImplId<I>, SpecializationPriority>,
map: IndexMap<ImplId<I>, SpecializationPriority>,
}

impl<I: Interner> SpecializationPriorities<I> {
pub fn new() -> Self {
Self {
map: BTreeMap::new(),
map: IndexMap::new(),
}
}

Expand Down Expand Up @@ -106,18 +108,22 @@ where

// Build the forest of specialization relationships.
fn build_specialization_forest(&self) -> Result<Graph<ImplId<I>, ()>, CoherenceError<I>> {
// The forest is returned as a graph but built as a GraphMap; this is
// so that we never add multiple nodes with the same ItemId.
let mut forest = DiGraphMap::new();
let mut forest = DiGraph::new();
let mut node_map = FxHashMap::default();

// Find all specializations (implemented in coherence/solve)
// Record them in the forest by adding an edge from the less special
// to the more special.
// Find all specializations. Record them in the forest
// by adding an edge from the less special to the more special.
self.visit_specializations_of_trait(|less_special, more_special| {
forest.add_edge(less_special, more_special, ());
let less_special_node = *node_map
.entry(less_special)
.or_insert_with(|| forest.add_node(less_special));
let more_special_node = *node_map
.entry(more_special)
.or_insert_with(|| forest.add_node(more_special));
forest.update_edge(less_special_node, more_special_node, ());
})?;

Ok(forest.into_graph())
Ok(forest)
}

// Recursively set priorities for those node and all of its children.
Expand Down
14 changes: 8 additions & 6 deletions chalk-solve/src/display/state.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Persistent state passed down between writers.
//!
//! This is essentially `InternalWriterState` and other things supporting that.
use core::hash::Hash;
use std::{
borrow::Borrow,
collections::BTreeMap,
Expand All @@ -12,6 +13,7 @@ use std::{

use crate::RustIrDatabase;
use chalk_ir::{interner::Interner, *};
use indexmap::IndexMap;
use itertools::Itertools;

/// Like a BoundVar, but with the debrujin index inverted so as to create a
Expand All @@ -36,31 +38,31 @@ impl Display for InvertedBoundVar {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
enum UnifiedId<I: Interner> {
AdtId(I::InternedAdtId),
DefId(I::DefId),
}

#[derive(Debug)]
pub struct IdAliasStore<T: Ord> {
pub struct IdAliasStore<T> {
/// Map from the DefIds we've encountered to a u32 alias id unique to all ids
/// the same name.
aliases: BTreeMap<T, u32>,
aliases: IndexMap<T, u32>,
/// Map from each name to the next unused u32 alias id.
next_unused_for_name: BTreeMap<String, u32>,
}

impl<T: Ord> Default for IdAliasStore<T> {
impl<T> Default for IdAliasStore<T> {
fn default() -> Self {
IdAliasStore {
aliases: BTreeMap::default(),
aliases: IndexMap::default(),
next_unused_for_name: BTreeMap::default(),
}
}
}

impl<T: Copy + Ord> IdAliasStore<T> {
impl<T: Copy + Eq + Hash> IdAliasStore<T> {
fn alias_for_id_name(&mut self, id: T, name: String) -> String {
let next_unused_for_name = &mut self.next_unused_for_name;
let alias = *self.aliases.entry(id).or_insert_with(|| {
Expand Down
43 changes: 4 additions & 39 deletions chalk-solve/src/logging_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
//! `.chalk` files containing those definitions.
use std::{
borrow::Borrow,
cmp::{Ord, Ordering},
collections::BTreeSet,
fmt::{self, Debug, Display},
io::Write,
marker::PhantomData,
Expand All @@ -18,6 +16,8 @@ use crate::{
};
use chalk_ir::{interner::Interner, *};

use indexmap::IndexSet;

mod id_collector;

/// Wraps another `RustIrDatabase` (`DB`) and records which definitions are
Expand All @@ -36,7 +36,7 @@ where
I: Interner,
{
ws: WriterState<I, DB, P>,
def_ids: Mutex<BTreeSet<RecordedItemId<I>>>,
def_ids: Mutex<IndexSet<RecordedItemId<I>>>,
_phantom: PhantomData<DB>,
}

Expand Down Expand Up @@ -535,7 +535,7 @@ where
}
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum RecordedItemId<I: Interner> {
Adt(AdtId<I>),
Trait(TraitId<I>),
Expand Down Expand Up @@ -580,38 +580,3 @@ impl<I: Interner> From<GeneratorId<I>> for RecordedItemId<I> {
RecordedItemId::Generator(v)
}
}

/// Utility for implementing Ord for RecordedItemId.
#[derive(PartialEq, Eq, PartialOrd, Ord)]
enum OrderedItemId<'a, DefId, AdtId> {
DefId(&'a DefId),
AdtId(&'a AdtId),
}

impl<I: Interner> RecordedItemId<I> {
/// Extract internal identifier. Allows for absolute ordering matching the
/// order in which chalk saw things (and thus reproducing that order in
/// printed programs)
fn ordered_item_id(&self) -> OrderedItemId<'_, I::DefId, I::InternedAdtId> {
match self {
RecordedItemId::Trait(TraitId(x))
| RecordedItemId::Impl(ImplId(x))
| RecordedItemId::OpaqueTy(OpaqueTyId(x))
| RecordedItemId::Generator(GeneratorId(x))
| RecordedItemId::FnDef(FnDefId(x)) => OrderedItemId::DefId(x),
RecordedItemId::Adt(AdtId(x)) => OrderedItemId::AdtId(x),
}
}
}

impl<I: Interner> PartialOrd for RecordedItemId<I> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl<I: Interner> Ord for RecordedItemId<I> {
fn cmp(&self, other: &Self) -> Ordering {
self.ordered_item_id().cmp(&other.ordered_item_id())
}
}
11 changes: 6 additions & 5 deletions chalk-solve/src/logging_db/id_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ use chalk_ir::{
visit::{SuperVisit, Visit},
AliasTy, DebruijnIndex, TyKind, WhereClause,
};
use std::collections::BTreeSet;
use std::ops::ControlFlow;

use indexmap::IndexSet;

/// Collects the identifiers needed to resolve all the names for a given
/// set of identifers, excluding identifiers we already have.
///
Expand All @@ -34,11 +35,11 @@ use std::ops::ControlFlow;
/// resolution is successful.
pub fn collect_unrecorded_ids<'i, I: Interner, DB: RustIrDatabase<I>>(
db: &'i DB,
identifiers: &'_ BTreeSet<RecordedItemId<I>>,
) -> BTreeSet<RecordedItemId<I>> {
identifiers: &'_ IndexSet<RecordedItemId<I>>,
) -> IndexSet<RecordedItemId<I>> {
let mut collector = IdCollector {
db,
found_identifiers: BTreeSet::new(),
found_identifiers: IndexSet::new(),
};
for id in identifiers {
match *id {
Expand Down Expand Up @@ -96,7 +97,7 @@ pub fn collect_unrecorded_ids<'i, I: Interner, DB: RustIrDatabase<I>>(

struct IdCollector<'i, I: Interner, DB: RustIrDatabase<I>> {
db: &'i DB,
found_identifiers: BTreeSet<RecordedItemId<I>>,
found_identifiers: IndexSet<RecordedItemId<I>>,
}

impl<'i, I: Interner, DB: RustIrDatabase<I>> IdCollector<'i, I, DB> {
Expand Down

0 comments on commit f6f1d1b

Please sign in to comment.