mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
we are compiling
This commit is contained in:
parent
01a7fe77d4
commit
a4889fd571
6 changed files with 406 additions and 297 deletions
|
@ -1,5 +1,6 @@
|
||||||
use crate::expected::{Expected, PExpected};
|
use crate::expected::{Expected, PExpected};
|
||||||
use roc_collections::soa::{Index, Slice};
|
use roc_collections::soa::{Index, Slice};
|
||||||
|
use roc_module::ident::TagName;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::{Loc, Region};
|
use roc_region::all::{Loc, Region};
|
||||||
use roc_types::types::{Category, PatternCategory, Type};
|
use roc_types::types::{Category, PatternCategory, Type};
|
||||||
|
@ -15,6 +16,7 @@ pub struct Constraints {
|
||||||
pattern_categories: Vec<PatternCategory>,
|
pattern_categories: Vec<PatternCategory>,
|
||||||
expectations: Vec<Expected<Type>>,
|
expectations: Vec<Expected<Type>>,
|
||||||
pattern_expectations: Vec<PExpected<Type>>,
|
pattern_expectations: Vec<PExpected<Type>>,
|
||||||
|
includes_tags: Vec<IncludesTag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Constraints {
|
impl Constraints {
|
||||||
|
@ -52,13 +54,9 @@ impl Constraints {
|
||||||
category: Category,
|
category: Category,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let type_index = Index::new(self.types.len() as _);
|
let type_index = Index::push_new(&mut self.types, typ);
|
||||||
let expected_index = Index::new(self.expectations.len() as _);
|
let expected_index = Index::push_new(&mut self.expectations, expected);
|
||||||
let category_index = Index::new(self.categories.len() as _);
|
let category_index = Index::push_new(&mut self.categories, category);
|
||||||
|
|
||||||
self.types.push(typ);
|
|
||||||
self.expectations.push(expected);
|
|
||||||
self.categories.push(category);
|
|
||||||
|
|
||||||
Constraint::Eq(type_index, expected_index, category_index, region)
|
Constraint::Eq(type_index, expected_index, category_index, region)
|
||||||
}
|
}
|
||||||
|
@ -70,17 +68,61 @@ impl Constraints {
|
||||||
category: PatternCategory,
|
category: PatternCategory,
|
||||||
region: Region,
|
region: Region,
|
||||||
) -> Constraint {
|
) -> Constraint {
|
||||||
let type_index = Index::new(self.types.len() as _);
|
let type_index = Index::push_new(&mut self.types, typ);
|
||||||
let expected_index = Index::new(self.pattern_expectations.len() as _);
|
let expected_index = Index::push_new(&mut self.pattern_expectations, expected);
|
||||||
let category_index = Index::new(self.pattern_categories.len() as _);
|
let category_index = Index::push_new(&mut self.pattern_categories, category);
|
||||||
|
|
||||||
self.types.push(typ);
|
|
||||||
self.pattern_expectations.push(expected);
|
|
||||||
self.pattern_categories.push(category);
|
|
||||||
|
|
||||||
Constraint::Pattern(type_index, expected_index, category_index, region)
|
Constraint::Pattern(type_index, expected_index, category_index, region)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pattern_presence(
|
||||||
|
&mut self,
|
||||||
|
typ: Type,
|
||||||
|
expected: PExpected<Type>,
|
||||||
|
category: PatternCategory,
|
||||||
|
region: Region,
|
||||||
|
) -> Constraint {
|
||||||
|
let type_index = Index::push_new(&mut self.types, typ);
|
||||||
|
let expected_index = Index::push_new(&mut self.pattern_expectations, expected);
|
||||||
|
let category_index = Index::push_new(&mut self.pattern_categories, category);
|
||||||
|
|
||||||
|
Constraint::PatternPresence(type_index, expected_index, category_index, region)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_open_type(&mut self, typ: Type) -> Constraint {
|
||||||
|
let type_index = Index::push_new(&mut self.types, typ);
|
||||||
|
|
||||||
|
Constraint::IsOpenType(type_index)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn includes_tag<I>(
|
||||||
|
&mut self,
|
||||||
|
typ: Type,
|
||||||
|
tag_name: TagName,
|
||||||
|
types: I,
|
||||||
|
category: PatternCategory,
|
||||||
|
region: Region,
|
||||||
|
) -> Constraint
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Type>,
|
||||||
|
{
|
||||||
|
let type_index = Index::push_new(&mut self.types, typ);
|
||||||
|
let category_index = Index::push_new(&mut self.pattern_categories, category);
|
||||||
|
let types_slice = Slice::extend_new(&mut self.types, types);
|
||||||
|
|
||||||
|
let includes_tag = IncludesTag {
|
||||||
|
type_index,
|
||||||
|
tag_name,
|
||||||
|
types: types_slice,
|
||||||
|
pattern_category: category_index,
|
||||||
|
region,
|
||||||
|
};
|
||||||
|
|
||||||
|
let includes_tag_index = Index::push_new(&mut self.includes_tags, includes_tag);
|
||||||
|
|
||||||
|
Constraint::IncludesTag(includes_tag_index)
|
||||||
|
}
|
||||||
|
|
||||||
fn variable_slice<I>(&mut self, it: I) -> Slice<Variable>
|
fn variable_slice<I>(&mut self, it: I) -> Slice<Variable>
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Variable>,
|
I: IntoIterator<Item = Variable>,
|
||||||
|
@ -133,6 +175,29 @@ impl Constraints {
|
||||||
Constraint::Let(let_index)
|
Constraint::Let(let_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exists_many<I, C>(&mut self, flex_vars: I, defs_constraint: C) -> Constraint
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Variable>,
|
||||||
|
C: IntoIterator<Item = Constraint>,
|
||||||
|
{
|
||||||
|
let defs_and_ret_constraint = Index::new(self.constraints.len() as _);
|
||||||
|
|
||||||
|
self.and_constraint(defs_constraint);
|
||||||
|
self.constraints.push(Constraint::True);
|
||||||
|
|
||||||
|
let let_contraint = LetConstraint {
|
||||||
|
rigid_vars: Slice::default(),
|
||||||
|
flex_vars: self.variable_slice(flex_vars),
|
||||||
|
def_types: Slice::default(),
|
||||||
|
defs_and_ret_constraint,
|
||||||
|
};
|
||||||
|
|
||||||
|
let let_index = Index::new(self.let_constraints.len() as _);
|
||||||
|
self.let_constraints.push(let_contraint);
|
||||||
|
|
||||||
|
Constraint::Let(let_index)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn let_constraint<I1, I2, I3>(
|
pub fn let_constraint<I1, I2, I3>(
|
||||||
&mut self,
|
&mut self,
|
||||||
rigid_vars: I1,
|
rigid_vars: I1,
|
||||||
|
@ -191,7 +256,7 @@ impl Constraints {
|
||||||
region,
|
region,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub fn contains_save_the_environment(&self, constraint: Constraint) -> bool {
|
pub fn contains_save_the_environment(&self, constraint: &Constraint) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +293,15 @@ pub enum Constraint {
|
||||||
SaveTheEnvironment,
|
SaveTheEnvironment,
|
||||||
Let(Index<LetConstraint>),
|
Let(Index<LetConstraint>),
|
||||||
And(Slice<Constraint>),
|
And(Slice<Constraint>),
|
||||||
|
/// Presence constraints
|
||||||
|
IsOpenType(Index<Type>), // Theory; always applied to a variable? if yes the use that
|
||||||
|
IncludesTag(Index<IncludesTag>),
|
||||||
|
PatternPresence(
|
||||||
|
Index<Type>,
|
||||||
|
Index<PExpected<Type>>,
|
||||||
|
Index<PatternCategory>,
|
||||||
|
Region,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -237,3 +311,12 @@ pub struct LetConstraint {
|
||||||
pub def_types: Slice<(Symbol, Loc<Type>)>,
|
pub def_types: Slice<(Symbol, Loc<Type>)>,
|
||||||
pub defs_and_ret_constraint: Index<(Constraint, Constraint)>,
|
pub defs_and_ret_constraint: Index<(Constraint, Constraint)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct IncludesTag {
|
||||||
|
pub type_index: Index<Type>,
|
||||||
|
pub tag_name: TagName,
|
||||||
|
pub types: Slice<Type>,
|
||||||
|
pub pattern_category: Index<PatternCategory>,
|
||||||
|
pub region: Region,
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,19 @@ impl<T> Slice<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn extend_new<I>(vector: &mut Vec<T>, values: I) -> Slice<T>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = T>,
|
||||||
|
{
|
||||||
|
let start = vector.len() as u32;
|
||||||
|
|
||||||
|
vector.extend(values);
|
||||||
|
|
||||||
|
let end = vector.len() as u32;
|
||||||
|
|
||||||
|
Self::new(start, (end - start) as u16)
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn len(&self) -> usize {
|
pub const fn len(&self) -> usize {
|
||||||
self.length as _
|
self.length as _
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,8 @@ pub fn add_numeric_bound_constr_soa(
|
||||||
1 => {
|
1 => {
|
||||||
let actual_type = Variable(range[0]);
|
let actual_type = Variable(range[0]);
|
||||||
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
|
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
|
||||||
let because_suffix = constraints.equal_types(actual_type, expected, category, region);
|
let because_suffix =
|
||||||
|
constraints.equal_types(total_num_type.clone(), expected, category, region);
|
||||||
|
|
||||||
num_constraints.extend([because_suffix]);
|
num_constraints.extend([because_suffix]);
|
||||||
|
|
||||||
|
|
|
@ -411,23 +411,17 @@ pub fn constrain_expr(
|
||||||
&mut vars,
|
&mut vars,
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.exists(
|
let pattern_state_constraints = constraints.and_constraint(pattern_state.constraints);
|
||||||
vars,
|
let cons = [
|
||||||
constraints.and_constraint([
|
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
Vec::new(),
|
[],
|
||||||
pattern_state.vars,
|
pattern_state.vars,
|
||||||
pattern_state.headers,
|
pattern_state.headers,
|
||||||
constraints.and_constraint(pattern_state.constraints),
|
pattern_state_constraints,
|
||||||
ret_constraint,
|
ret_constraint,
|
||||||
),
|
),
|
||||||
// "the closure's type is equal to expected type"
|
// "the closure's type is equal to expected type"
|
||||||
constraints.equal_types(
|
constraints.equal_types(function_type.clone(), expected, Category::Lambda, region),
|
||||||
function_type.clone(),
|
|
||||||
expected,
|
|
||||||
Category::Lambda,
|
|
||||||
region,
|
|
||||||
),
|
|
||||||
// "fn_var is equal to the closure's type" - fn_var is used in code gen
|
// "fn_var is equal to the closure's type" - fn_var is used in code gen
|
||||||
constraints.equal_types(
|
constraints.equal_types(
|
||||||
Type::Variable(*fn_var),
|
Type::Variable(*fn_var),
|
||||||
|
@ -436,8 +430,9 @@ pub fn constrain_expr(
|
||||||
region,
|
region,
|
||||||
),
|
),
|
||||||
closure_constraint,
|
closure_constraint,
|
||||||
]),
|
];
|
||||||
)
|
|
||||||
|
constraints.exists_many(vars, cons)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(loc_cond, continuation) => {
|
Expect(loc_cond, continuation) => {
|
||||||
|
@ -462,7 +457,7 @@ pub fn constrain_expr(
|
||||||
expected,
|
expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.exists([], constraints.and_constraint([cond_con, continuation_con]))
|
constraints.exists_many([], [cond_con, continuation_con])
|
||||||
}
|
}
|
||||||
|
|
||||||
If {
|
If {
|
||||||
|
@ -548,10 +543,7 @@ pub fn constrain_expr(
|
||||||
branch_cons.push(ast_con);
|
branch_cons.push(ast_con);
|
||||||
branch_cons.push(else_con);
|
branch_cons.push(else_con);
|
||||||
|
|
||||||
constraints.exists(
|
constraints.exists_many([*cond_var, *branch_var], branch_cons)
|
||||||
[*cond_var, *branch_var],
|
|
||||||
constraints.and_constraint(branch_cons),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
for (index, (loc_cond, loc_body)) in branches.iter().enumerate() {
|
for (index, (loc_cond, loc_body)) in branches.iter().enumerate() {
|
||||||
|
@ -604,10 +596,7 @@ pub fn constrain_expr(
|
||||||
));
|
));
|
||||||
branch_cons.push(else_con);
|
branch_cons.push(else_con);
|
||||||
|
|
||||||
constraints.exists(
|
constraints.exists_many([*cond_var, *branch_var], branch_cons)
|
||||||
[*cond_var, *branch_var],
|
|
||||||
constraints.and_constraint(branch_cons),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -677,10 +666,7 @@ pub fn constrain_expr(
|
||||||
region,
|
region,
|
||||||
));
|
));
|
||||||
|
|
||||||
return constraints.exists(
|
return constraints.exists_many([cond_var, *expr_var], branch_constraints);
|
||||||
[cond_var, *expr_var],
|
|
||||||
constraints.and_constraint(branch_constraints),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -691,6 +677,7 @@ pub fn constrain_expr(
|
||||||
let pattern_region =
|
let pattern_region =
|
||||||
Region::across_all(when_branch.patterns.iter().map(|v| &v.region));
|
Region::across_all(when_branch.patterns.iter().map(|v| &v.region));
|
||||||
let branch_con = constrain_when_branch(
|
let branch_con = constrain_when_branch(
|
||||||
|
constraints,
|
||||||
env,
|
env,
|
||||||
region,
|
region,
|
||||||
when_branch,
|
when_branch,
|
||||||
|
@ -713,23 +700,26 @@ pub fn constrain_expr(
|
||||||
branch_cons.push(branch_con);
|
branch_cons.push(branch_con);
|
||||||
}
|
}
|
||||||
|
|
||||||
branch_constraints.push(constraints.and_constraint([
|
// Deviation: elm adds another layer of And nesting
|
||||||
|
//
|
||||||
// Record the original conditional expression's constraint.
|
// Record the original conditional expression's constraint.
|
||||||
// Each branch's pattern must have the same type
|
// Each branch's pattern must have the same type
|
||||||
// as the condition expression did.
|
// as the condition expression did.
|
||||||
constraints.and_constraint(branch_cons),
|
//
|
||||||
// The return type of each branch must equal
|
// The return type of each branch must equal the return type of
|
||||||
// the return type of the entire when-expression.
|
// the entire when-expression.
|
||||||
constraints.equal_types(branch_type, expected, Category::When, region),
|
branch_cons.push(constraints.equal_types(
|
||||||
]));
|
branch_type,
|
||||||
|
expected,
|
||||||
|
Category::When,
|
||||||
|
region,
|
||||||
|
));
|
||||||
|
branch_constraints.push(constraints.and_constraint(branch_cons));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// exhautiveness checking happens when converting to mono::Expr
|
// exhautiveness checking happens when converting to mono::Expr
|
||||||
constraints.exists(
|
constraints.exists_many([cond_var, *expr_var], branch_constraints)
|
||||||
[cond_var, *expr_var],
|
|
||||||
constraints.and_constraint(branch_constraints),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Access {
|
Access {
|
||||||
record_var,
|
record_var,
|
||||||
|
@ -771,13 +761,10 @@ pub fn constrain_expr(
|
||||||
record_expected,
|
record_expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.exists(
|
let eq = constraints.equal_types(field_type, expected, category, region);
|
||||||
|
constraints.exists_many(
|
||||||
[*record_var, field_var, ext_var],
|
[*record_var, field_var, ext_var],
|
||||||
constraints.and_constraint([
|
[constraint, eq, record_con],
|
||||||
constraint,
|
|
||||||
constraints.equal_types(field_type, expected, category, region),
|
|
||||||
record_con,
|
|
||||||
]),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Accessor {
|
Accessor {
|
||||||
|
@ -820,15 +807,8 @@ pub fn constrain_expr(
|
||||||
Box::new(field_type),
|
Box::new(field_type),
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.exists(
|
let cons = [
|
||||||
[*record_var, *function_var, *closure_var, field_var, ext_var],
|
constraints.equal_types(function_type.clone(), expected, category.clone(), region),
|
||||||
constraints.and_constraint([
|
|
||||||
constraints.equal_types(
|
|
||||||
function_type.clone(),
|
|
||||||
expected,
|
|
||||||
category.clone(),
|
|
||||||
region,
|
|
||||||
),
|
|
||||||
constraints.equal_types(
|
constraints.equal_types(
|
||||||
function_type,
|
function_type,
|
||||||
NoExpectation(Variable(*function_var)),
|
NoExpectation(Variable(*function_var)),
|
||||||
|
@ -836,7 +816,11 @@ pub fn constrain_expr(
|
||||||
region,
|
region,
|
||||||
),
|
),
|
||||||
record_con,
|
record_con,
|
||||||
]),
|
];
|
||||||
|
|
||||||
|
constraints.exists_many(
|
||||||
|
[*record_var, *function_var, *closure_var, field_var, ext_var],
|
||||||
|
cons,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
LetRec(defs, loc_ret, var) => {
|
LetRec(defs, loc_ret, var) => {
|
||||||
|
@ -848,10 +832,8 @@ pub fn constrain_expr(
|
||||||
expected.clone(),
|
expected.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.exists(
|
let cons = [
|
||||||
[*var],
|
constrain_recursive_defs(constraints, env, defs, body_con),
|
||||||
constraints.and_constraint([
|
|
||||||
constrain_recursive_defs(env, defs, body_con),
|
|
||||||
// Record the type of tne entire def-expression in the variable.
|
// Record the type of tne entire def-expression in the variable.
|
||||||
// Code gen will need that later!
|
// Code gen will need that later!
|
||||||
constraints.equal_types(
|
constraints.equal_types(
|
||||||
|
@ -860,8 +842,9 @@ pub fn constrain_expr(
|
||||||
Category::Storage(std::file!(), std::line!()),
|
Category::Storage(std::file!(), std::line!()),
|
||||||
loc_ret.region,
|
loc_ret.region,
|
||||||
),
|
),
|
||||||
]),
|
];
|
||||||
)
|
|
||||||
|
constraints.exists_many([*var], cons)
|
||||||
}
|
}
|
||||||
LetNonRec(def, loc_ret, var) => {
|
LetNonRec(def, loc_ret, var) => {
|
||||||
let mut stack = Vec::with_capacity(1);
|
let mut stack = Vec::with_capacity(1);
|
||||||
|
@ -884,10 +867,8 @@ pub fn constrain_expr(
|
||||||
);
|
);
|
||||||
|
|
||||||
while let Some((def, var, ret_region)) = stack.pop() {
|
while let Some((def, var, ret_region)) = stack.pop() {
|
||||||
body_con = constraints.exists(
|
let cons = [
|
||||||
[*var],
|
constrain_def(constraints, env, def, body_con),
|
||||||
constraints.and_constraint([
|
|
||||||
constrain_def(env, def, body_con),
|
|
||||||
// Record the type of the entire def-expression in the variable.
|
// Record the type of the entire def-expression in the variable.
|
||||||
// Code gen will need that later!
|
// Code gen will need that later!
|
||||||
constraints.equal_types(
|
constraints.equal_types(
|
||||||
|
@ -896,8 +877,9 @@ pub fn constrain_expr(
|
||||||
Category::Storage(std::file!(), std::line!()),
|
Category::Storage(std::file!(), std::line!()),
|
||||||
ret_region,
|
ret_region,
|
||||||
),
|
),
|
||||||
]),
|
];
|
||||||
)
|
|
||||||
|
body_con = constraints.exists_many([*var], cons)
|
||||||
}
|
}
|
||||||
|
|
||||||
body_con
|
body_con
|
||||||
|
@ -950,7 +932,7 @@ pub fn constrain_expr(
|
||||||
arg_cons.push(union_con);
|
arg_cons.push(union_con);
|
||||||
arg_cons.push(ast_con);
|
arg_cons.push(ast_con);
|
||||||
|
|
||||||
constraints.exists(vars, constraints.and_constraint(arg_cons))
|
constraints.exists_many(vars, arg_cons)
|
||||||
}
|
}
|
||||||
ZeroArgumentTag {
|
ZeroArgumentTag {
|
||||||
variant_var,
|
variant_var,
|
||||||
|
@ -1002,7 +984,7 @@ pub fn constrain_expr(
|
||||||
arg_cons.push(union_con);
|
arg_cons.push(union_con);
|
||||||
arg_cons.push(ast_con);
|
arg_cons.push(ast_con);
|
||||||
|
|
||||||
constraints.exists(vars, constraints.and_constraint(arg_cons))
|
constraints.exists_many(vars, arg_cons)
|
||||||
}
|
}
|
||||||
|
|
||||||
OpaqueRef {
|
OpaqueRef {
|
||||||
|
@ -1069,9 +1051,9 @@ pub fn constrain_expr(
|
||||||
v.0.expect_variable("all lambda sets should be fresh variables here")
|
v.0.expect_variable("all lambda sets should be fresh variables here")
|
||||||
}));
|
}));
|
||||||
|
|
||||||
constraints.exists(
|
constraints.exists_many(
|
||||||
vars,
|
vars,
|
||||||
constraints.and([arg_con, opaque_con, link_type_variables_con, storage_con]),
|
[arg_con, opaque_con, link_type_variables_con, storage_con],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,12 +1091,8 @@ pub fn constrain_expr(
|
||||||
|
|
||||||
let category = Category::LowLevelOpResult(*op);
|
let category = Category::LowLevelOpResult(*op);
|
||||||
|
|
||||||
constraints.exists(
|
let eq = constraints.equal_types(ret_type, expected, category, region);
|
||||||
vars,
|
constraints.exists_many(vars, arg_cons.into_iter().chain(std::iter::once(eq)))
|
||||||
constraints.and_constraint(arg_cons.into_iter().chain(std::iter::once(
|
|
||||||
constraints.equal_types(ret_type, expected, category, region),
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ForeignCall {
|
ForeignCall {
|
||||||
args,
|
args,
|
||||||
|
@ -1154,12 +1132,8 @@ pub fn constrain_expr(
|
||||||
|
|
||||||
let category = Category::ForeignCall;
|
let category = Category::ForeignCall;
|
||||||
|
|
||||||
constraints.exists(
|
let eq = constraints.equal_types(ret_type, expected, category, region);
|
||||||
vars,
|
constraints.exists_many(vars, arg_cons.into_iter().chain(std::iter::once(eq)))
|
||||||
constraints.and_constraint(arg_cons.into_iter().chain(std::iter::once(
|
|
||||||
constraints.equal_types(ret_type, expected, category, region),
|
|
||||||
))),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
RuntimeError(_) => {
|
RuntimeError(_) => {
|
||||||
// Runtime Errors have no constraints because they're going to crash.
|
// Runtime Errors have no constraints because they're going to crash.
|
||||||
|
@ -1195,6 +1169,7 @@ fn constrain_when_branch(
|
||||||
// then unify that variable with the expectation?
|
// then unify that variable with the expectation?
|
||||||
for loc_pattern in &when_branch.patterns {
|
for loc_pattern in &when_branch.patterns {
|
||||||
constrain_pattern(
|
constrain_pattern(
|
||||||
|
constraints,
|
||||||
env,
|
env,
|
||||||
&loc_pattern.value,
|
&loc_pattern.value,
|
||||||
loc_pattern.region,
|
loc_pattern.region,
|
||||||
|
@ -1217,25 +1192,23 @@ fn constrain_when_branch(
|
||||||
);
|
);
|
||||||
|
|
||||||
// must introduce the headers from the pattern before constraining the guard
|
// must introduce the headers from the pattern before constraining the guard
|
||||||
constraints.let_constraint(
|
let state_constraints = constraints.and_constraint(state.constraints);
|
||||||
[],
|
let inner = constraints.let_constraint(
|
||||||
state.vars,
|
|
||||||
state.headers,
|
|
||||||
constraints.and_constraint(state.constraints),
|
|
||||||
constraints.let_constraint(
|
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
SendMap::default(),
|
SendMap::default(),
|
||||||
guard_constraint,
|
guard_constraint,
|
||||||
ret_constraint,
|
ret_constraint,
|
||||||
),
|
);
|
||||||
)
|
|
||||||
|
constraints.let_constraint([], state.vars, state.headers, state_constraints, inner)
|
||||||
} else {
|
} else {
|
||||||
|
let state_constraints = constraints.and_constraint(state.constraints);
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
[],
|
[],
|
||||||
state.vars,
|
state.vars,
|
||||||
state.headers,
|
state.headers,
|
||||||
constraints.and_constraint(state.constraints),
|
state_constraints,
|
||||||
ret_constraint,
|
ret_constraint,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1300,7 +1273,7 @@ pub fn constrain_decls(
|
||||||
constraint = constrain_def(constraints, &env, def, constraint);
|
constraint = constrain_def(constraints, &env, def, constraint);
|
||||||
}
|
}
|
||||||
Declaration::DeclareRec(defs) => {
|
Declaration::DeclareRec(defs) => {
|
||||||
constraint = constrain_recursive_defs(&env, defs, constraint);
|
constraint = constrain_recursive_defs(constraints, &env, defs, constraint);
|
||||||
}
|
}
|
||||||
Declaration::InvalidCycle(_) => {
|
Declaration::InvalidCycle(_) => {
|
||||||
// invalid cycles give a canonicalization error. we skip them here.
|
// invalid cycles give a canonicalization error. we skip them here.
|
||||||
|
@ -1310,7 +1283,7 @@ pub fn constrain_decls(
|
||||||
}
|
}
|
||||||
|
|
||||||
// this assert make the "root" of the constraint wasn't dropped
|
// this assert make the "root" of the constraint wasn't dropped
|
||||||
debug_assert!(constraints.contains_save_the_environment(constraint));
|
debug_assert!(constraints.contains_save_the_environment(&constraint));
|
||||||
|
|
||||||
constraint
|
constraint
|
||||||
}
|
}
|
||||||
|
@ -1484,6 +1457,7 @@ fn constrain_def(
|
||||||
}
|
}
|
||||||
|
|
||||||
let closure_constraint = constrain_closure_size(
|
let closure_constraint = constrain_closure_size(
|
||||||
|
constraints,
|
||||||
*name,
|
*name,
|
||||||
region,
|
region,
|
||||||
captured_symbols,
|
captured_symbols,
|
||||||
|
@ -1512,9 +1486,7 @@ fn constrain_def(
|
||||||
vars.push(*fn_var);
|
vars.push(*fn_var);
|
||||||
let defs_constraint = constraints.and_constraint(state.constraints);
|
let defs_constraint = constraints.and_constraint(state.constraints);
|
||||||
|
|
||||||
constraints.exists(
|
let cons = [
|
||||||
vars,
|
|
||||||
constraints.and_constraint([
|
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
[],
|
[],
|
||||||
state.vars,
|
state.vars,
|
||||||
|
@ -1535,17 +1507,14 @@ fn constrain_def(
|
||||||
Category::ClosureSize,
|
Category::ClosureSize,
|
||||||
region,
|
region,
|
||||||
),
|
),
|
||||||
constraints.store(
|
constraints.store(signature.clone(), *fn_var, std::file!(), std::line!()),
|
||||||
signature.clone(),
|
|
||||||
*fn_var,
|
|
||||||
std::file!(),
|
|
||||||
std::line!(),
|
|
||||||
),
|
|
||||||
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
||||||
constraints.store(ret_type, ret_var, std::file!(), std::line!()),
|
constraints.store(ret_type, ret_var, std::file!(), std::line!()),
|
||||||
closure_constraint,
|
closure_constraint,
|
||||||
]),
|
];
|
||||||
)
|
|
||||||
|
let and_constraint = constraints.and_constraint(cons);
|
||||||
|
constraints.exists(vars, and_constraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1559,7 +1528,7 @@ fn constrain_def(
|
||||||
expected,
|
expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
constraints.and_constraint([
|
let cons = [
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
|
@ -1569,7 +1538,8 @@ fn constrain_def(
|
||||||
),
|
),
|
||||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||||
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
||||||
])
|
];
|
||||||
|
constraints.and_constraint(cons)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1586,17 +1556,21 @@ fn constrain_def(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let and_constraint = constraints.and_constraint(def_pattern_state.constraints);
|
||||||
|
|
||||||
|
let def_con = constraints.let_constraint(
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
SendMap::default(), // empty, because our functions have no arguments!
|
||||||
|
and_constraint,
|
||||||
|
expr_con,
|
||||||
|
);
|
||||||
|
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
new_rigids,
|
new_rigids,
|
||||||
def_pattern_state.vars,
|
def_pattern_state.vars,
|
||||||
def_pattern_state.headers,
|
def_pattern_state.headers,
|
||||||
constraints.let_constraint(
|
def_con,
|
||||||
[],
|
|
||||||
[],
|
|
||||||
SendMap::default(), // empty, because our functions have no arguments!
|
|
||||||
constraints.and_constraint(def_pattern_state.constraints),
|
|
||||||
expr_con,
|
|
||||||
),
|
|
||||||
body_con,
|
body_con,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1706,8 +1680,14 @@ fn instantiate_rigids(
|
||||||
annotation
|
annotation
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constrain_recursive_defs(env: &Env, defs: &[Def], body_con: Constraint) -> Constraint {
|
fn constrain_recursive_defs(
|
||||||
|
constraints: &mut Constraints,
|
||||||
|
env: &Env,
|
||||||
|
defs: &[Def],
|
||||||
|
body_con: Constraint,
|
||||||
|
) -> Constraint {
|
||||||
rec_defs_help(
|
rec_defs_help(
|
||||||
|
constraints,
|
||||||
env,
|
env,
|
||||||
defs,
|
defs,
|
||||||
body_con,
|
body_con,
|
||||||
|
@ -1897,14 +1877,13 @@ pub fn rec_defs_help(
|
||||||
|
|
||||||
vars.push(*fn_var);
|
vars.push(*fn_var);
|
||||||
|
|
||||||
let def_con = constraints.exists(
|
let state_constraints = constraints.and_constraint(state.constraints);
|
||||||
vars,
|
let cons = [
|
||||||
constraints.and_constraint([
|
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
[],
|
[],
|
||||||
state.vars,
|
state.vars,
|
||||||
state.headers,
|
state.headers,
|
||||||
constraints.and_constraint(state.constraints),
|
state_constraints,
|
||||||
expr_con,
|
expr_con,
|
||||||
),
|
),
|
||||||
constraints.equal_types(
|
constraints.equal_types(
|
||||||
|
@ -1924,8 +1903,10 @@ pub fn rec_defs_help(
|
||||||
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
||||||
constraints.store(ret_type, ret_var, std::file!(), std::line!()),
|
constraints.store(ret_type, ret_var, std::file!(), std::line!()),
|
||||||
closure_constraint,
|
closure_constraint,
|
||||||
]),
|
];
|
||||||
);
|
|
||||||
|
let and_constraint = constraints.and_constraint(cons);
|
||||||
|
let def_con = constraints.exists(vars, and_constraint);
|
||||||
|
|
||||||
rigid_info.vars.extend(&new_rigids);
|
rigid_info.vars.extend(&new_rigids);
|
||||||
|
|
||||||
|
@ -1949,7 +1930,7 @@ pub fn rec_defs_help(
|
||||||
expected,
|
expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
let def_con = constraints.and_constraint([
|
let cons = [
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
|
@ -1959,7 +1940,8 @@ pub fn rec_defs_help(
|
||||||
),
|
),
|
||||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||||
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
constraints.store(signature, expr_var, std::file!(), std::line!()),
|
||||||
]);
|
];
|
||||||
|
let def_con = constraints.and_constraint(cons);
|
||||||
|
|
||||||
rigid_info.vars.extend(&new_rigids);
|
rigid_info.vars.extend(&new_rigids);
|
||||||
|
|
||||||
|
@ -1977,25 +1959,36 @@ pub fn rec_defs_help(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let flex_constraints = constraints.and_constraint(flex_info.constraints);
|
||||||
|
let inner_inner = constraints.let_constraint(
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
flex_info.def_types.clone(),
|
||||||
|
Constraint::True,
|
||||||
|
flex_constraints,
|
||||||
|
);
|
||||||
|
|
||||||
|
let rigid_constraints = {
|
||||||
|
let mut temp = rigid_info.constraints;
|
||||||
|
temp.push(body_con);
|
||||||
|
|
||||||
|
constraints.and_constraint(temp)
|
||||||
|
};
|
||||||
|
|
||||||
|
let inner = constraints.let_constraint(
|
||||||
|
[],
|
||||||
|
flex_info.vars,
|
||||||
|
flex_info.def_types,
|
||||||
|
inner_inner,
|
||||||
|
rigid_constraints,
|
||||||
|
);
|
||||||
|
|
||||||
constraints.let_constraint(
|
constraints.let_constraint(
|
||||||
rigid_info.vars,
|
rigid_info.vars,
|
||||||
[],
|
[],
|
||||||
rigid_info.def_types,
|
rigid_info.def_types,
|
||||||
Constraint::True,
|
Constraint::True,
|
||||||
constraints.let_constraint(
|
inner,
|
||||||
[],
|
|
||||||
flex_info.vars,
|
|
||||||
flex_info.def_types.clone(),
|
|
||||||
constraints.let_constraint(
|
|
||||||
[],
|
|
||||||
[],
|
|
||||||
flex_info.def_types,
|
|
||||||
Constraint::True,
|
|
||||||
constraints.and_constraint(flex_info.constraints),
|
|
||||||
),
|
|
||||||
constraints
|
|
||||||
.and_constraint([constraints.and_constraint(rigid_info.constraints), body_con]),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::builtins;
|
use crate::builtins;
|
||||||
use crate::soa_expr::{constrain_expr, Env};
|
use crate::soa_expr::{constrain_expr, Env};
|
||||||
use roc_can::constraint_soa::{Constraint, Constraints, PresenceConstraint};
|
use roc_can::constraint_soa::{Constraint, Constraints};
|
||||||
use roc_can::expected::{Expected, PExpected};
|
use roc_can::expected::{Expected, PExpected};
|
||||||
use roc_can::pattern::Pattern::{self, *};
|
use roc_can::pattern::Pattern::{self, *};
|
||||||
use roc_can::pattern::{DestructType, RecordDestruct};
|
use roc_can::pattern::{DestructType, RecordDestruct};
|
||||||
|
@ -168,20 +168,18 @@ pub fn constrain_pattern(
|
||||||
// A -> ""
|
// A -> ""
|
||||||
// _ -> ""
|
// _ -> ""
|
||||||
// so, we know that "x" (in this case, a tag union) must be open.
|
// so, we know that "x" (in this case, a tag union) must be open.
|
||||||
state.constraints.push(Constraint::Present(
|
state
|
||||||
expected.get_type(),
|
.constraints
|
||||||
PresenceConstraint::IsOpen,
|
.push(constraints.is_open_type(expected.get_type()));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
UnsupportedPattern(_) | MalformedPattern(_, _) | OpaqueNotInScope(..) => {
|
UnsupportedPattern(_) | MalformedPattern(_, _) | OpaqueNotInScope(..) => {
|
||||||
// Erroneous patterns don't add any constraints.
|
// Erroneous patterns don't add any constraints.
|
||||||
}
|
}
|
||||||
|
|
||||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||||
state.constraints.push(Constraint::Present(
|
state
|
||||||
expected.get_type_ref().clone(),
|
.constraints
|
||||||
PresenceConstraint::IsOpen,
|
.push(constraints.is_open_type(expected.get_type_ref().clone()));
|
||||||
));
|
|
||||||
state.headers.insert(
|
state.headers.insert(
|
||||||
*symbol,
|
*symbol,
|
||||||
Loc {
|
Loc {
|
||||||
|
@ -205,18 +203,19 @@ pub fn constrain_pattern(
|
||||||
Category::Num,
|
Category::Num,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(constraints.equal_pattern_types(
|
||||||
region,
|
|
||||||
PatternCategory::Num,
|
|
||||||
num_type,
|
num_type,
|
||||||
expected,
|
expected,
|
||||||
|
PatternCategory::Num,
|
||||||
|
region,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
&IntLiteral(num_var, precision_var, _, _, bound) => {
|
&IntLiteral(num_var, precision_var, _, _, bound) => {
|
||||||
// First constraint on the free num var; this improves the resolved type quality in
|
// First constraint on the free num var; this improves the resolved type quality in
|
||||||
// case the bound is an alias.
|
// case the bound is an alias.
|
||||||
let num_type = builtins::add_numeric_bound_constr(
|
let num_type = builtins::add_numeric_bound_constr_soa(
|
||||||
|
constraints,
|
||||||
&mut state.constraints,
|
&mut state.constraints,
|
||||||
Type::Variable(num_var),
|
Type::Variable(num_var),
|
||||||
bound,
|
bound,
|
||||||
|
@ -266,29 +265,29 @@ pub fn constrain_pattern(
|
||||||
));
|
));
|
||||||
|
|
||||||
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(constraints.equal_pattern_types(
|
||||||
region,
|
|
||||||
PatternCategory::Float,
|
|
||||||
num_type, // TODO check me if something breaks!
|
num_type, // TODO check me if something breaks!
|
||||||
expected,
|
expected,
|
||||||
|
PatternCategory::Float,
|
||||||
|
region,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
StrLiteral(_) => {
|
StrLiteral(_) => {
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(constraints.equal_pattern_types(
|
||||||
region,
|
|
||||||
PatternCategory::Str,
|
|
||||||
builtins::str_type(),
|
builtins::str_type(),
|
||||||
expected,
|
expected,
|
||||||
|
PatternCategory::Str,
|
||||||
|
region,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
SingleQuote(_) => {
|
SingleQuote(_) => {
|
||||||
state.constraints.push(Constraint::Pattern(
|
state.constraints.push(constraints.equal_pattern_types(
|
||||||
region,
|
|
||||||
PatternCategory::Character,
|
|
||||||
builtins::num_u32(),
|
builtins::num_u32(),
|
||||||
expected,
|
expected,
|
||||||
|
PatternCategory::Character,
|
||||||
|
region,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,36 +324,39 @@ pub fn constrain_pattern(
|
||||||
|
|
||||||
let field_type = match typ {
|
let field_type = match typ {
|
||||||
DestructType::Guard(guard_var, loc_guard) => {
|
DestructType::Guard(guard_var, loc_guard) => {
|
||||||
state.constraints.push(Constraint::Present(
|
state.constraints.push(constraints.pattern_presence(
|
||||||
Type::Variable(*guard_var),
|
Type::Variable(*guard_var),
|
||||||
PresenceConstraint::Pattern(
|
|
||||||
region,
|
|
||||||
PatternCategory::PatternGuard,
|
|
||||||
PExpected::ForReason(
|
PExpected::ForReason(
|
||||||
PReason::PatternGuard,
|
PReason::PatternGuard,
|
||||||
pat_type.clone(),
|
pat_type.clone(),
|
||||||
loc_guard.region,
|
loc_guard.region,
|
||||||
),
|
),
|
||||||
),
|
PatternCategory::PatternGuard,
|
||||||
|
region,
|
||||||
));
|
));
|
||||||
state.vars.push(*guard_var);
|
state.vars.push(*guard_var);
|
||||||
|
|
||||||
constrain_pattern(env, &loc_guard.value, loc_guard.region, expected, state);
|
constrain_pattern(
|
||||||
|
constraints,
|
||||||
|
env,
|
||||||
|
&loc_guard.value,
|
||||||
|
loc_guard.region,
|
||||||
|
expected,
|
||||||
|
state,
|
||||||
|
);
|
||||||
|
|
||||||
RecordField::Demanded(pat_type)
|
RecordField::Demanded(pat_type)
|
||||||
}
|
}
|
||||||
DestructType::Optional(expr_var, loc_expr) => {
|
DestructType::Optional(expr_var, loc_expr) => {
|
||||||
state.constraints.push(Constraint::Present(
|
state.constraints.push(constraints.pattern_presence(
|
||||||
Type::Variable(*expr_var),
|
Type::Variable(*expr_var),
|
||||||
PresenceConstraint::Pattern(
|
|
||||||
region,
|
|
||||||
PatternCategory::PatternDefault,
|
|
||||||
PExpected::ForReason(
|
PExpected::ForReason(
|
||||||
PReason::OptionalField,
|
PReason::OptionalField,
|
||||||
pat_type.clone(),
|
pat_type.clone(),
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
),
|
),
|
||||||
),
|
PatternCategory::PatternDefault,
|
||||||
|
region,
|
||||||
));
|
));
|
||||||
|
|
||||||
state.vars.push(*expr_var);
|
state.vars.push(*expr_var);
|
||||||
|
@ -365,8 +367,13 @@ pub fn constrain_pattern(
|
||||||
loc_expr.region,
|
loc_expr.region,
|
||||||
);
|
);
|
||||||
|
|
||||||
let expr_con =
|
let expr_con = constrain_expr(
|
||||||
constrain_expr(env, loc_expr.region, &loc_expr.value, expr_expected);
|
constraints,
|
||||||
|
env,
|
||||||
|
loc_expr.region,
|
||||||
|
&loc_expr.value,
|
||||||
|
expr_expected,
|
||||||
|
);
|
||||||
state.constraints.push(expr_con);
|
state.constraints.push(expr_con);
|
||||||
|
|
||||||
RecordField::Optional(pat_type)
|
RecordField::Optional(pat_type)
|
||||||
|
@ -391,9 +398,11 @@ pub fn constrain_pattern(
|
||||||
region,
|
region,
|
||||||
);
|
);
|
||||||
|
|
||||||
let record_con = Constraint::Present(
|
let record_con = constraints.pattern_presence(
|
||||||
Type::Variable(*whole_var),
|
Type::Variable(*whole_var),
|
||||||
PresenceConstraint::Pattern(region, PatternCategory::Record, expected),
|
expected,
|
||||||
|
PatternCategory::Record,
|
||||||
|
region,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.constraints.push(whole_con);
|
state.constraints.push(whole_con);
|
||||||
|
@ -420,24 +429,31 @@ pub fn constrain_pattern(
|
||||||
pattern_type,
|
pattern_type,
|
||||||
region,
|
region,
|
||||||
);
|
);
|
||||||
constrain_pattern(env, &loc_pattern.value, loc_pattern.region, expected, state);
|
constrain_pattern(
|
||||||
|
constraints,
|
||||||
|
env,
|
||||||
|
&loc_pattern.value,
|
||||||
|
loc_pattern.region,
|
||||||
|
expected,
|
||||||
|
state,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let pat_category = PatternCategory::Ctor(tag_name.clone());
|
let pat_category = PatternCategory::Ctor(tag_name.clone());
|
||||||
|
|
||||||
let whole_con = Constraint::Present(
|
let whole_con = constraints.includes_tag(
|
||||||
expected.clone().get_type(),
|
expected.clone().get_type(),
|
||||||
PresenceConstraint::IncludesTag(
|
|
||||||
tag_name.clone(),
|
tag_name.clone(),
|
||||||
argument_types.clone(),
|
argument_types.clone(),
|
||||||
region,
|
|
||||||
pat_category.clone(),
|
pat_category.clone(),
|
||||||
),
|
region,
|
||||||
);
|
);
|
||||||
|
|
||||||
let tag_con = Constraint::Present(
|
let tag_con = constraints.pattern_presence(
|
||||||
Type::Variable(*whole_var),
|
Type::Variable(*whole_var),
|
||||||
PresenceConstraint::Pattern(region, pat_category, expected),
|
expected,
|
||||||
|
pat_category,
|
||||||
|
region,
|
||||||
);
|
);
|
||||||
|
|
||||||
state.vars.push(*whole_var);
|
state.vars.push(*whole_var);
|
||||||
|
@ -469,6 +485,7 @@ pub fn constrain_pattern(
|
||||||
// First, add a constraint for the argument "who"
|
// First, add a constraint for the argument "who"
|
||||||
let arg_pattern_expected = PExpected::NoExpectation(arg_pattern_type.clone());
|
let arg_pattern_expected = PExpected::NoExpectation(arg_pattern_type.clone());
|
||||||
constrain_pattern(
|
constrain_pattern(
|
||||||
|
constraints,
|
||||||
env,
|
env,
|
||||||
&loc_arg_pattern.value,
|
&loc_arg_pattern.value,
|
||||||
loc_arg_pattern.region,
|
loc_arg_pattern.region,
|
||||||
|
@ -495,9 +512,11 @@ pub fn constrain_pattern(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Next, link `whole_var` (the type of "@Id who") to the expected type
|
// Next, link `whole_var` (the type of "@Id who") to the expected type
|
||||||
let opaque_pattern_con = Constraint::Present(
|
let opaque_pattern_con = constraints.pattern_presence(
|
||||||
Type::Variable(*whole_var),
|
Type::Variable(*whole_var),
|
||||||
PresenceConstraint::Pattern(region, PatternCategory::Opaque(*opaque), expected),
|
expected,
|
||||||
|
PatternCategory::Opaque(*opaque),
|
||||||
|
region,
|
||||||
);
|
);
|
||||||
|
|
||||||
state
|
state
|
||||||
|
|
|
@ -1372,7 +1372,7 @@ fn to_pattern_report<'b>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PReason::WhenMatch { index } => {
|
PReason::WhenMatch { index } => {
|
||||||
if index == Index::FIRST {
|
if index == HumanIndex::FIRST {
|
||||||
let doc = alloc.stack(vec![
|
let doc = alloc.stack(vec![
|
||||||
alloc
|
alloc
|
||||||
.text("The 1st pattern in this ")
|
.text("The 1st pattern in this ")
|
||||||
|
@ -1384,7 +1384,7 @@ fn to_pattern_report<'b>(
|
||||||
found,
|
found,
|
||||||
expected_type,
|
expected_type,
|
||||||
add_pattern_category(
|
add_pattern_category(
|
||||||
HumanIndexlloc,
|
alloc,
|
||||||
alloc.text("The first pattern is trying to match"),
|
alloc.text("The first pattern is trying to match"),
|
||||||
&category,
|
&category,
|
||||||
),
|
),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue