diff --git a/editor/src/lang/constrain.rs b/editor/src/lang/constrain.rs index f9ae771a86..14ab80bb69 100644 --- a/editor/src/lang/constrain.rs +++ b/editor/src/lang/constrain.rs @@ -9,7 +9,7 @@ use crate::lang::{ use roc_can::expected::Expected; use roc_collections::all::{BumpMap, BumpMapDefault, Index}; -use roc_module::symbol::Symbol; +use roc_module::{ident::TagName, symbol::Symbol}; use roc_region::all::{Located, Region}; use roc_types::{ subs::Variable, @@ -216,6 +216,68 @@ pub fn constrain_expr<'a>( exists(arena, field_vars, And(constraints)) } } + Expr2::GlobalTag { + variant_var, + ext_var, + name, + arguments, + } => { + let mut flex_vars = BumpVec::with_capacity_in(arguments.len(), arena); + let types = PoolVec::with_capacity(arguments.len() as u32, env.pool); + let mut arg_cons = BumpVec::with_capacity_in(arguments.len(), arena); + + for (argument_node_id, type_node_id) in + arguments.iter_node_ids().zip(types.iter_node_ids()) + { + let (var, expr_node_id) = env.pool.get(argument_node_id); + + let argument_expr = env.pool.get(*expr_node_id); + + let arg_con = constrain_expr( + arena, + env, + argument_expr, + Expected::NoExpectation(Type2::Variable(*var)), + region, + ); + + arg_cons.push(arg_con); + flex_vars.push(*var); + + env.pool[type_node_id] = Type2::Variable(*var); + } + + let members = PoolVec::with_capacity(1, env.pool); + + for (member_node_id, member) in members.iter_node_ids().zip(vec![(*name, types)]) { + env.pool[member_node_id] = member; + } + + let union_con = Eq( + Type2::TagUnion(members, env.pool.add(Type2::Variable(*ext_var))), + expected.shallow_clone(), + Category::TagApply { + tag_name: TagName::Global(name.as_str(env.pool).into()), + args_count: arguments.len(), + }, + region, + ); + + let ast_con = Eq( + Type2::Variable(*variant_var), + expected, + Category::Storage(std::file!(), std::line!()), + region, + ); + + flex_vars.push(*variant_var); + flex_vars.push(*ext_var); + + arg_cons.push(union_con); + arg_cons.push(ast_con); + + exists(arena, flex_vars, And(arg_cons)) + } _ => todo!("implement constaints for {:?}", expr), } } diff --git a/editor/src/lang/solve.rs b/editor/src/lang/solve.rs index 3d7118e4f4..b50b9d4300 100644 --- a/editor/src/lang/solve.rs +++ b/editor/src/lang/solve.rs @@ -826,7 +826,7 @@ fn type_to_variable<'a>( let mut tag_vars = MutMap::default(); let ext = mempool.get(*ext_id); - for (_tag, tag_argument_types) in tags.iter(mempool) { + for (tag, tag_argument_types) in tags.iter(mempool) { let mut tag_argument_vars = Vec::with_capacity(tag_argument_types.len()); for arg_type in tag_argument_types.iter(mempool) { @@ -836,7 +836,7 @@ fn type_to_variable<'a>( } tag_vars.insert( - roc_module::ident::TagName::Private(Symbol::NUM_NUM), + roc_module::ident::TagName::Global(tag.as_str(mempool).into()), tag_argument_vars, ); } diff --git a/editor/tests/solve_expr2.rs b/editor/tests/solve_expr2.rs index 8faa4bcacb..f162f3e577 100644 --- a/editor/tests/solve_expr2.rs +++ b/editor/tests/solve_expr2.rs @@ -238,3 +238,15 @@ fn constrain_list_of_records() { "List { x : Num * }", ) } + +#[test] +fn constrain_global_tag() { + infer_eq( + indoc!( + r#" + Foo + "# + ), + "[ Foo ]*", + ) +}