mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +00:00
special hash and dedup for SolvedType
This commit is contained in:
parent
7faab5d857
commit
7a8e9fe343
4 changed files with 129 additions and 8 deletions
|
@ -15,7 +15,7 @@ pub struct Symbol(u64);
|
||||||
// Set it to false if you want to see the raw ModuleId and IdentId ints,
|
// Set it to false if you want to see the raw ModuleId and IdentId ints,
|
||||||
// but please set it back to true before checking in the result!
|
// but please set it back to true before checking in the result!
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
const PRETTY_PRINT_DEBUG_SYMBOLS: bool = false;
|
const PRETTY_PRINT_DEBUG_SYMBOLS: bool = true;
|
||||||
|
|
||||||
/// In Debug builds only, Symbol has a name() method that lets
|
/// In Debug builds only, Symbol has a name() method that lets
|
||||||
/// you look up its name in a global intern table. This table is
|
/// you look up its name in a global intern table. This table is
|
||||||
|
|
|
@ -444,7 +444,7 @@ impl<'a> Procs<'a> {
|
||||||
// register the pending specialization, so this gets code genned later
|
// register the pending specialization, so this gets code genned later
|
||||||
add_pending(pending_specializations, symbol, layout.clone(), pending);
|
add_pending(pending_specializations, symbol, layout.clone(), pending);
|
||||||
|
|
||||||
debug_assert!(!self.partial_procs.contains_key(&symbol), "Procs was told to insert a value for symbol {:?}, but there was already an entry for that key! Procs should never attempt to insert duplicates.", symbol);
|
debug_assert!(!self.partial_procs.contains_key(&symbol), "Procs was told to insert a value for symbol {:?}, but there was already an entry for that key! The same PartialProc should never be added twice", symbol);
|
||||||
|
|
||||||
self.partial_procs.insert(
|
self.partial_procs.insert(
|
||||||
symbol,
|
symbol,
|
||||||
|
@ -1336,10 +1336,26 @@ pub fn specialize_all<'a>(
|
||||||
mut procs: Procs<'a>,
|
mut procs: Procs<'a>,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
) -> Procs<'a> {
|
) -> Procs<'a> {
|
||||||
|
dbg!(&procs.externals_others_need);
|
||||||
let it = procs.externals_others_need.specs.clone();
|
let it = procs.externals_others_need.specs.clone();
|
||||||
let it = it
|
let it = it
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(symbol, solved_types)| solved_types.into_iter().map(move |s| (symbol, s)))
|
.map(|(symbol, solved_types)| {
|
||||||
|
let mut as_vec: std::vec::Vec<_> = solved_types.into_iter().collect();
|
||||||
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
let hash_the_thing = |x: &SolvedType| {
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
x.hash(&mut hasher);
|
||||||
|
(hasher.finish());
|
||||||
|
};
|
||||||
|
|
||||||
|
as_vec.sort_by_key(|x| hash_the_thing(x));
|
||||||
|
as_vec.dedup_by_key(|x| hash_the_thing(x));
|
||||||
|
|
||||||
|
as_vec.into_iter().map(move |s| (symbol, s))
|
||||||
|
})
|
||||||
.flatten();
|
.flatten();
|
||||||
for (name, solved_type) in it.into_iter() {
|
for (name, solved_type) in it.into_iter() {
|
||||||
let partial_proc = match procs.partial_procs.get(&name) {
|
let partial_proc = match procs.partial_procs.get(&name) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ use roc_collections::all::{ImMap, MutSet, SendMap};
|
||||||
use roc_module::ident::{Lowercase, TagName};
|
use roc_module::ident::{Lowercase, TagName};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Located, Region};
|
use roc_region::all::{Located, Region};
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
/// A marker that a given Subs has been solved.
|
/// A marker that a given Subs has been solved.
|
||||||
/// The only way to obtain a Solved<Subs> is by running the solver on it.
|
/// The only way to obtain a Solved<Subs> is by running the solver on it.
|
||||||
|
@ -25,8 +26,114 @@ impl<T> Solved<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Hash for SolvedType {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
hash_solved_type_help(self, &mut Vec::new(), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hash_solved_type_help<H: Hasher>(
|
||||||
|
solved_type: &SolvedType,
|
||||||
|
flex_vars: &mut Vec<VarId>,
|
||||||
|
state: &mut H,
|
||||||
|
) {
|
||||||
|
use SolvedType::*;
|
||||||
|
|
||||||
|
match solved_type {
|
||||||
|
Flex(var_id) => {
|
||||||
|
var_id_hash_help(*var_id, flex_vars, state);
|
||||||
|
}
|
||||||
|
Wildcard => "wildcard".hash(state),
|
||||||
|
EmptyRecord => "empty_record".hash(state),
|
||||||
|
EmptyTagUnion => "empty_tag_union".hash(state),
|
||||||
|
Error => "error".hash(state),
|
||||||
|
Func(arguments, closure, result) => {
|
||||||
|
for x in arguments {
|
||||||
|
hash_solved_type_help(x, flex_vars, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_solved_type_help(closure, flex_vars, state);
|
||||||
|
hash_solved_type_help(result, flex_vars, state);
|
||||||
|
}
|
||||||
|
Apply(name, arguments) => {
|
||||||
|
name.hash(state);
|
||||||
|
for x in arguments {
|
||||||
|
hash_solved_type_help(x, flex_vars, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rigid(name) => name.hash(state),
|
||||||
|
Erroneous(problem) => problem.hash(state),
|
||||||
|
Boolean(solved_bool) => solved_bool.hash(state),
|
||||||
|
|
||||||
|
Record { fields, ext } => {
|
||||||
|
for (name, x) in fields {
|
||||||
|
name.hash(state);
|
||||||
|
"record_field".hash(state);
|
||||||
|
hash_solved_type_help(x.as_inner(), flex_vars, state);
|
||||||
|
}
|
||||||
|
hash_solved_type_help(ext, flex_vars, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
TagUnion(tags, ext) => {
|
||||||
|
for (name, arguments) in tags {
|
||||||
|
name.hash(state);
|
||||||
|
for x in arguments {
|
||||||
|
hash_solved_type_help(x, flex_vars, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_solved_type_help(ext, flex_vars, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
RecursiveTagUnion(rec, tags, ext) => {
|
||||||
|
var_id_hash_help(*rec, flex_vars, state);
|
||||||
|
for (name, arguments) in tags {
|
||||||
|
name.hash(state);
|
||||||
|
for x in arguments {
|
||||||
|
hash_solved_type_help(x, flex_vars, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hash_solved_type_help(ext, flex_vars, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
Alias(name, arguments, actual) => {
|
||||||
|
name.hash(state);
|
||||||
|
for (name, x) in arguments {
|
||||||
|
name.hash(state);
|
||||||
|
hash_solved_type_help(x, flex_vars, state);
|
||||||
|
}
|
||||||
|
hash_solved_type_help(actual, flex_vars, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
HostExposedAlias {
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
actual,
|
||||||
|
actual_var,
|
||||||
|
} => {
|
||||||
|
name.hash(state);
|
||||||
|
for (name, x) in arguments {
|
||||||
|
name.hash(state);
|
||||||
|
hash_solved_type_help(x, flex_vars, state);
|
||||||
|
}
|
||||||
|
hash_solved_type_help(actual, flex_vars, state);
|
||||||
|
var_id_hash_help(*actual_var, flex_vars, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn var_id_hash_help<H: Hasher>(var_id: VarId, flex_vars: &mut Vec<VarId>, state: &mut H) {
|
||||||
|
let opt_index = flex_vars.iter().position(|x| *x == var_id);
|
||||||
|
match opt_index {
|
||||||
|
Some(index) => index.hash(state),
|
||||||
|
None => {
|
||||||
|
flex_vars.len().hash(state);
|
||||||
|
flex_vars.push(var_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This is a fully solved type, with no Variables remaining in it.
|
/// This is a fully solved type, with no Variables remaining in it.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum SolvedType {
|
pub enum SolvedType {
|
||||||
/// A function. The types of its arguments, then the type of its return value.
|
/// A function. The types of its arguments, then the type of its return value.
|
||||||
Func(Vec<SolvedType>, Box<SolvedType>, Box<SolvedType>),
|
Func(Vec<SolvedType>, Box<SolvedType>, Box<SolvedType>),
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
app Main provides [ main ] imports [ Effect ]
|
app Main provides [ main ] imports [ Effect ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
main : Effect.Effect {} as Fx
|
main : Effect.Effect {} as Fx
|
||||||
main =
|
main =
|
||||||
d = Effect.putChar 68
|
|
||||||
e = Effect.putChar 69
|
e = Effect.putChar 69
|
||||||
|
d = Effect.putChar 68
|
||||||
|
|
||||||
e |> Effect.after \{} -> e
|
e |> Effect.after \{} -> d
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue