diff --git a/src/solve.rs b/src/solve.rs index ea3fc105e6..d2613c33b8 100644 --- a/src/solve.rs +++ b/src/solve.rs @@ -2,7 +2,7 @@ use crate::can::ident::Lowercase; use crate::can::symbol::Symbol; use crate::collections::ImMap; use crate::region::Located; -use crate::subs::{Content, Descriptor, FlatType, Mark, Rank, Subs, Variable}; +use crate::subs::{Content, Descriptor, FlatType, Mark, OptVariable, Rank, Subs, Variable}; use crate::types::Constraint::{self, *}; use crate::types::Problem; use crate::types::Type::{self, *}; @@ -662,7 +662,7 @@ fn register(subs: &mut Subs, rank: Rank, pools: &mut Pools, content: Content) -> content, rank, mark: Mark::NONE, - copy: Variable::NULL, + copy: OptVariable::NONE, }); pools.get_mut(rank).push(var); diff --git a/src/subs.rs b/src/subs.rs index 9de0ab3f1a..4ee2d2e2fc 100644 --- a/src/subs.rs +++ b/src/subs.rs @@ -87,6 +87,35 @@ impl Into for VarStore { } } +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub struct OptVariable(usize); + +impl OptVariable { + pub const NONE: OptVariable = OptVariable(Variable::NULL.0); + + pub fn is_none(&self) -> bool { + self == &OptVariable::NONE + } + + pub fn is_some(&self) -> bool { + self != &OptVariable::NONE + } + + pub fn into_variable(self) -> Option { + if self.is_none() { + None + } else { + Some(Variable(self.0)) + } + } +} + +impl Into> for OptVariable { + fn into(self) -> Option { + self.into_variable() + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Variable(usize); @@ -95,7 +124,7 @@ impl Variable { // This lets us avoid using Option for the Descriptor's // copy field, which is a relevant space savings because we make // a *ton* of Descriptors. - pub const NULL: Variable = Variable(0); + const NULL: Variable = Variable(0); const FIRST_USER_SPACE_VAR: Variable = Variable(1); @@ -103,14 +132,6 @@ impl Variable { // This is a hack that should only ever be used for testing! Variable(num) } - - pub fn is_null(&self) -> bool { - self == &Variable::NULL - } - - pub fn is_not_null(&self) -> bool { - self != &Variable::NULL - } } impl fmt::Debug for Variable { @@ -258,7 +279,7 @@ impl Subs { pub fn restore(&mut self, var: Variable) { let desc = self.get(var); - if desc.copy.is_not_null() { + if desc.copy.is_some() { let content = desc.content; self.set(var, content.clone().into()); @@ -326,7 +347,7 @@ pub struct Descriptor { pub content: Content, pub rank: Rank, pub mark: Mark, - pub copy: Variable, + pub copy: OptVariable, } impl fmt::Debug for Descriptor { @@ -334,7 +355,10 @@ impl fmt::Debug for Descriptor { write!( f, "{:?}, r: {:?}, m: {:?} c: {:?}", - self.content, self.rank, self.mark, self.copy + self.content, + self.rank, + self.mark, + self.copy.into_variable() ) } } @@ -351,7 +375,7 @@ impl From for Descriptor { content, rank: Rank::NONE, mark: Mark::NONE, - copy: Variable::NULL, + copy: OptVariable::NONE, } } } diff --git a/src/unify.rs b/src/unify.rs index 9d2bc6cdb5..d9e5deebb4 100644 --- a/src/unify.rs +++ b/src/unify.rs @@ -1,7 +1,7 @@ use crate::can::ident::{Lowercase, ModuleName, Uppercase}; use crate::collections::ImMap; use crate::subs::Content::{self, *}; -use crate::subs::{Descriptor, FlatType, Mark, Subs, Variable}; +use crate::subs::{Descriptor, FlatType, Mark, OptVariable, Subs, Variable}; use crate::types::RecordFieldLabel; use crate::types::{Mismatch, Problem}; @@ -397,7 +397,7 @@ fn merge(subs: &mut Subs, ctx: &Context, content: Content) -> Outcome { content, rank, mark: Mark::NONE, - copy: Variable::NULL, + copy: OptVariable::NONE, }; subs.union(ctx.first, ctx.second, desc); @@ -420,7 +420,7 @@ fn fresh(subs: &mut Subs, pool: &mut Pool, ctx: &Context, content: Content) -> V content, rank: ctx.first_desc.rank.min(ctx.second_desc.rank), mark: Mark::NONE, - copy: Variable::NULL, + copy: OptVariable::NONE, }, pool, )