mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-10 10:02:38 +03:00
loads of things
This commit is contained in:
parent
ac18da302c
commit
79f01e0604
@ -1691,7 +1691,7 @@ fn constrain_def_pattern(
|
||||
fn annotation_to_attr_type(
|
||||
var_store: &mut VarStore,
|
||||
ann: &Type,
|
||||
rigids: &mut ImMap<Variable, Variable>,
|
||||
rigids: &mut ImSet<Variable>,
|
||||
change_var_kind: bool,
|
||||
) -> (Vec<Variable>, Type) {
|
||||
use roc_types::types::Type::*;
|
||||
@ -1699,19 +1699,12 @@ fn annotation_to_attr_type(
|
||||
match ann {
|
||||
Variable(var) => {
|
||||
if change_var_kind {
|
||||
if let Some(uvar) = rigids.get(var) {
|
||||
(
|
||||
vec![],
|
||||
attr_type(Bool::variable(*uvar), Type::Variable(*var)),
|
||||
)
|
||||
} else {
|
||||
let uvar = var_store.fresh();
|
||||
rigids.insert(*var, uvar);
|
||||
(
|
||||
vec![],
|
||||
attr_type(Bool::variable(uvar), Type::Variable(*var)),
|
||||
)
|
||||
}
|
||||
let uvar = var_store.fresh();
|
||||
rigids.insert(uvar);
|
||||
(
|
||||
vec![],
|
||||
attr_type(Bool::variable(uvar), Type::Variable(*var)),
|
||||
)
|
||||
} else {
|
||||
(vec![], Type::Variable(*var))
|
||||
}
|
||||
@ -1900,7 +1893,7 @@ fn annotation_to_attr_type(
|
||||
fn annotation_to_attr_type_many(
|
||||
var_store: &mut VarStore,
|
||||
anns: &[Type],
|
||||
rigids: &mut ImMap<Variable, Variable>,
|
||||
rigids: &mut ImSet<Variable>,
|
||||
change_var_kind: bool,
|
||||
) -> (Vec<Variable>, Vec<Type>) {
|
||||
anns.iter()
|
||||
@ -1926,7 +1919,7 @@ fn aliases_to_attr_type(var_store: &mut VarStore, aliases: &mut SendMap<Symbol,
|
||||
//
|
||||
// That would give a double attr wrapper on the type arguments.
|
||||
// The `change_var_kind` flag set to false ensures type variables remain of kind *
|
||||
let (_, new) = annotation_to_attr_type(var_store, &alias.typ, &mut ImMap::default(), false);
|
||||
let (_, new) = annotation_to_attr_type(var_store, &alias.typ, &mut ImSet::default(), false);
|
||||
// remove the outer Attr, because when this occurs in a signature it'll already be wrapped in one
|
||||
match new {
|
||||
Type::Apply(Symbol::ATTR_ATTR, args) => {
|
||||
@ -1942,8 +1935,6 @@ fn aliases_to_attr_type(var_store: &mut VarStore, aliases: &mut SendMap<Symbol,
|
||||
fix_mutual_recursive_alias(&mut alias.typ, b);
|
||||
}
|
||||
}
|
||||
|
||||
dbg!(&aliases);
|
||||
}
|
||||
|
||||
fn constrain_def(
|
||||
@ -2077,9 +2068,9 @@ fn instantiate_rigids(
|
||||
annotation.substitute(&rigid_substitution);
|
||||
}
|
||||
|
||||
let mut new_rigid_pairs = ImMap::default();
|
||||
let mut new_uniqueness_rigids = ImSet::default();
|
||||
let (mut uniq_vars, annotation) =
|
||||
annotation_to_attr_type(var_store, &annotation, &mut new_rigid_pairs, true);
|
||||
annotation_to_attr_type(var_store, &annotation, &mut new_uniqueness_rigids, true);
|
||||
|
||||
if let Pattern::Identifier(symbol) = loc_pattern.value {
|
||||
headers.insert(symbol, Located::at(loc_pattern.region, annotation.clone()));
|
||||
@ -2089,7 +2080,7 @@ fn instantiate_rigids(
|
||||
) {
|
||||
for (k, v) in new_headers {
|
||||
let (new_uniq_vars, attr_annotation) =
|
||||
annotation_to_attr_type(var_store, &v.value, &mut new_rigid_pairs, true);
|
||||
annotation_to_attr_type(var_store, &v.value, &mut new_uniqueness_rigids, true);
|
||||
|
||||
uniq_vars.extend(new_uniq_vars);
|
||||
|
||||
@ -2099,10 +2090,7 @@ fn instantiate_rigids(
|
||||
|
||||
new_rigids.extend(uniq_vars);
|
||||
new_rigids.extend(introduced_vars.wildcards.iter().cloned());
|
||||
|
||||
for (_, v) in new_rigid_pairs {
|
||||
new_rigids.push(v);
|
||||
}
|
||||
new_rigids.extend(new_uniqueness_rigids);
|
||||
|
||||
annotation
|
||||
}
|
||||
|
@ -650,6 +650,7 @@ fn type_to_variable(
|
||||
}
|
||||
Alias(Symbol::BOOL_BOOL, _, _) => Variable::BOOL,
|
||||
Alias(symbol, args, alias_type) => {
|
||||
// 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)
|
||||
// different variables (once for each occurence). The recursion restriction is required
|
||||
// for uniqueness types only: recursive aliases "introduce" an unbound uniqueness
|
||||
@ -666,11 +667,13 @@ fn type_to_variable(
|
||||
// TODO does caching work at all with uniqueness types? even Int then hides a uniqueness variable
|
||||
let is_recursive = alias_type.is_recursive();
|
||||
let no_args = args.is_empty();
|
||||
/*
|
||||
if no_args && !is_recursive {
|
||||
if let Some(var) = cached.get(symbol) {
|
||||
return *var;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
let mut arg_vars = Vec::with_capacity(args.len());
|
||||
let mut new_aliases = ImMap::default();
|
||||
@ -688,7 +691,7 @@ fn type_to_variable(
|
||||
let result = register(subs, rank, pools, content);
|
||||
|
||||
if no_args && !is_recursive {
|
||||
cached.insert(*symbol, result);
|
||||
// cached.insert(*symbol, result);
|
||||
}
|
||||
|
||||
result
|
||||
|
@ -1737,8 +1737,6 @@ mod test_uniq_solve {
|
||||
);
|
||||
}
|
||||
|
||||
// This snippet exhibits the rank issue. Seems to only occur when using recursive types with
|
||||
// recursive functions.
|
||||
#[test]
|
||||
fn rigids_in_signature() {
|
||||
infer_eq(
|
||||
@ -1746,13 +1744,19 @@ mod test_uniq_solve {
|
||||
r#"
|
||||
ConsList a : [ Cons a (ConsList a), Nil ]
|
||||
|
||||
map : (p -> q), p -> ConsList q
|
||||
map = \f, x -> map f x
|
||||
map : (p -> q), ConsList p -> ConsList q
|
||||
map = \f, list ->
|
||||
when list is
|
||||
Cons x xs ->
|
||||
Cons (f x) (map f xs)
|
||||
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
map
|
||||
"#
|
||||
),
|
||||
"Attr Shared (Attr * (Attr a p -> Attr b q), Attr a p -> Attr * (ConsList (Attr b q)))",
|
||||
"Attr Shared (Attr Shared (Attr a p -> Attr b q), Attr (* | a) (ConsList (Attr a p)) -> Attr * (ConsList (Attr b q)))",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1773,7 +1777,7 @@ mod test_uniq_solve {
|
||||
toEmpty
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr * (ConsList (Attr a p)) -> Attr * (ConsList (Attr a p)))",
|
||||
"Attr * (Attr * (ConsList (Attr * p)) -> Attr * (ConsList (Attr * p)))",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1794,7 +1798,7 @@ mod test_uniq_solve {
|
||||
toEmpty
|
||||
"#
|
||||
),
|
||||
"Attr Shared (Attr * (ConsList (Attr a p)) -> Attr * (ConsList (Attr a p)))",
|
||||
"Attr Shared (Attr * (ConsList (Attr * p)) -> Attr * (ConsList (Attr * p)))",
|
||||
);
|
||||
}
|
||||
|
||||
@ -1830,33 +1834,61 @@ mod test_uniq_solve {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn typecheck_mutually_recursive_tag_union() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
ListA a b : [ Cons a (ListB b a), Nil ]
|
||||
ListB a b : [ Cons a (ListA b a), Nil ]
|
||||
|
||||
ConsList q : [ Cons q (ConsList q), Nil ]
|
||||
|
||||
toAs : (q -> p), ListA p q -> ConsList p
|
||||
toAs =
|
||||
\f, lista ->
|
||||
when lista is
|
||||
Nil -> Nil
|
||||
Cons a listb ->
|
||||
when listb is
|
||||
Nil -> Nil
|
||||
Cons b newLista ->
|
||||
Cons a (Cons (f b) (toAs f newLista))
|
||||
|
||||
toAs
|
||||
"#
|
||||
),
|
||||
"Attr Shared (Attr Shared (Attr a q -> Attr b p), Attr (* | a | b) (ListA (Attr b p) (Attr a q)) -> Attr * (ConsList (Attr b p)))"
|
||||
);
|
||||
}
|
||||
// #[test]
|
||||
// fn assoc_list_map() {
|
||||
// infer_eq(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// ConsList a : [ Cons a (ConsList a), Nil ]
|
||||
// AssocList a b : ConsList { key: a, value : b }
|
||||
//
|
||||
// map : (k, v -> v2), AssocList k v -> ConsList k v2
|
||||
// map = \f, list ->
|
||||
// when list is
|
||||
// Cons { key, value } xs ->
|
||||
// Cons (f key value) (map f xs)
|
||||
// Nil ->
|
||||
// Nil
|
||||
//
|
||||
// map
|
||||
// "#
|
||||
// ),
|
||||
// "Attr Shared (Attr Shared (Attr a p -> Attr b q), Attr (* | a) (ConsList (Attr a p)) -> Attr * (ConsList (Attr b q)))",
|
||||
// );
|
||||
// }
|
||||
//
|
||||
//
|
||||
// #[test]
|
||||
// fn typecheck_mutually_recursive_tag_union() {
|
||||
// infer_eq(
|
||||
// indoc!(
|
||||
// r#"
|
||||
// ListA a b : [ Cons a (ListB b a), Nil ]
|
||||
// ListB a b : [ Cons a (ListA b a), Nil ]
|
||||
//
|
||||
// ConsList q : [ Cons q (ConsList q), Nil ]
|
||||
//
|
||||
// toAs : (q -> p), ListA p q -> ConsList p
|
||||
// toAs =
|
||||
// \f, lista ->
|
||||
// when lista is
|
||||
// Nil -> Nil
|
||||
// Cons a listb ->
|
||||
// when listb is
|
||||
// Nil -> Nil
|
||||
// Cons b newLista ->
|
||||
// Cons a (Cons (f b) (toAs f newLista))
|
||||
//
|
||||
// foo = \_ ->
|
||||
// x = 4
|
||||
// { a : x, b : x }.a
|
||||
//
|
||||
// toAs foo Nil
|
||||
// "#
|
||||
// ),
|
||||
// "Attr Shared (Attr Shared (Attr a q -> Attr b p), Attr (* | a | b) (ListA (Attr b p) (Attr a q)) -> Attr * (ConsList (Attr b p)))"
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn infer_mutually_recursive_tag_union() {
|
||||
@ -2285,6 +2317,59 @@ mod test_uniq_solve {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hidden_uniqueness_one() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
Model : { foo : Int }
|
||||
|
||||
extract : Model -> Int
|
||||
extract = \{ foo } -> foo
|
||||
|
||||
extract
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr (* | a) Model -> Attr a Int)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hidden_uniqueness_two() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
Model : { foo : Int, bar : Int }
|
||||
|
||||
extract : Model -> Int
|
||||
extract = \{ foo } -> foo
|
||||
|
||||
extract
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr (* | a) Model -> Attr a Int)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hidden_uniqueness_three() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
Model : { foo : Int, bar : Int }
|
||||
|
||||
# extract : { foo : Int, bar : Int } -> Int
|
||||
extract : Model -> Int
|
||||
# extract = \r -> r.foo + r.bar
|
||||
extract = \{foo, bar} -> foo + bar
|
||||
|
||||
extract
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr (* | * | *) Model -> Attr * Int)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peano_roc_is_empty() {
|
||||
infer_eq(
|
||||
@ -2319,7 +2404,7 @@ mod test_uniq_solve {
|
||||
map
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr (* | c | d) (Result (Attr d a) (Attr c e)), Attr * (Attr d a -> Attr f b) -> Attr * (Result (Attr f b) (Attr c e)))"
|
||||
"Attr * (Attr (* | c | d) (Result (Attr c a) (Attr d e)), Attr * (Attr c a -> Attr f b) -> Attr * (Result (Attr f b) (Attr d e)))"
|
||||
);
|
||||
}
|
||||
|
||||
@ -2386,6 +2471,21 @@ mod test_uniq_solve {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_abs_with_annotation() {
|
||||
infer_eq(
|
||||
indoc!(
|
||||
r#"
|
||||
foobar : Int -> Int
|
||||
foobar = \x -> Num.abs x
|
||||
|
||||
foobar
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr * Int -> Attr * Int)",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_addition_without_annotation() {
|
||||
infer_eq(
|
||||
@ -2492,7 +2592,7 @@ mod test_uniq_solve {
|
||||
reconstructPath
|
||||
"#
|
||||
),
|
||||
"Attr Shared (Attr Shared (Map (Attr Shared position) (Attr Shared position)), Attr Shared position -> Attr * (List (Attr Shared position)))"
|
||||
"Attr Shared (Attr Shared (Map (Attr * position) (Attr Shared position)), Attr Shared position -> Attr * (List (Attr Shared position)))"
|
||||
);
|
||||
}
|
||||
|
||||
@ -2508,7 +2608,7 @@ mod test_uniq_solve {
|
||||
, cameFrom : Map.Map position position
|
||||
}
|
||||
|
||||
# cheapestOpen : (position -> Float), Model position -> Result position [ KeyNotFound ]*
|
||||
cheapestOpen : (position -> Float), Model position -> Result position [ KeyNotFound ]*
|
||||
cheapestOpen = \costFunction, model ->
|
||||
|
||||
folder = \position, resSmallestSoFar ->
|
||||
@ -2534,7 +2634,7 @@ mod test_uniq_solve {
|
||||
cheapestOpen
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr * (Attr Shared position -> Attr Shared Float), Attr * (Model (Attr Shared position)) -> Attr * (Result (Attr Shared position) (Attr * [ KeyNotFound ]*)))"
|
||||
"Attr * (Attr * (Attr Shared position -> Attr Shared Float), Attr (* | * | *) (Model (Attr Shared position)) -> Attr * (Result (Attr Shared position) (Attr * [ KeyNotFound ]*)))"
|
||||
)
|
||||
});
|
||||
}
|
||||
@ -2701,7 +2801,7 @@ mod test_uniq_solve {
|
||||
findPath
|
||||
"#
|
||||
),
|
||||
"Attr * (Attr * { costFunction : (Attr Shared (Attr Shared position, Attr Shared position -> Attr Shared Float)), end : (Attr Shared position), moveFunction : (Attr Shared (Attr Shared position -> Attr * (Set (Attr Shared position)))), start : (Attr Shared position) } -> Attr * (Result (Attr * (List (Attr Shared position))) (Attr * [ KeyNotFound ]*)))"
|
||||
"Attr * (Attr * { costFunction : (Attr Shared (Attr Shared position, Attr Shared position -> Attr Shared Float)), end : (Attr Shared position), moveFunction : (Attr Shared (Attr Shared position -> Attr * (Set (Attr * position)))), start : (Attr Shared position) } -> Attr * (Result (Attr * (List (Attr Shared position))) (Attr * [ KeyNotFound ]*)))"
|
||||
)
|
||||
});
|
||||
}
|
||||
|
@ -164,7 +164,16 @@ impl Bool {
|
||||
match self {
|
||||
Bool::Container(cvar, mvars) => {
|
||||
let flattened_mvars = var_to_variables(subs, *cvar, mvars);
|
||||
Bool::Container(*cvar, flattened_mvars)
|
||||
|
||||
// find the parent variable, to remove distinct variables that all have the same
|
||||
// parent. This prevents the signature from rendering as e.g. `( a | b | b)` and
|
||||
// instead makes it `( a | b )`.
|
||||
let parent_mvars = flattened_mvars
|
||||
.into_iter()
|
||||
.map(|v| subs.get_root_key_without_compacting(v))
|
||||
.collect();
|
||||
|
||||
Bool::Container(*cvar, parent_mvars)
|
||||
}
|
||||
Bool::Shared => Bool::Shared,
|
||||
}
|
||||
|
@ -333,6 +333,15 @@ fn write_content(env: &Env, content: Content, subs: &Subs, buf: &mut String, par
|
||||
Parens::InTypeParam,
|
||||
);
|
||||
}
|
||||
|
||||
// useful for debugging
|
||||
let write_out_alias = false;
|
||||
if write_out_alias {
|
||||
buf.push_str("[[ but really ");
|
||||
let content = subs.get_without_compacting(_actual).content;
|
||||
write_content(env, content, subs, buf, parens);
|
||||
buf.push_str("]]");
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -603,7 +612,7 @@ fn write_boolean(env: &Env, boolean: Bool, subs: &Subs, buf: &mut String, parens
|
||||
);
|
||||
}
|
||||
Bool::Container(cvar, mvars) => {
|
||||
let mut buffers_set = ImSet::default();
|
||||
let mut buffers = Vec::with_capacity(mvars.len());
|
||||
for v in mvars {
|
||||
if var_is_shared(subs, v) {
|
||||
continue;
|
||||
@ -617,10 +626,11 @@ fn write_boolean(env: &Env, boolean: Bool, subs: &Subs, buf: &mut String, parens
|
||||
&mut inner_buf,
|
||||
parens,
|
||||
);
|
||||
buffers_set.insert(inner_buf);
|
||||
// buffers_set.insert(inner_buf);
|
||||
buffers.push(inner_buf);
|
||||
}
|
||||
|
||||
let mut buffers: Vec<String> = buffers_set.into_iter().collect();
|
||||
// let mut buffers: Vec<String> = buffers_set.into_iter().collect();
|
||||
buffers.sort();
|
||||
|
||||
let combined = buffers.join(" | ");
|
||||
|
@ -876,13 +876,26 @@ where
|
||||
}
|
||||
|
||||
fn var_to_err_type(subs: &mut Subs, state: &mut ErrorTypeState, var: Variable) -> ErrorType {
|
||||
let desc = subs.get(var);
|
||||
let mut desc = subs.get(var);
|
||||
|
||||
if desc.mark == Mark::OCCURS {
|
||||
ErrorType::Infinite
|
||||
} else {
|
||||
subs.set_mark(var, Mark::OCCURS);
|
||||
|
||||
if false {
|
||||
// useful for debugging
|
||||
match desc.content {
|
||||
Content::FlexVar(_) => {
|
||||
desc.content = Content::FlexVar(Some(format!("{:?}", var).into()));
|
||||
}
|
||||
Content::RigidVar(_) => {
|
||||
desc.content = Content::RigidVar(format!("{:?}", var).into());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let err_type = content_to_err_type(subs, state, var, desc.content);
|
||||
|
||||
subs.set_mark(var, desc.mark);
|
||||
|
@ -79,7 +79,7 @@ impl fmt::Debug for Type {
|
||||
}
|
||||
|
||||
// Sometimes it's useful to see the expansion of the alias
|
||||
write!(f, "[ but actually {:?} ]", _actual)?;
|
||||
// write!(f, "[ but actually {:?} ]", _actual)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -794,7 +794,7 @@ pub enum Mismatch {
|
||||
CanonicalizationProblem,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
pub enum ErrorType {
|
||||
Infinite,
|
||||
Type(Symbol, Vec<ErrorType>),
|
||||
@ -809,6 +809,13 @@ pub enum ErrorType {
|
||||
Error,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ErrorType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// TODO remove clone
|
||||
write!(f, "{:?}", write_debug_error_type(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorType {
|
||||
pub fn unwrap_alias(self) -> ErrorType {
|
||||
match self {
|
||||
@ -925,6 +932,174 @@ fn write_error_type_help(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_debug_error_type(error_type: ErrorType) -> String {
|
||||
let mut buf = String::new();
|
||||
write_debug_error_type_help(error_type, &mut buf, Parens::Unnecessary);
|
||||
|
||||
buf
|
||||
}
|
||||
|
||||
fn write_debug_error_type_help(error_type: ErrorType, buf: &mut String, parens: Parens) {
|
||||
use ErrorType::*;
|
||||
|
||||
match error_type {
|
||||
Infinite => buf.push_str("∞"),
|
||||
Error => buf.push_str("?"),
|
||||
FlexVar(name) => buf.push_str(name.as_str()),
|
||||
RigidVar(name) => buf.push_str(name.as_str()),
|
||||
Type(symbol, arguments) => {
|
||||
let write_parens = parens == Parens::InTypeParam && !arguments.is_empty();
|
||||
|
||||
if write_parens {
|
||||
buf.push('(');
|
||||
}
|
||||
buf.push_str(&format!("{:?}", symbol));
|
||||
|
||||
for arg in arguments {
|
||||
buf.push(' ');
|
||||
|
||||
write_debug_error_type_help(arg, buf, Parens::InTypeParam);
|
||||
}
|
||||
|
||||
if write_parens {
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
Alias(symbol, arguments, _actual) => {
|
||||
let write_parens = parens == Parens::InTypeParam && !arguments.is_empty();
|
||||
|
||||
if write_parens {
|
||||
buf.push('(');
|
||||
}
|
||||
buf.push_str(&format!("{:?}", symbol));
|
||||
|
||||
for arg in arguments {
|
||||
buf.push(' ');
|
||||
|
||||
write_debug_error_type_help(arg.1, buf, Parens::InTypeParam);
|
||||
}
|
||||
|
||||
// useful for debugging
|
||||
let write_out_alias = true;
|
||||
if write_out_alias {
|
||||
buf.push_str("[[ but really ");
|
||||
write_debug_error_type_help(*_actual, buf, Parens::Unnecessary);
|
||||
buf.push_str("]]");
|
||||
}
|
||||
|
||||
if write_parens {
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
Alias(Symbol::NUM_NUM, mut arguments, _actual) => {
|
||||
debug_assert!(arguments.len() == 1);
|
||||
|
||||
let argument = arguments.remove(0).1;
|
||||
|
||||
match argument {
|
||||
Type(Symbol::INT_INTEGER, _) => {
|
||||
buf.push_str("Int");
|
||||
}
|
||||
Type(Symbol::FLOAT_FLOATINGPOINT, _) => {
|
||||
buf.push_str("Float");
|
||||
}
|
||||
other => {
|
||||
let write_parens = parens == Parens::InTypeParam;
|
||||
|
||||
if write_parens {
|
||||
buf.push('(');
|
||||
}
|
||||
buf.push_str("Num ");
|
||||
write_debug_error_type_help(other, buf, Parens::InTypeParam);
|
||||
|
||||
if write_parens {
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Function(arguments, result) => {
|
||||
let write_parens = parens != Parens::Unnecessary;
|
||||
|
||||
if write_parens {
|
||||
buf.push('(');
|
||||
}
|
||||
|
||||
let mut it = arguments.into_iter().peekable();
|
||||
|
||||
while let Some(arg) = it.next() {
|
||||
write_debug_error_type_help(arg, buf, Parens::InFn);
|
||||
if it.peek().is_some() {
|
||||
buf.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
buf.push_str(" -> ");
|
||||
|
||||
write_debug_error_type_help(*result, buf, Parens::InFn);
|
||||
|
||||
if write_parens {
|
||||
buf.push(')');
|
||||
}
|
||||
}
|
||||
Record(fields, ext) => {
|
||||
buf.push('{');
|
||||
|
||||
for (label, content) in fields {
|
||||
buf.push_str(label.as_str());
|
||||
buf.push_str(": ");
|
||||
write_debug_error_type_help(content, buf, Parens::Unnecessary);
|
||||
}
|
||||
|
||||
buf.push('}');
|
||||
write_type_ext(ext, buf);
|
||||
}
|
||||
TagUnion(tags, ext) => {
|
||||
buf.push('[');
|
||||
|
||||
let mut it = tags.into_iter().peekable();
|
||||
|
||||
while let Some((tag, args)) = it.next() {
|
||||
buf.push_str(&format!("{:?}", tag));
|
||||
for arg in args {
|
||||
buf.push_str(" ");
|
||||
write_debug_error_type_help(arg, buf, Parens::InTypeParam);
|
||||
}
|
||||
|
||||
if it.peek().is_some() {
|
||||
buf.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
buf.push(']');
|
||||
write_type_ext(ext, buf);
|
||||
}
|
||||
RecursiveTagUnion(rec, tags, ext) => {
|
||||
buf.push('[');
|
||||
|
||||
for (tag, args) in tags {
|
||||
buf.push_str(&format!("{:?}", tag));
|
||||
for arg in args {
|
||||
buf.push_str(" ");
|
||||
write_debug_error_type_help(arg, buf, Parens::Unnecessary);
|
||||
}
|
||||
}
|
||||
|
||||
buf.push(']');
|
||||
write_type_ext(ext, buf);
|
||||
|
||||
buf.push_str(" as ");
|
||||
|
||||
write_debug_error_type_help(*rec, buf, Parens::Unnecessary);
|
||||
}
|
||||
|
||||
Boolean(boolean_algebra::Bool::Shared) => buf.push_str("Shared"),
|
||||
Boolean(boolean_algebra::Bool::Container(mvar, cvars)) => {
|
||||
buf.push_str(&format!("Container({:?}, {:?})", mvar, cvars))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
pub enum TypeExt {
|
||||
Closed,
|
||||
|
@ -128,7 +128,16 @@ pub fn unify_pool(subs: &mut Subs, pool: &mut Pool, var1: Variable, var2: Variab
|
||||
}
|
||||
|
||||
fn unify_context(subs: &mut Subs, pool: &mut Pool, ctx: Context) -> Outcome {
|
||||
// println!( "{:?} {:?} ~ {:?} {:?}", ctx.first, ctx.first_desc.content, ctx.second, ctx.second_desc.content,);
|
||||
let print_debug_messages = false;
|
||||
if print_debug_messages {
|
||||
let (type1, _problems1) = subs.var_to_error_type(ctx.first);
|
||||
let (type2, _problems2) = subs.var_to_error_type(ctx.second);
|
||||
println!("\n --------------- \n");
|
||||
dbg!(ctx.first, type1);
|
||||
println!("\n --- \n");
|
||||
dbg!(ctx.second, type2);
|
||||
println!("\n --------------- \n");
|
||||
}
|
||||
match &ctx.first_desc.content {
|
||||
FlexVar(opt_name) => unify_flex(subs, pool, &ctx, opt_name, &ctx.second_desc.content),
|
||||
RigidVar(name) => unify_rigid(subs, &ctx, name, &ctx.second_desc.content),
|
||||
@ -218,7 +227,8 @@ fn unify_structure(
|
||||
}
|
||||
RigidVar(name) => {
|
||||
// Type mismatch! Rigid can only unify with flex.
|
||||
mismatch!("trying to unify {:?} with rigid var {:?}", &flat_type, name)
|
||||
mismatch!("trying to unify {:?} with rigid var {:?}", &flat_type, name);
|
||||
panic!()
|
||||
}
|
||||
|
||||
Structure(ref other_flat_type) => {
|
||||
|
Loading…
Reference in New Issue
Block a user