mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
First pass at expectations taking a type index
This commit is contained in:
parent
6dc6386f77
commit
2a4fca7034
7 changed files with 379 additions and 272 deletions
|
@ -19,7 +19,7 @@ pub struct Constraints {
|
|||
pub let_constraints: Vec<LetConstraint>,
|
||||
pub categories: Vec<Category>,
|
||||
pub pattern_categories: Vec<PatternCategory>,
|
||||
pub expectations: Vec<Expected<Cell<Type>>>,
|
||||
pub expectations: Vec<Expected<TypeOrVar>>,
|
||||
pub pattern_expectations: Vec<PExpected<Cell<Type>>>,
|
||||
pub includes_tags: Vec<IncludesTag>,
|
||||
pub strings: Vec<&'static str>,
|
||||
|
@ -59,7 +59,7 @@ impl Default for Constraints {
|
|||
}
|
||||
|
||||
pub type TypeIndex = Index<Cell<Type>>;
|
||||
pub type ExpectedTypeIndex = Index<Expected<Cell<Type>>>;
|
||||
pub type ExpectedTypeIndex = Index<Expected<TypeOrVar>>;
|
||||
pub type PExpectedTypeIndex = Index<PExpected<Cell<Type>>>;
|
||||
pub type TypeOrVar = EitherIndex<Cell<Type>, Variable>;
|
||||
|
||||
|
@ -215,8 +215,8 @@ impl Constraints {
|
|||
EitherIndex::from_right(index)
|
||||
}
|
||||
|
||||
pub fn push_expected_type(&mut self, expected: Expected<Type>) -> ExpectedTypeIndex {
|
||||
Index::push_new(&mut self.expectations, expected.map(Cell::new))
|
||||
pub fn push_expected_type(&mut self, expected: Expected<TypeOrVar>) -> ExpectedTypeIndex {
|
||||
Index::push_new(&mut self.expectations, expected)
|
||||
}
|
||||
|
||||
pub fn push_pat_expected_type(&mut self, expected: PExpected<Type>) -> PExpectedTypeIndex {
|
||||
|
@ -464,7 +464,7 @@ impl Constraints {
|
|||
where
|
||||
I1: IntoIterator<Item = Variable>,
|
||||
I2: IntoIterator<Item = Variable>,
|
||||
I3: IntoIterator<Item = (Symbol, Loc<Type>)>,
|
||||
I3: IntoIterator<Item = (Symbol, Loc<TypeOrVar>)>,
|
||||
I3::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
// defs and ret constraint are stored consequtively, so we only need to store one index
|
||||
|
@ -473,27 +473,10 @@ impl Constraints {
|
|||
self.constraints.push(defs_constraint);
|
||||
self.constraints.push(ret_constraint);
|
||||
|
||||
let def_types = {
|
||||
let types = def_types
|
||||
.into_iter()
|
||||
.map(|(sym, Loc { region, value })| {
|
||||
let type_index = self.push_type(value);
|
||||
(
|
||||
sym,
|
||||
Loc {
|
||||
region,
|
||||
value: type_index,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
self.def_types_slice(types)
|
||||
};
|
||||
|
||||
let let_constraint = LetConstraint {
|
||||
rigid_vars: self.variable_slice(rigid_vars),
|
||||
flex_vars: self.variable_slice(flex_vars),
|
||||
def_types,
|
||||
def_types: self.def_types_slice(def_types),
|
||||
defs_and_ret_constraint,
|
||||
};
|
||||
|
||||
|
@ -714,7 +697,7 @@ roc_error_macros::assert_sizeof_aarch64!(Constraint, 3 * 8);
|
|||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Eq(
|
||||
pub TypeOrVar,
|
||||
pub Index<Expected<Cell<Type>>>,
|
||||
pub ExpectedTypeIndex,
|
||||
pub Index<Category>,
|
||||
pub Region,
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use arrayvec::ArrayVec;
|
||||
use roc_can::constraint::{Constraint, Constraints};
|
||||
use roc_can::constraint::{Constraint, Constraints, TypeOrVar};
|
||||
use roc_can::expected::Expected::{self, *};
|
||||
use roc_can::num::{FloatBound, FloatWidth, IntBound, IntLitWidth, NumBound, SignDemand};
|
||||
use roc_module::symbol::Symbol;
|
||||
|
@ -30,7 +30,7 @@ pub fn add_numeric_bound_constr(
|
|||
num_num(Variable(num_var))
|
||||
}
|
||||
NumericBound::FloatExact(width) => {
|
||||
let actual_type = Variable(float_width_to_variable(width));
|
||||
let actual_type = constraints.push_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);
|
||||
|
@ -42,7 +42,7 @@ pub fn add_numeric_bound_constr(
|
|||
Variable(num_var)
|
||||
}
|
||||
NumericBound::IntExact(width) => {
|
||||
let actual_type = Variable(int_lit_width_to_variable(width));
|
||||
let actual_type = constraints.push_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);
|
||||
|
@ -54,11 +54,10 @@ pub fn add_numeric_bound_constr(
|
|||
Variable(num_var)
|
||||
}
|
||||
NumericBound::Range(range) => {
|
||||
let actual_type = Variable(precision_var);
|
||||
let expected = Expected::NoExpectation(RangedNumber(range));
|
||||
let type_index = constraints.push_type(actual_type);
|
||||
let precision_type = constraints.push_type(Variable(precision_var));
|
||||
let expected = Expected::NoExpectation(constraints.push_type(RangedNumber(range)));
|
||||
let expected_index = constraints.push_expected_type(expected);
|
||||
let constr = constraints.equal_types(type_index, expected_index, category, region);
|
||||
let constr = constraints.equal_types(precision_type, expected_index, category, region);
|
||||
|
||||
num_constraints.extend([constr]);
|
||||
|
||||
|
@ -72,7 +71,7 @@ pub fn int_literal(
|
|||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
expected: Expected<Type>,
|
||||
expected: Expected<TypeOrVar>,
|
||||
region: Region,
|
||||
bound: IntBound,
|
||||
) -> Constraint {
|
||||
|
@ -91,11 +90,10 @@ pub fn int_literal(
|
|||
);
|
||||
|
||||
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,
|
||||
));
|
||||
let int_precision_type = constraints.push_type(num_int(Type::Variable(precision_var)));
|
||||
|
||||
let expect_precision_var =
|
||||
constraints.push_expected_type(ForReason(reason, int_precision_type, region));
|
||||
|
||||
constrs.extend([
|
||||
constraints.equal_types(num_type_index, expect_precision_var, Category::Int, region),
|
||||
|
@ -114,7 +112,7 @@ pub fn single_quote_literal(
|
|||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
expected: Expected<Type>,
|
||||
expected: Expected<TypeOrVar>,
|
||||
region: Region,
|
||||
bound: SingleQuoteBound,
|
||||
) -> Constraint {
|
||||
|
@ -133,11 +131,10 @@ pub fn single_quote_literal(
|
|||
);
|
||||
|
||||
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,
|
||||
));
|
||||
let int_precision_type = constraints.push_type(num_int(Type::Variable(precision_var)));
|
||||
|
||||
let expect_precision_var =
|
||||
constraints.push_expected_type(ForReason(reason, int_precision_type, region));
|
||||
|
||||
constrs.extend([
|
||||
constraints.equal_types(
|
||||
|
@ -161,7 +158,7 @@ pub fn float_literal(
|
|||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
precision_var: Variable,
|
||||
expected: Expected<Type>,
|
||||
expected: Expected<TypeOrVar>,
|
||||
region: Region,
|
||||
bound: FloatBound,
|
||||
) -> Constraint {
|
||||
|
@ -179,11 +176,10 @@ pub fn float_literal(
|
|||
);
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
let expect_precision_var = constraints.push_expected_type(ForReason(
|
||||
reason,
|
||||
num_float(Type::Variable(precision_var)),
|
||||
region,
|
||||
));
|
||||
let float_precision_type = constraints.push_type(num_float(Type::Variable(precision_var)));
|
||||
|
||||
let expect_precision_var =
|
||||
constraints.push_expected_type(ForReason(reason, float_precision_type, region));
|
||||
|
||||
constrs.extend([
|
||||
constraints.equal_types(num_type_index, expect_precision_var, Category::Frac, region),
|
||||
|
@ -201,7 +197,7 @@ pub fn float_literal(
|
|||
pub fn num_literal(
|
||||
constraints: &mut Constraints,
|
||||
num_var: Variable,
|
||||
expected: Expected<Type>,
|
||||
expected: Expected<TypeOrVar>,
|
||||
region: Region,
|
||||
bound: NumBound,
|
||||
) -> Constraint {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -69,13 +69,15 @@ fn constrain_symbols_from_requires(
|
|||
// Otherwise, this symbol comes from an app module - we want to check that the type
|
||||
// provided by the app is in fact what the package module requires.
|
||||
let arity = loc_type.value.arity();
|
||||
let typ = loc_type.value;
|
||||
let type_index = constraints.push_type(typ);
|
||||
let expected = constraints.push_expected_type(Expected::FromAnnotation(
|
||||
loc_symbol.map(|&s| Pattern::Identifier(s)),
|
||||
arity,
|
||||
AnnotationSource::RequiredSymbol {
|
||||
region: loc_type.region,
|
||||
},
|
||||
loc_type.value,
|
||||
type_index,
|
||||
));
|
||||
let provided_eq_requires_constr =
|
||||
constraints.lookup(loc_symbol.value, expected, loc_type.region);
|
||||
|
@ -120,8 +122,9 @@ pub fn frontload_ability_constraints(
|
|||
let rigid_variables = vars.rigid_vars.iter().chain(vars.able_vars.iter()).copied();
|
||||
let infer_variables = vars.flex_vars.iter().copied();
|
||||
|
||||
let signature_index = constraints.push_type(signature.clone());
|
||||
let signature_expectation =
|
||||
constraints.push_expected_type(Expected::NoExpectation(signature.clone()));
|
||||
constraints.push_expected_type(Expected::NoExpectation(signature_index));
|
||||
|
||||
def_pattern_state
|
||||
.constraints
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::builtins;
|
||||
use crate::expr::{constrain_expr, Env};
|
||||
use roc_can::constraint::{Constraint, Constraints};
|
||||
use roc_can::constraint::{Constraint, Constraints, TypeOrVar};
|
||||
use roc_can::expected::{Expected, PExpected};
|
||||
use roc_can::pattern::Pattern::{self, *};
|
||||
use roc_can::pattern::{DestructType, ListPatterns, RecordDestruct};
|
||||
|
@ -17,7 +17,7 @@ use roc_types::types::{
|
|||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct PatternState {
|
||||
pub headers: VecMap<Symbol, Loc<Type>>,
|
||||
pub headers: VecMap<Symbol, Loc<TypeOrVar>>,
|
||||
pub vars: Vec<Variable>,
|
||||
pub constraints: Vec<Constraint>,
|
||||
pub delayed_is_open_constraints: Vec<Constraint>,
|
||||
|
@ -31,14 +31,16 @@ pub struct PatternState {
|
|||
/// Would add `x => <42>` to the headers (i.e., symbol points to a type variable). If the
|
||||
/// definition has an annotation, we instead now add `x => Int`.
|
||||
pub fn headers_from_annotation(
|
||||
constraints: &mut Constraints,
|
||||
pattern: &Pattern,
|
||||
annotation: &Loc<&Type>,
|
||||
) -> Option<VecMap<Symbol, Loc<Type>>> {
|
||||
) -> Option<VecMap<Symbol, Loc<TypeOrVar>>> {
|
||||
let mut headers = VecMap::default();
|
||||
// Check that the annotation structurally agrees with the pattern, preventing e.g. `{ x, y } : Int`
|
||||
// in such incorrect cases we don't put the full annotation in headers, just a variable, and let
|
||||
// inference generate a proper error.
|
||||
let is_structurally_valid = headers_from_annotation_help(pattern, annotation, &mut headers);
|
||||
let is_structurally_valid =
|
||||
headers_from_annotation_help(constraints, pattern, annotation, &mut headers);
|
||||
|
||||
if is_structurally_valid {
|
||||
Some(headers)
|
||||
|
@ -48,9 +50,10 @@ pub fn headers_from_annotation(
|
|||
}
|
||||
|
||||
fn headers_from_annotation_help(
|
||||
constraints: &mut Constraints,
|
||||
pattern: &Pattern,
|
||||
annotation: &Loc<&Type>,
|
||||
headers: &mut VecMap<Symbol, Loc<Type>>,
|
||||
headers: &mut VecMap<Symbol, Loc<TypeOrVar>>,
|
||||
) -> bool {
|
||||
match pattern {
|
||||
Identifier(symbol)
|
||||
|
@ -60,7 +63,8 @@ fn headers_from_annotation_help(
|
|||
ident: symbol,
|
||||
specializes: _,
|
||||
} => {
|
||||
let typ = Loc::at(annotation.region, annotation.value.clone());
|
||||
let annotation_index = constraints.push_type(annotation.value.clone());
|
||||
let typ = Loc::at(annotation.region, annotation_index);
|
||||
headers.insert(*symbol, typ);
|
||||
true
|
||||
}
|
||||
|
@ -87,9 +91,10 @@ fn headers_from_annotation_help(
|
|||
// `{ x ? 0 } = rec` or `{ x: 5 } -> ...` in all cases
|
||||
// the type of `x` within the binding itself is the same.
|
||||
if let Some(field_type) = fields.get(&destruct.label) {
|
||||
let field_type_index = constraints.push_type(field_type.as_inner().clone());
|
||||
headers.insert(
|
||||
destruct.symbol,
|
||||
Loc::at(annotation.region, field_type.clone().into_inner()),
|
||||
Loc::at(annotation.region, field_type_index),
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
|
@ -125,6 +130,7 @@ fn headers_from_annotation_help(
|
|||
.zip(arg_types.iter())
|
||||
.all(|(arg_pattern, arg_type)| {
|
||||
headers_from_annotation_help(
|
||||
constraints,
|
||||
&arg_pattern.1.value,
|
||||
&Loc::at(annotation.region, arg_type),
|
||||
headers,
|
||||
|
@ -156,11 +162,13 @@ fn headers_from_annotation_help(
|
|||
&& type_arguments.len() == pat_type_arguments.len()
|
||||
&& lambda_set_variables.len() == pat_lambda_set_variables.len() =>
|
||||
{
|
||||
let typ = Loc::at(annotation.region, annotation.value.clone());
|
||||
let annotation_index = constraints.push_type(annotation.value.clone());
|
||||
let typ = Loc::at(annotation.region, annotation_index);
|
||||
headers.insert(*opaque, typ);
|
||||
|
||||
let (_, argument_pat) = &**argument;
|
||||
headers_from_annotation_help(
|
||||
constraints,
|
||||
&argument_pat.value,
|
||||
&Loc::at(annotation.region, actual),
|
||||
headers,
|
||||
|
@ -203,9 +211,9 @@ pub fn constrain_pattern(
|
|||
}
|
||||
|
||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
let type_index = constraints.push_type(expected.get_type_ref().clone());
|
||||
let type_index = constraints.push_type(expected.get_type_ref().clone());
|
||||
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
.push(constraints.is_open_type(type_index));
|
||||
|
@ -215,7 +223,7 @@ pub fn constrain_pattern(
|
|||
*symbol,
|
||||
Loc {
|
||||
region,
|
||||
value: expected.get_type(),
|
||||
value: type_index,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -224,9 +232,9 @@ pub fn constrain_pattern(
|
|||
ident: symbol,
|
||||
specializes: _,
|
||||
} => {
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
let type_index = constraints.push_type(expected.get_type_ref().clone());
|
||||
let type_index = constraints.push_type(expected.get_type_ref().clone());
|
||||
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
state.constraints.push(constraints.is_open_type(type_index));
|
||||
}
|
||||
|
||||
|
@ -234,7 +242,7 @@ pub fn constrain_pattern(
|
|||
*symbol,
|
||||
Loc {
|
||||
region,
|
||||
value: expected.get_type(),
|
||||
value: type_index,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -278,7 +286,7 @@ pub fn constrain_pattern(
|
|||
let num_type = constraints.push_type(num_type);
|
||||
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = builtins::num_int(Type::Variable(precision_var));
|
||||
let int_type = constraints.push_type(builtins::num_int(Type::Variable(precision_var)));
|
||||
|
||||
state.constraints.push({
|
||||
let expected_index =
|
||||
|
@ -308,10 +316,11 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
Category::Frac,
|
||||
);
|
||||
let num_type_index = constraints.push_type(num_type); // TODO check me if something breaks!
|
||||
|
||||
// Link the free num var with the float var and our expectation.
|
||||
let float_type = builtins::num_float(Type::Variable(precision_var));
|
||||
let num_type_index = constraints.push_type(num_type); // TODO check me if something breaks!
|
||||
let float_type =
|
||||
constraints.push_type(builtins::num_float(Type::Variable(precision_var)));
|
||||
|
||||
state.constraints.push({
|
||||
let expected_index =
|
||||
|
@ -353,11 +362,11 @@ pub fn constrain_pattern(
|
|||
Category::Int,
|
||||
);
|
||||
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = builtins::num_int(Type::Variable(precision_var));
|
||||
|
||||
let num_type_index = constraints.push_type(num_type);
|
||||
|
||||
// Link the free num var with the int var and our expectation.
|
||||
let int_type = constraints.push_type(builtins::num_int(Type::Variable(precision_var)));
|
||||
|
||||
state.constraints.push({
|
||||
let expected_index =
|
||||
constraints.push_expected_type(Expected::NoExpectation(int_type));
|
||||
|
@ -402,12 +411,13 @@ pub fn constrain_pattern(
|
|||
} in destructs
|
||||
{
|
||||
let pat_type = Type::Variable(*var);
|
||||
let pat_type_index = constraints.push_type(pat_type.clone());
|
||||
let expected = PExpected::NoExpectation(pat_type.clone());
|
||||
|
||||
if !state.headers.contains_key(symbol) {
|
||||
state
|
||||
.headers
|
||||
.insert(*symbol, Loc::at(region, pat_type.clone()));
|
||||
.insert(*symbol, Loc::at(region, pat_type_index));
|
||||
}
|
||||
|
||||
let field_type = match typ {
|
||||
|
@ -459,7 +469,7 @@ pub fn constrain_pattern(
|
|||
|
||||
let expr_expected = Expected::ForReason(
|
||||
Reason::RecordDefaultField(label.clone()),
|
||||
pat_type.clone(),
|
||||
pat_type_index,
|
||||
loc_expr.region,
|
||||
);
|
||||
|
||||
|
@ -485,7 +495,10 @@ pub fn constrain_pattern(
|
|||
state.vars.push(*var);
|
||||
}
|
||||
|
||||
let record_type = Type::Record(field_types, TypeExtension::from_type(ext_type));
|
||||
let record_type = constraints.push_type(Type::Record(
|
||||
field_types,
|
||||
TypeExtension::from_type(ext_type),
|
||||
));
|
||||
|
||||
let whole_var_index = constraints.push_type(Type::Variable(*whole_var));
|
||||
let expected_record =
|
||||
|
@ -623,7 +636,7 @@ pub fn constrain_pattern(
|
|||
let (arg_pattern_var, loc_arg_pattern) = &**argument;
|
||||
let arg_pattern_type = Type::Variable(*arg_pattern_var);
|
||||
|
||||
let opaque_type = Type::Alias {
|
||||
let opaque_type = constraints.push_type(Type::Alias {
|
||||
symbol: *opaque,
|
||||
type_arguments: type_arguments
|
||||
.iter()
|
||||
|
@ -636,7 +649,7 @@ pub fn constrain_pattern(
|
|||
infer_ext_in_output_types: vec![],
|
||||
actual: Box::new(arg_pattern_type.clone()),
|
||||
kind: AliasKind::Opaque,
|
||||
};
|
||||
});
|
||||
|
||||
// First, add a constraint for the argument "who"
|
||||
let arg_pattern_expected = PExpected::NoExpectation(arg_pattern_type.clone());
|
||||
|
|
|
@ -947,15 +947,16 @@ fn solve(
|
|||
);
|
||||
|
||||
let expectation = &constraints.expectations[expectation_index.index()];
|
||||
let expected = type_cell_to_var(
|
||||
let expected = either_type_index_to_var(
|
||||
constraints,
|
||||
subs,
|
||||
rank,
|
||||
pools,
|
||||
problems,
|
||||
abilities_store,
|
||||
obligation_cache,
|
||||
pools,
|
||||
aliases,
|
||||
expectation.get_type_ref(),
|
||||
*expectation.get_type_ref(),
|
||||
);
|
||||
|
||||
match unify(
|
||||
|
@ -1065,15 +1066,16 @@ fn solve(
|
|||
let actual = deep_copy_var_in(subs, rank, pools, var, arena);
|
||||
let expectation = &constraints.expectations[expectation_index.index()];
|
||||
|
||||
let expected = type_cell_to_var(
|
||||
let expected = either_type_index_to_var(
|
||||
constraints,
|
||||
subs,
|
||||
rank,
|
||||
pools,
|
||||
problems,
|
||||
abilities_store,
|
||||
obligation_cache,
|
||||
pools,
|
||||
aliases,
|
||||
expectation.get_type_ref(),
|
||||
*expectation.get_type_ref(),
|
||||
);
|
||||
|
||||
match unify(
|
||||
|
@ -1487,15 +1489,28 @@ fn solve(
|
|||
// 4. Condition and branch types aren't "almost equal", this is just a normal type
|
||||
// error.
|
||||
|
||||
let (real_var, real_region, expected_type, category_and_expected) = match eq {
|
||||
let (real_var, real_region, branches_var, category_and_expected) = match eq {
|
||||
Ok(eq) => {
|
||||
let roc_can::constraint::Eq(real_var, expected, category, real_region) =
|
||||
constraints.eq[eq.index()];
|
||||
let expected = &constraints.expectations[expected.index()];
|
||||
|
||||
let branches_var = either_type_index_to_var(
|
||||
constraints,
|
||||
subs,
|
||||
rank,
|
||||
pools,
|
||||
problems,
|
||||
abilities_store,
|
||||
obligation_cache,
|
||||
aliases,
|
||||
*expected.get_type_ref(),
|
||||
);
|
||||
|
||||
(
|
||||
real_var,
|
||||
real_region,
|
||||
expected.get_type_ref(),
|
||||
branches_var,
|
||||
Ok((category, expected)),
|
||||
)
|
||||
}
|
||||
|
@ -1507,10 +1522,22 @@ fn solve(
|
|||
real_region,
|
||||
) = constraints.pattern_eq[peq.index()];
|
||||
let expected = &constraints.pattern_expectations[expected.index()];
|
||||
|
||||
let branches_var = type_cell_to_var(
|
||||
subs,
|
||||
rank,
|
||||
problems,
|
||||
abilities_store,
|
||||
obligation_cache,
|
||||
pools,
|
||||
aliases,
|
||||
expected.get_type_ref(),
|
||||
);
|
||||
|
||||
(
|
||||
real_var,
|
||||
real_region,
|
||||
expected.get_type_ref(),
|
||||
branches_var,
|
||||
Err((category, expected)),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -140,9 +140,12 @@ pub fn can_expr_with<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
let mut constraints = Constraints::new();
|
||||
|
||||
let mut var_store = VarStore::default();
|
||||
let var = var_store.fresh();
|
||||
let expected = Expected::NoExpectation(Type::Variable(var));
|
||||
let var_index = constraints.push_type(Type::Variable(var));
|
||||
let expected = Expected::NoExpectation(var_index);
|
||||
let mut module_ids = ModuleIds::default();
|
||||
|
||||
// ensure the Test module is accessible in our tests
|
||||
|
@ -169,7 +172,6 @@ pub fn can_expr_with<'a>(
|
|||
&loc_expr.value,
|
||||
);
|
||||
|
||||
let mut constraints = Constraints::new();
|
||||
let constraint = constrain_expr(
|
||||
&mut constraints,
|
||||
&mut roc_constrain::expr::Env {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue