mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 00:09:33 +03:00
Require type and expected indices in equal_types constraints
This commit is contained in:
parent
35a4781045
commit
55d7f3f658
@ -211,7 +211,7 @@ impl Constraints {
|
||||
EitherIndex::from_right(index)
|
||||
}
|
||||
|
||||
pub fn push_expected_type(&mut self, expected: Expected<Type>) -> Index<Expected<Cell<Type>>> {
|
||||
pub fn push_expected_type(&mut self, expected: Expected<Type>) -> ExpectedTypeIndex {
|
||||
Index::push_new(&mut self.expectations, expected.map(Cell::new))
|
||||
}
|
||||
|
||||
@ -256,13 +256,11 @@ impl Constraints {
|
||||
|
||||
pub fn equal_types(
|
||||
&mut self,
|
||||
typ: Type,
|
||||
expected: Expected<Type>,
|
||||
type_index: TypeOrVar,
|
||||
expected_index: ExpectedTypeIndex,
|
||||
category: Category,
|
||||
region: Region,
|
||||
) -> Constraint {
|
||||
let type_index = self.push_type(typ);
|
||||
let expected_index = Index::push_new(&mut self.expectations, expected.map(Cell::new));
|
||||
let category_index = Self::push_category(self, category);
|
||||
|
||||
Constraint::Eq(Eq(type_index, expected_index, category_index, region))
|
||||
|
@ -32,8 +32,10 @@ pub fn add_numeric_bound_constr(
|
||||
NumericBound::FloatExact(width) => {
|
||||
let actual_type = Variable(float_width_to_variable(width));
|
||||
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
|
||||
let type_index = constraints.push_type(Variable(num_var));
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let because_suffix =
|
||||
constraints.equal_types(Variable(num_var), expected, category, region);
|
||||
constraints.equal_types(type_index, expected_index, category, region);
|
||||
|
||||
num_constraints.extend([because_suffix]);
|
||||
|
||||
@ -42,8 +44,10 @@ pub fn add_numeric_bound_constr(
|
||||
NumericBound::IntExact(width) => {
|
||||
let actual_type = Variable(int_lit_width_to_variable(width));
|
||||
let expected = Expected::ForReason(Reason::NumericLiteralSuffix, actual_type, region);
|
||||
let type_index = constraints.push_type(Variable(num_var));
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let because_suffix =
|
||||
constraints.equal_types(Variable(num_var), expected, category, region);
|
||||
constraints.equal_types(type_index, expected_index, category, region);
|
||||
|
||||
num_constraints.extend([because_suffix]);
|
||||
|
||||
@ -52,7 +56,9 @@ pub fn add_numeric_bound_constr(
|
||||
NumericBound::Range(range) => {
|
||||
let actual_type = Variable(precision_var);
|
||||
let expected = Expected::NoExpectation(RangedNumber(range));
|
||||
let constr = constraints.equal_types(actual_type, expected, category, region);
|
||||
let type_index = constraints.push_type(actual_type);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let constr = constraints.equal_types(type_index, expected_index, category, region);
|
||||
|
||||
num_constraints.extend([constr]);
|
||||
|
||||
@ -84,14 +90,19 @@ pub fn int_literal(
|
||||
Category::Num,
|
||||
);
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
let expect_precision_var = constraints.push_expected_type(ForReason(
|
||||
reason,
|
||||
num_int(Type::Variable(precision_var)),
|
||||
region,
|
||||
));
|
||||
|
||||
constrs.extend([
|
||||
constraints.equal_types(
|
||||
num_type.clone(),
|
||||
ForReason(reason, num_int(Type::Variable(precision_var)), region),
|
||||
Category::Int,
|
||||
region,
|
||||
),
|
||||
constraints.equal_types(num_type, expected, Category::Int, region),
|
||||
constraints.equal_types(num_type_index, expect_precision_var, Category::Int, region),
|
||||
{
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(num_type_index, expected_index, Category::Int, region)
|
||||
},
|
||||
]);
|
||||
|
||||
// TODO the precision_var is not part of the exists here; for float it is. Which is correct?
|
||||
@ -122,13 +133,20 @@ pub fn single_quote_literal(
|
||||
);
|
||||
|
||||
constrs.extend([
|
||||
constraints.equal_types(
|
||||
num_type.clone(),
|
||||
ForReason(reason, num_int(Type::Variable(precision_var)), region),
|
||||
Category::Character,
|
||||
region,
|
||||
),
|
||||
constraints.equal_types(num_type, expected, Category::Character, region),
|
||||
{
|
||||
let type_index = constraints.push_type(num_type.clone());
|
||||
let expected_index = constraints.push_expected_type(ForReason(
|
||||
reason,
|
||||
num_int(Type::Variable(precision_var)),
|
||||
region,
|
||||
));
|
||||
constraints.equal_types(type_index, expected_index, Category::Character, region)
|
||||
},
|
||||
{
|
||||
let type_index = constraints.push_type(num_type);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(type_index, expected_index, Category::Character, region)
|
||||
},
|
||||
]);
|
||||
|
||||
let and_constraint = constraints.and_constraint(constrs);
|
||||
@ -158,13 +176,20 @@ pub fn float_literal(
|
||||
);
|
||||
|
||||
constrs.extend([
|
||||
constraints.equal_types(
|
||||
num_type.clone(),
|
||||
ForReason(reason, num_float(Type::Variable(precision_var)), region),
|
||||
Category::Frac,
|
||||
region,
|
||||
),
|
||||
constraints.equal_types(num_type, expected, Category::Frac, region),
|
||||
{
|
||||
let type_index = constraints.push_type(num_type.clone());
|
||||
let expected_index = constraints.push_expected_type(ForReason(
|
||||
reason,
|
||||
num_float(Type::Variable(precision_var)),
|
||||
region,
|
||||
));
|
||||
constraints.equal_types(type_index, expected_index, Category::Frac, region)
|
||||
},
|
||||
{
|
||||
let type_index = constraints.push_type(num_type);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(type_index, expected_index, Category::Frac, region)
|
||||
},
|
||||
]);
|
||||
|
||||
let and_constraint = constraints.and_constraint(constrs);
|
||||
@ -190,7 +215,9 @@ pub fn num_literal(
|
||||
Category::Num,
|
||||
);
|
||||
|
||||
constrs.extend([constraints.equal_types(num_type, expected, Category::Num, region)]);
|
||||
let type_index = constraints.push_type(num_type);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constrs.extend([constraints.equal_types(type_index, expected_index, Category::Num, region)]);
|
||||
|
||||
let and_constraint = constraints.and_constraint(constrs);
|
||||
constraints.exists([num_var], and_constraint)
|
||||
|
@ -292,7 +292,11 @@ pub fn constrain_expr(
|
||||
let and_constraint = constraints.and_constraint(cons);
|
||||
constraints.exists(vars, and_constraint)
|
||||
}
|
||||
Str(_) => constraints.equal_types(str_type(), expected, Category::Str, region),
|
||||
Str(_) => {
|
||||
let str_index = constraints.push_type(str_type());
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(str_index, expected_index, Category::Str, region)
|
||||
}
|
||||
SingleQuote(num_var, precision_var, _, bound) => single_quote_literal(
|
||||
constraints,
|
||||
*num_var,
|
||||
@ -306,9 +310,11 @@ pub fn constrain_expr(
|
||||
loc_elems,
|
||||
} => {
|
||||
if loc_elems.is_empty() {
|
||||
let elem_type_index = constraints.push_type(empty_list_type(*elem_var));
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let eq = constraints.equal_types(
|
||||
empty_list_type(*elem_var),
|
||||
expected,
|
||||
elem_type_index,
|
||||
expected_index,
|
||||
Category::List,
|
||||
region,
|
||||
);
|
||||
@ -336,9 +342,11 @@ pub fn constrain_expr(
|
||||
list_constraints.push(constraint);
|
||||
}
|
||||
|
||||
let elem_type_index = constraints.push_type(list_type(list_elem_type));
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
list_constraints.push(constraints.equal_types(
|
||||
list_type(list_elem_type),
|
||||
expected,
|
||||
elem_type_index,
|
||||
expected_index,
|
||||
Category::List,
|
||||
region,
|
||||
));
|
||||
@ -1005,13 +1013,17 @@ pub fn constrain_expr(
|
||||
category.clone(),
|
||||
region,
|
||||
),
|
||||
constraints.equal_types(function_type.clone(), expected, category.clone(), region),
|
||||
constraints.equal_types(
|
||||
function_type,
|
||||
NoExpectation(Variable(*function_var)),
|
||||
category,
|
||||
region,
|
||||
),
|
||||
{
|
||||
let type_index = constraints.push_type(function_type.clone());
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(type_index, expected_index, category.clone(), region)
|
||||
},
|
||||
{
|
||||
let type_index = constraints.push_type(function_type);
|
||||
let expected_index =
|
||||
constraints.push_expected_type(NoExpectation(Variable(*function_var)));
|
||||
constraints.equal_types(type_index, expected_index, category, region)
|
||||
},
|
||||
record_con,
|
||||
];
|
||||
|
||||
@ -1173,12 +1185,17 @@ pub fn constrain_expr(
|
||||
// Link the entire wrapped opaque type (with the now-constrained argument) to the type
|
||||
// variables of the opaque type
|
||||
// TODO: better expectation here
|
||||
let link_type_variables_con = constraints.equal_types(
|
||||
arg_type,
|
||||
Expected::NoExpectation((**specialized_def_type).clone()),
|
||||
Category::OpaqueArg,
|
||||
arg_loc_expr.region,
|
||||
);
|
||||
let link_type_variables_con = {
|
||||
let type_index = constraints.push_type(arg_type);
|
||||
let expected_index = constraints
|
||||
.push_expected_type(Expected::NoExpectation((**specialized_def_type).clone()));
|
||||
constraints.equal_types(
|
||||
type_index,
|
||||
expected_index,
|
||||
Category::OpaqueArg,
|
||||
arg_loc_expr.region,
|
||||
)
|
||||
};
|
||||
|
||||
let mut vars = vec![*arg_var, *opaque_var];
|
||||
// Also add the fresh variables we created for the type argument and lambda sets
|
||||
@ -1225,12 +1242,17 @@ pub fn constrain_expr(
|
||||
);
|
||||
|
||||
// Tie the type of the value wrapped by the opaque to the opaque's type variables.
|
||||
let link_type_variables_con = constraints.equal_types(
|
||||
argument_type.clone(),
|
||||
Expected::NoExpectation((*specialized_def_type).clone()),
|
||||
Category::OpaqueArg,
|
||||
region,
|
||||
);
|
||||
let link_type_variables_con = {
|
||||
let arg_type_index = constraints.push_type(argument_type.clone());
|
||||
let expected_specialized = constraints
|
||||
.push_expected_type(Expected::NoExpectation((*specialized_def_type).clone()));
|
||||
constraints.equal_types(
|
||||
arg_type_index,
|
||||
expected_specialized,
|
||||
Category::OpaqueArg,
|
||||
region,
|
||||
)
|
||||
};
|
||||
|
||||
let lambda_set = Type::ClosureTag {
|
||||
name: *function_name,
|
||||
@ -1441,12 +1463,17 @@ fn constrain_function_def(
|
||||
signature.clone(),
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(constraints.equal_types(
|
||||
Type::Variable(expr_var),
|
||||
annotation_expected,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
Region::span_across(&annotation.region, &loc_body_expr.region),
|
||||
));
|
||||
{
|
||||
let expr_type_index = constraints.push_type(Type::Variable(expr_var));
|
||||
let expected_index =
|
||||
constraints.push_expected_type(annotation_expected);
|
||||
def_pattern_state.constraints.push(constraints.equal_types(
|
||||
expr_type_index,
|
||||
expected_index,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
Region::span_across(&annotation.region, &loc_body_expr.region),
|
||||
));
|
||||
}
|
||||
|
||||
def_pattern_state
|
||||
};
|
||||
@ -1544,12 +1571,16 @@ fn constrain_function_def(
|
||||
signature.clone(),
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(constraints.equal_types(
|
||||
Type::Variable(expr_var),
|
||||
annotation_expected,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
Region::span_across(&annotation.region, &loc_body_expr.region),
|
||||
));
|
||||
{
|
||||
let expr_type_index = constraints.push_type(Type::Variable(expr_var));
|
||||
let expected_index = constraints.push_expected_type(annotation_expected);
|
||||
def_pattern_state.constraints.push(constraints.equal_types(
|
||||
expr_type_index,
|
||||
expected_index,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
Region::span_across(&annotation.region, &loc_body_expr.region),
|
||||
));
|
||||
}
|
||||
|
||||
constrain_typed_function_arguments_simple(
|
||||
constraints,
|
||||
@ -1929,9 +1960,12 @@ fn constrain_when_branch_help(
|
||||
// Make sure the bound variables in the patterns on the same branch agree in their types.
|
||||
for (sym, typ1) in state.headers.iter() {
|
||||
if let Some(typ2) = partial_state.headers.get(sym) {
|
||||
let type_index = constraints.push_type(typ1.value.clone());
|
||||
let expected_index =
|
||||
constraints.push_expected_type(Expected::NoExpectation(typ2.value.clone()));
|
||||
state.constraints.push(constraints.equal_types(
|
||||
typ1.value.clone(),
|
||||
Expected::NoExpectation(typ2.value.clone()),
|
||||
type_index,
|
||||
expected_index,
|
||||
Category::When,
|
||||
typ2.region,
|
||||
));
|
||||
@ -2016,7 +2050,9 @@ fn constrain_empty_record(
|
||||
region: Region,
|
||||
expected: Expected<Type>,
|
||||
) -> Constraint {
|
||||
constraints.equal_types(Type::EmptyRec, expected, Category::Record, region)
|
||||
let record_type_index = constraints.push_type(Type::EmptyRec);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(record_type_index, expected_index, Category::Record, region)
|
||||
}
|
||||
|
||||
/// Constrain top-level module declarations
|
||||
@ -2214,12 +2250,16 @@ fn constrain_typed_def(
|
||||
signature.clone(),
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(constraints.equal_types(
|
||||
expr_type.clone(),
|
||||
annotation_expected,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
Region::span_across(&annotation.region, &def.loc_expr.region),
|
||||
));
|
||||
{
|
||||
let type_index = constraints.push_type(expr_type.clone());
|
||||
let expected_index = constraints.push_expected_type(annotation_expected);
|
||||
def_pattern_state.constraints.push(constraints.equal_types(
|
||||
type_index,
|
||||
expected_index,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
Region::span_across(&annotation.region, &def.loc_expr.region),
|
||||
));
|
||||
}
|
||||
|
||||
// when a def is annotated, and its body is a closure, treat this
|
||||
// as a named function (in elm terms) for error messages.
|
||||
@ -3072,7 +3112,11 @@ fn constraint_recursive_function(
|
||||
state_constraints,
|
||||
expr_con,
|
||||
),
|
||||
constraints.equal_types(fn_type, expected, Category::Lambda, region),
|
||||
{
|
||||
let type_index = constraints.push_type(fn_type);
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
constraints.equal_types(type_index, expected_index, Category::Lambda, region)
|
||||
},
|
||||
// "fn_var is equal to the closure's type" - fn_var is used in code gen
|
||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||
constraints.store_index(signature_index, expr_var, std::file!(), std::line!()),
|
||||
@ -3482,12 +3526,17 @@ fn rec_defs_help(
|
||||
state_constraints,
|
||||
expr_con,
|
||||
),
|
||||
constraints.equal_types(
|
||||
fn_type.clone(),
|
||||
expected.clone(),
|
||||
Category::Lambda,
|
||||
region,
|
||||
),
|
||||
{
|
||||
let fn_type_index = constraints.push_type(fn_type.clone());
|
||||
let expected_index =
|
||||
constraints.push_expected_type(expected.clone());
|
||||
constraints.equal_types(
|
||||
fn_type_index,
|
||||
expected_index,
|
||||
Category::Lambda,
|
||||
region,
|
||||
)
|
||||
},
|
||||
// "fn_var is equal to the closure's type" - fn_var is used in code gen
|
||||
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||
constraints.store_index(
|
||||
|
@ -263,12 +263,12 @@ pub fn constrain_pattern(
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = builtins::num_int(Type::Variable(precision_var));
|
||||
|
||||
state.constraints.push(constraints.equal_types(
|
||||
num_type.clone(), // TODO check me if something breaks!
|
||||
Expected::NoExpectation(int_type),
|
||||
Category::Int,
|
||||
region,
|
||||
));
|
||||
state.constraints.push({
|
||||
let type_index = constraints.push_type(num_type.clone()); // TODO check me if something breaks!
|
||||
let expected_index =
|
||||
constraints.push_expected_type(Expected::NoExpectation(int_type));
|
||||
constraints.equal_types(type_index, expected_index, Category::Int, region)
|
||||
});
|
||||
|
||||
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
||||
state.constraints.push(constraints.equal_pattern_types(
|
||||
@ -295,12 +295,12 @@ pub fn constrain_pattern(
|
||||
// Link the free num var with the float var and our expectation.
|
||||
let float_type = builtins::num_float(Type::Variable(precision_var));
|
||||
|
||||
state.constraints.push(constraints.equal_types(
|
||||
num_type.clone(), // TODO check me if something breaks!
|
||||
Expected::NoExpectation(float_type),
|
||||
Category::Frac,
|
||||
region,
|
||||
));
|
||||
state.constraints.push({
|
||||
let type_index = constraints.push_type(num_type.clone()); // TODO check me if something breaks!
|
||||
let expected_index =
|
||||
constraints.push_expected_type(Expected::NoExpectation(float_type));
|
||||
constraints.equal_types(type_index, expected_index, Category::Frac, region)
|
||||
});
|
||||
|
||||
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
||||
state.constraints.push(constraints.equal_pattern_types(
|
||||
@ -336,12 +336,17 @@ pub fn constrain_pattern(
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = builtins::num_int(Type::Variable(precision_var));
|
||||
|
||||
state.constraints.push(constraints.equal_types(
|
||||
num_type.clone(), // TODO check me if something breaks!
|
||||
Expected::NoExpectation(int_type),
|
||||
Category::Int,
|
||||
region,
|
||||
));
|
||||
state.constraints.push({
|
||||
let type_index = constraints.push_type(num_type.clone());
|
||||
let expected_index =
|
||||
constraints.push_expected_type(Expected::NoExpectation(int_type));
|
||||
constraints.equal_types(
|
||||
type_index, // TODO check me if something breaks!
|
||||
expected_index,
|
||||
Category::Int,
|
||||
region,
|
||||
)
|
||||
});
|
||||
|
||||
// Also constrain the pattern against the num var, again to reuse aliases if they're present.
|
||||
state.constraints.push(constraints.equal_pattern_types(
|
||||
@ -452,9 +457,12 @@ pub fn constrain_pattern(
|
||||
|
||||
let record_type = Type::Record(field_types, TypeExtension::from_type(ext_type));
|
||||
|
||||
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
|
||||
let expected_record =
|
||||
constraints.push_expected_type(Expected::NoExpectation(record_type));
|
||||
let whole_con = constraints.equal_types(
|
||||
Type::Variable(*whole_var),
|
||||
Expected::NoExpectation(record_type),
|
||||
whole_var_index,
|
||||
expected_record,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
);
|
||||
@ -561,9 +569,12 @@ pub fn constrain_pattern(
|
||||
);
|
||||
|
||||
// Next, link `whole_var` to the opaque type of "@Id who"
|
||||
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
|
||||
let expected_opaque =
|
||||
constraints.push_expected_type(Expected::NoExpectation(opaque_type));
|
||||
let whole_con = constraints.equal_types(
|
||||
Type::Variable(*whole_var),
|
||||
Expected::NoExpectation(opaque_type),
|
||||
whole_var_index,
|
||||
expected_opaque,
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user