store lambda set in alias types

This commit is contained in:
Folkert 2021-07-28 15:26:25 +02:00
parent dad5d5de85
commit 4cefbec5c7
11 changed files with 223 additions and 103 deletions

View file

@ -234,7 +234,12 @@ fn can_annotation_help(
// instantiate variables // instantiate variables
actual.substitute(&substitutions); actual.substitute(&substitutions);
Type::Alias(symbol, vars, Box::new(actual)) Type::Alias {
symbol,
type_arguments: vars,
lambda_set_variables: alias.lambda_set_variables.clone(),
actual: Box::new(actual),
}
} }
None => { None => {
let mut args = Vec::new(); let mut args = Vec::new();
@ -378,7 +383,12 @@ fn can_annotation_help(
actual_var, actual_var,
} }
} else { } else {
Type::Alias(symbol, vars, Box::new(alias.typ.clone())) Type::Alias {
symbol,
type_arguments: vars,
lambda_set_variables: alias.lambda_set_variables.clone(),
actual: Box::new(alias.typ.clone()),
}
} }
} }
_ => { _ => {

View file

@ -76,7 +76,7 @@ fn subtract(declared: &Declared, detail: &VariableDetail, accum: &mut VariableDe
} }
if !declared.flex_vars.contains(&var.into_inner()) { if !declared.flex_vars.contains(&var.into_inner()) {
accum.lambda_set_variables.insert(*var); accum.lambda_set_variables.push(*var);
} }
} }

View file

@ -1634,7 +1634,7 @@ fn make_tag_union_recursive<'a>(
typ.substitute_alias(symbol, &Type::Variable(rec_var)); typ.substitute_alias(symbol, &Type::Variable(rec_var));
} }
Type::RecursiveTagUnion(_, _, _) => {} Type::RecursiveTagUnion(_, _, _) => {}
Type::Alias(_, _, actual) => make_tag_union_recursive( Type::Alias { actual, .. } => make_tag_union_recursive(
env, env,
symbol, symbol,
region, region,

View file

@ -47,7 +47,7 @@ impl Scope {
let alias = Alias { let alias = Alias {
region, region,
typ, typ,
lambda_set_variables: MutSet::default(), lambda_set_variables: Vec::new(),
recursion_variables: MutSet::default(), recursion_variables: MutSet::default(),
type_variables: variables, type_variables: variables,
}; };

View file

@ -2,7 +2,7 @@ use roc_can::constraint::Constraint::{self, *};
use roc_can::constraint::LetConstraint; use roc_can::constraint::LetConstraint;
use roc_can::expected::Expected::{self, *}; use roc_can::expected::Expected::{self, *};
use roc_collections::all::SendMap; use roc_collections::all::SendMap;
use roc_module::ident::TagName; use roc_module::ident::{Lowercase, TagName};
use roc_module::symbol::Symbol; use roc_module::symbol::Symbol;
use roc_region::all::Region; use roc_region::all::Region;
use roc_types::subs::Variable; use roc_types::subs::Variable;
@ -89,9 +89,23 @@ pub fn str_type() -> Type {
builtin_type(Symbol::STR_STR, Vec::new()) builtin_type(Symbol::STR_STR, Vec::new())
} }
#[inline(always)]
fn builtin_alias(
symbol: Symbol,
type_arguments: Vec<(Lowercase, Type)>,
actual: Box<Type>,
) -> Type {
Type::Alias {
symbol,
type_arguments,
actual,
lambda_set_variables: vec![],
}
}
#[inline(always)] #[inline(always)]
pub fn num_float(range: Type) -> Type { pub fn num_float(range: Type) -> Type {
Type::Alias( builtin_alias(
Symbol::NUM_FLOAT, Symbol::NUM_FLOAT,
vec![("range".into(), range.clone())], vec![("range".into(), range.clone())],
Box::new(num_num(num_floatingpoint(range))), Box::new(num_num(num_floatingpoint(range))),
@ -108,7 +122,7 @@ pub fn num_floatingpoint(range: Type) -> Type {
Box::new(Type::EmptyTagUnion), Box::new(Type::EmptyTagUnion),
); );
Type::Alias( builtin_alias(
Symbol::NUM_FLOATINGPOINT, Symbol::NUM_FLOATINGPOINT,
vec![("range".into(), range)], vec![("range".into(), range)],
Box::new(alias_content), Box::new(alias_content),
@ -122,12 +136,12 @@ pub fn num_binary64() -> Type {
Box::new(Type::EmptyTagUnion), Box::new(Type::EmptyTagUnion),
); );
Type::Alias(Symbol::NUM_BINARY64, vec![], Box::new(alias_content)) builtin_alias(Symbol::NUM_BINARY64, vec![], Box::new(alias_content))
} }
#[inline(always)] #[inline(always)]
pub fn num_int(range: Type) -> Type { pub fn num_int(range: Type) -> Type {
Type::Alias( builtin_alias(
Symbol::NUM_INT, Symbol::NUM_INT,
vec![("range".into(), range.clone())], vec![("range".into(), range.clone())],
Box::new(num_num(num_integer(range))), Box::new(num_num(num_integer(range))),
@ -141,7 +155,7 @@ pub fn num_signed64() -> Type {
Box::new(Type::EmptyTagUnion), Box::new(Type::EmptyTagUnion),
); );
Type::Alias(Symbol::NUM_SIGNED64, vec![], Box::new(alias_content)) builtin_alias(Symbol::NUM_SIGNED64, vec![], Box::new(alias_content))
} }
#[inline(always)] #[inline(always)]
@ -154,7 +168,7 @@ pub fn num_integer(range: Type) -> Type {
Box::new(Type::EmptyTagUnion), Box::new(Type::EmptyTagUnion),
); );
Type::Alias( builtin_alias(
Symbol::NUM_INTEGER, Symbol::NUM_INTEGER,
vec![("range".into(), range)], vec![("range".into(), range)],
Box::new(alias_content), Box::new(alias_content),
@ -168,7 +182,7 @@ pub fn num_num(typ: Type) -> Type {
Box::new(Type::EmptyTagUnion), Box::new(Type::EmptyTagUnion),
); );
Type::Alias( builtin_alias(
Symbol::NUM_NUM, Symbol::NUM_NUM,
vec![("range".into(), typ)], vec![("range".into(), typ)],
Box::new(alias_content), Box::new(alias_content),

View file

@ -1,3 +1,4 @@
use roc_can::annotation::IntroducedVariables;
use roc_can::def::{Declaration, Def}; use roc_can::def::{Declaration, Def};
use roc_can::env::Env; use roc_can::env::Env;
use roc_can::expr::{Expr, Recursive}; use roc_can::expr::{Expr, Recursive};
@ -160,25 +161,22 @@ fn build_effect_always(
(function_var, closure) (function_var, closure)
}; };
use roc_can::annotation::IntroducedVariables;
let mut introduced_variables = IntroducedVariables::default(); let mut introduced_variables = IntroducedVariables::default();
let signature = { let signature = {
// Effect.always : a -> Effect a // Effect.always : a -> Effect a
let var_a = var_store.fresh(); let var_a = var_store.fresh();
introduced_variables.insert_named("a".into(), var_a); introduced_variables.insert_named("a".into(), var_a);
let effect_a = { let effect_a = build_effect_alias(
let actual = build_effect_actual(effect_tag_name, Type::Variable(var_a), var_store); effect_symbol,
effect_tag_name,
Type::Alias( "a",
effect_symbol, var_a,
vec![("a".into(), Type::Variable(var_a))], Type::Variable(var_a),
Box::new(actual), var_store,
) &mut introduced_variables,
}; );
let closure_var = var_store.fresh(); let closure_var = var_store.fresh();
introduced_variables.insert_wildcard(closure_var); introduced_variables.insert_wildcard(closure_var);
@ -353,8 +351,6 @@ fn build_effect_map(
loc_body: Box::new(Located::at_zero(body)), loc_body: Box::new(Located::at_zero(body)),
}; };
use roc_can::annotation::IntroducedVariables;
let mut introduced_variables = IntroducedVariables::default(); let mut introduced_variables = IntroducedVariables::default();
let signature = { let signature = {
@ -365,26 +361,25 @@ fn build_effect_map(
introduced_variables.insert_named("a".into(), var_a); introduced_variables.insert_named("a".into(), var_a);
introduced_variables.insert_named("b".into(), var_b); introduced_variables.insert_named("b".into(), var_b);
let effect_a = { let effect_a = build_effect_alias(
let actual = effect_symbol,
build_effect_actual(effect_tag_name.clone(), Type::Variable(var_a), var_store); effect_tag_name.clone(),
"a",
var_a,
Type::Variable(var_a),
var_store,
&mut introduced_variables,
);
Type::Alias( let effect_b = build_effect_alias(
effect_symbol, effect_symbol,
vec![("a".into(), Type::Variable(var_a))], effect_tag_name,
Box::new(actual), "b",
) var_b,
}; Type::Variable(var_b),
var_store,
let effect_b = { &mut introduced_variables,
let actual = build_effect_actual(effect_tag_name, Type::Variable(var_b), var_store); );
Type::Alias(
effect_symbol,
vec![("b".into(), Type::Variable(var_b))],
Box::new(actual),
)
};
let closure_var = var_store.fresh(); let closure_var = var_store.fresh();
introduced_variables.insert_wildcard(closure_var); introduced_variables.insert_wildcard(closure_var);
@ -526,8 +521,6 @@ fn build_effect_after(
loc_body: Box::new(Located::at_zero(to_effect_call)), loc_body: Box::new(Located::at_zero(to_effect_call)),
}; };
use roc_can::annotation::IntroducedVariables;
let mut introduced_variables = IntroducedVariables::default(); let mut introduced_variables = IntroducedVariables::default();
let signature = { let signature = {
@ -537,26 +530,25 @@ fn build_effect_after(
introduced_variables.insert_named("a".into(), var_a); introduced_variables.insert_named("a".into(), var_a);
introduced_variables.insert_named("b".into(), var_b); introduced_variables.insert_named("b".into(), var_b);
let effect_a = { let effect_a = build_effect_alias(
let actual = effect_symbol,
build_effect_actual(effect_tag_name.clone(), Type::Variable(var_a), var_store); effect_tag_name.clone(),
"a",
var_a,
Type::Variable(var_a),
var_store,
&mut introduced_variables,
);
Type::Alias( let effect_b = build_effect_alias(
effect_symbol, effect_symbol,
vec![("a".into(), Type::Variable(var_a))], effect_tag_name,
Box::new(actual), "b",
) var_b,
}; Type::Variable(var_b),
var_store,
let effect_b = { &mut introduced_variables,
let actual = build_effect_actual(effect_tag_name, Type::Variable(var_b), var_store); );
Type::Alias(
effect_symbol,
vec![("b".into(), Type::Variable(var_b))],
Box::new(actual),
)
};
let closure_var = var_store.fresh(); let closure_var = var_store.fresh();
introduced_variables.insert_wildcard(closure_var); introduced_variables.insert_wildcard(closure_var);
@ -763,6 +755,40 @@ pub fn build_host_exposed_def(
} }
} }
fn build_effect_alias(
effect_symbol: Symbol,
effect_tag_name: TagName,
a_name: &str,
a_var: Variable,
a_type: Type,
var_store: &mut VarStore,
introduced_variables: &mut IntroducedVariables,
) -> Type {
let closure_var = var_store.fresh();
introduced_variables.insert_wildcard(closure_var);
let actual = {
Type::TagUnion(
vec![(
effect_tag_name,
vec![Type::Function(
vec![Type::EmptyRec],
Box::new(Type::Variable(closure_var)),
Box::new(a_type),
)],
)],
Box::new(Type::EmptyTagUnion),
)
};
Type::Alias {
symbol: effect_symbol,
type_arguments: vec![(a_name.into(), Type::Variable(a_var))],
lambda_set_variables: vec![roc_types::subs::LambdaSet(closure_var)],
actual: Box::new(actual),
}
}
pub fn build_effect_actual( pub fn build_effect_actual(
effect_tag_name: TagName, effect_tag_name: TagName,
a_type: Type, a_type: Type,

View file

@ -790,8 +790,14 @@ fn type_to_variable(
tag_union_var tag_union_var
} }
Alias(Symbol::BOOL_BOOL, _, _) => Variable::BOOL,
Alias(symbol, args, alias_type) => { Type::Alias {
symbol,
type_arguments: args,
actual: alias_type,
lambda_set_variables,
} => {
dbg!(lambda_set_variables);
let mut arg_vars = Vec::with_capacity(args.len()); let mut arg_vars = Vec::with_capacity(args.len());
for (arg, arg_type) in args { for (arg, arg_type) in args {

View file

@ -183,6 +183,7 @@ pub enum SolvedType {
Erroneous(Problem), Erroneous(Problem),
/// A type alias /// A type alias
/// TODO transmit lambda sets!
Alias(Symbol, Vec<(Lowercase, SolvedType)>, Box<SolvedType>), Alias(Symbol, Vec<(Lowercase, SolvedType)>, Box<SolvedType>),
HostExposedAlias { HostExposedAlias {
@ -293,11 +294,16 @@ impl SolvedType {
) )
} }
Erroneous(problem) => SolvedType::Erroneous(problem.clone()), Erroneous(problem) => SolvedType::Erroneous(problem.clone()),
Alias(symbol, args, box_type) => { Alias {
symbol,
type_arguments,
actual: box_type,
..
} => {
let solved_type = Self::from_type(solved_subs, box_type); let solved_type = Self::from_type(solved_subs, box_type);
let mut solved_args = Vec::with_capacity(args.len()); let mut solved_args = Vec::with_capacity(type_arguments.len());
for (name, var) in args { for (name, var) in type_arguments {
solved_args.push((name.clone(), Self::from_type(solved_subs, var))); solved_args.push((name.clone(), Self::from_type(solved_subs, var)));
} }
@ -617,7 +623,12 @@ pub fn to_type(
let actual = to_type(solved_actual, free_vars, var_store); let actual = to_type(solved_actual, free_vars, var_store);
Type::Alias(*symbol, type_variables, Box::new(actual)) Type::Alias {
symbol: *symbol,
type_arguments: type_variables,
lambda_set_variables: vec![], // TODO transfer lambda sets
actual: Box::new(actual),
}
} }
HostExposedAlias { HostExposedAlias {
name, name,

View file

@ -206,7 +206,7 @@ impl UnifyKey for Variable {
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LambdaSet(Variable); pub struct LambdaSet(pub Variable);
impl fmt::Debug for LambdaSet { impl fmt::Debug for LambdaSet {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View file

@ -12,6 +12,11 @@ pub const TYPE_NUM: &str = "Num";
pub const TYPE_INTEGER: &str = "Integer"; pub const TYPE_INTEGER: &str = "Integer";
pub const TYPE_FLOATINGPOINT: &str = "FloatingPoint"; pub const TYPE_FLOATINGPOINT: &str = "FloatingPoint";
const GREEK_LETTERS: &[char] = &[
'α', 'ν', 'β', 'ξ', 'γ', 'ο', 'δ', 'π', 'ε', 'ρ', 'ζ', 'σ', 'η', 'τ', 'θ', 'υ', 'ι', 'φ', 'κ',
'χ', 'λ', 'ψ', 'μ', 'ω', 'ς',
];
/// ///
/// Intuitively /// Intuitively
/// ///
@ -142,7 +147,12 @@ pub enum Type {
Record(SendMap<Lowercase, RecordField<Type>>, Box<Type>), Record(SendMap<Lowercase, RecordField<Type>>, Box<Type>),
TagUnion(Vec<(TagName, Vec<Type>)>, Box<Type>), TagUnion(Vec<(TagName, Vec<Type>)>, Box<Type>),
FunctionOrTagUnion(TagName, Symbol, Box<Type>), FunctionOrTagUnion(TagName, Symbol, Box<Type>),
Alias(Symbol, Vec<(Lowercase, Type)>, Box<Type>), Alias {
symbol: Symbol,
type_arguments: Vec<(Lowercase, Type)>,
lambda_set_variables: Vec<LambdaSet>,
actual: Box<Type>,
},
HostExposedAlias { HostExposedAlias {
name: Symbol, name: Symbol,
arguments: Vec<(Lowercase, Type)>, arguments: Vec<(Lowercase, Type)>,
@ -198,13 +208,22 @@ impl fmt::Debug for Type {
write!(f, ")") write!(f, ")")
} }
Type::Alias(symbol, args, _actual) => { Type::Alias {
symbol,
type_arguments,
lambda_set_variables,
..
} => {
write!(f, "Alias {:?}", symbol)?; write!(f, "Alias {:?}", symbol)?;
for (_, arg) in args { for (_, arg) in type_arguments {
write!(f, " {:?}", arg)?; write!(f, " {:?}", arg)?;
} }
for (_, greek_letter) in lambda_set_variables.iter().zip(GREEK_LETTERS.iter()) {
write!(f, " {:?}", greek_letter)?;
}
// Sometimes it's useful to see the expansion of the alias // Sometimes it's useful to see the expansion of the alias
// write!(f, "[ but actually {:?} ]", _actual)?; // write!(f, "[ but actually {:?} ]", _actual)?;
@ -442,11 +461,16 @@ impl Type {
} }
ext.substitute(substitutions); ext.substitute(substitutions);
} }
Alias(_, zipped, actual_type) => { Alias {
for (_, value) in zipped.iter_mut() { type_arguments,
actual,
..
} => {
for (_, value) in type_arguments.iter_mut() {
value.substitute(substitutions); value.substitute(substitutions);
} }
actual_type.substitute(substitutions);
actual.substitute(substitutions);
} }
HostExposedAlias { HostExposedAlias {
arguments, arguments,
@ -497,8 +521,11 @@ impl Type {
} }
ext.substitute_alias(rep_symbol, actual); ext.substitute_alias(rep_symbol, actual);
} }
Alias(_, _, actual_type) => { Alias {
actual_type.substitute_alias(rep_symbol, actual); actual: alias_actual,
..
} => {
alias_actual.substitute_alias(rep_symbol, actual);
} }
HostExposedAlias { HostExposedAlias {
actual: actual_type, actual: actual_type,
@ -547,9 +574,11 @@ impl Type {
ext.contains_symbol(rep_symbol) ext.contains_symbol(rep_symbol)
|| fields.values().any(|arg| arg.contains_symbol(rep_symbol)) || fields.values().any(|arg| arg.contains_symbol(rep_symbol))
} }
Alias(alias_symbol, _, actual_type) => { Alias {
alias_symbol == &rep_symbol || actual_type.contains_symbol(rep_symbol) symbol: alias_symbol,
} actual: actual_type,
..
} => alias_symbol == &rep_symbol || actual_type.contains_symbol(rep_symbol),
HostExposedAlias { name, actual, .. } => { HostExposedAlias { name, actual, .. } => {
name == &rep_symbol || actual.contains_symbol(rep_symbol) name == &rep_symbol || actual.contains_symbol(rep_symbol)
} }
@ -585,7 +614,10 @@ impl Type {
.values() .values()
.any(|arg| arg.contains_variable(rep_variable)) .any(|arg| arg.contains_variable(rep_variable))
} }
Alias(_, _, actual_type) => actual_type.contains_variable(rep_variable), Alias {
actual: actual_type,
..
} => actual_type.contains_variable(rep_variable),
HostExposedAlias { actual, .. } => actual.contains_variable(rep_variable), HostExposedAlias { actual, .. } => actual.contains_variable(rep_variable),
Apply(_, args) => args.iter().any(|arg| arg.contains_variable(rep_variable)), Apply(_, args) => args.iter().any(|arg| arg.contains_variable(rep_variable)),
EmptyRec | EmptyTagUnion | Erroneous(_) => false, EmptyRec | EmptyTagUnion | Erroneous(_) => false,
@ -602,7 +634,7 @@ impl Type {
/// a shallow dealias, continue until the first constructor is not an alias. /// a shallow dealias, continue until the first constructor is not an alias.
pub fn shallow_dealias(&self) -> &Self { pub fn shallow_dealias(&self) -> &Self {
match self { match self {
Type::Alias(_, _, actual) => actual.shallow_dealias(), Type::Alias { actual, .. } => actual.shallow_dealias(),
_ => self, _ => self,
} }
} }
@ -646,7 +678,11 @@ impl Type {
actual: actual_type, actual: actual_type,
.. ..
} }
| Alias(_, type_args, actual_type) => { | Alias {
type_arguments: type_args,
actual: actual_type,
..
} => {
for arg in type_args { for arg in type_args {
arg.1 arg.1
.instantiate_aliases(region, aliases, var_store, introduced); .instantiate_aliases(region, aliases, var_store, introduced);
@ -737,13 +773,19 @@ impl Type {
} }
ext.substitute(&substitution); ext.substitute(&substitution);
*self = Type::Alias( *self = Type::Alias {
*symbol, symbol: *symbol,
named_args, type_arguments: named_args,
Box::new(Type::RecursiveTagUnion(new_rec_var, tags, ext)), lambda_set_variables: alias.lambda_set_variables.clone(),
); actual: Box::new(Type::RecursiveTagUnion(new_rec_var, tags, ext)),
};
} else { } else {
*self = Type::Alias(*symbol, named_args, Box::new(actual)); *self = Type::Alias {
symbol: *symbol,
type_arguments: named_args,
lambda_set_variables: alias.lambda_set_variables.clone(),
actual: Box::new(actual),
};
} }
} else { } else {
// one of the special-cased Apply types. // one of the special-cased Apply types.
@ -789,7 +831,11 @@ fn symbols_help(tipe: &Type, accum: &mut ImSet<Symbol>) {
} }
}); });
} }
Alias(alias_symbol, _, actual_type) => { Alias {
symbol: alias_symbol,
actual: actual_type,
..
} => {
accum.insert(*alias_symbol); accum.insert(*alias_symbol);
symbols_help(&actual_type, accum); symbols_help(&actual_type, accum);
} }
@ -859,8 +905,12 @@ fn variables_help(tipe: &Type, accum: &mut ImSet<Variable>) {
// this rec var doesn't need to be in flex_vars or rigid_vars // this rec var doesn't need to be in flex_vars or rigid_vars
accum.remove(rec); accum.remove(rec);
} }
Alias(_, args, actual) => { Alias {
for (_, arg) in args { type_arguments,
actual,
..
} => {
for (_, arg) in type_arguments {
variables_help(arg, accum); variables_help(arg, accum);
} }
variables_help(actual, accum); variables_help(actual, accum);
@ -884,7 +934,7 @@ fn variables_help(tipe: &Type, accum: &mut ImSet<Variable>) {
#[derive(Default)] #[derive(Default)]
pub struct VariableDetail { pub struct VariableDetail {
pub type_variables: MutSet<Variable>, pub type_variables: MutSet<Variable>,
pub lambda_set_variables: MutSet<LambdaSet>, pub lambda_set_variables: Vec<LambdaSet>,
pub recursion_variables: MutSet<Variable>, pub recursion_variables: MutSet<Variable>,
} }
@ -911,7 +961,7 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) {
variables_help_detailed(arg, accum); variables_help_detailed(arg, accum);
} }
if let Type::Variable(v) = **closure { if let Type::Variable(v) = **closure {
accum.lambda_set_variables.insert(LambdaSet::from(v)); accum.lambda_set_variables.push(LambdaSet::from(v));
} else { } else {
variables_help_detailed(closure, accum); variables_help_detailed(closure, accum);
} }
@ -957,8 +1007,12 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) {
accum.recursion_variables.insert(*rec); accum.recursion_variables.insert(*rec);
} }
Alias(_, args, actual) => { Alias {
for (_, arg) in args { type_arguments,
actual,
..
} => {
for (_, arg) in type_arguments {
variables_help_detailed(arg, accum); variables_help_detailed(arg, accum);
} }
variables_help_detailed(actual, accum); variables_help_detailed(actual, accum);
@ -1106,7 +1160,7 @@ pub struct Alias {
/// lambda set variables, e.g. the one annotating the arrow in /// lambda set variables, e.g. the one annotating the arrow in
/// a |c|-> b /// a |c|-> b
pub lambda_set_variables: MutSet<LambdaSet>, pub lambda_set_variables: Vec<LambdaSet>,
pub recursion_variables: MutSet<Variable>, pub recursion_variables: MutSet<Variable>,

View file

@ -767,7 +767,6 @@ fn type_to_variable<'a>(
register(subs, rank, pools, content) register(subs, rank, pools, content)
} }
Alias(Symbol::BOOL_BOOL, _, _) => roc_types::subs::Variable::BOOL,
Alias(symbol, args, alias_type_id) => { Alias(symbol, args, alias_type_id) => {
// TODO cache in uniqueness inference gives problems! all Int's get the same uniqueness var! // TODO cache in uniqueness inference gives problems! all Int's get the same uniqueness var!
// Cache aliases without type arguments. Commonly used aliases like `Int` would otherwise get O(n) // Cache aliases without type arguments. Commonly used aliases like `Int` would otherwise get O(n)