mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Pattern expectation takes a type index
This commit is contained in:
parent
cbd014a98a
commit
34cd1fb825
5 changed files with 81 additions and 81 deletions
|
@ -20,7 +20,7 @@ pub struct Constraints {
|
|||
pub categories: Vec<Category>,
|
||||
pub pattern_categories: Vec<PatternCategory>,
|
||||
pub expectations: Vec<Expected<TypeOrVar>>,
|
||||
pub pattern_expectations: Vec<PExpected<Cell<Type>>>,
|
||||
pub pattern_expectations: Vec<PExpected<TypeOrVar>>,
|
||||
pub includes_tags: Vec<IncludesTag>,
|
||||
pub strings: Vec<&'static str>,
|
||||
pub sketched_rows: Vec<SketchedRows>,
|
||||
|
@ -58,9 +58,8 @@ impl Default for Constraints {
|
|||
}
|
||||
}
|
||||
|
||||
pub type TypeIndex = Index<Cell<Type>>;
|
||||
pub type ExpectedTypeIndex = Index<Expected<TypeOrVar>>;
|
||||
pub type PExpectedTypeIndex = Index<PExpected<Cell<Type>>>;
|
||||
pub type PExpectedTypeIndex = Index<PExpected<TypeOrVar>>;
|
||||
pub type TypeOrVar = EitherIndex<Cell<Type>, Variable>;
|
||||
|
||||
impl Constraints {
|
||||
|
@ -219,8 +218,8 @@ impl Constraints {
|
|||
Index::push_new(&mut self.expectations, expected)
|
||||
}
|
||||
|
||||
pub fn push_pat_expected_type(&mut self, expected: PExpected<Type>) -> PExpectedTypeIndex {
|
||||
Index::push_new(&mut self.pattern_expectations, expected.map(Cell::new))
|
||||
pub fn push_pat_expected_type(&mut self, expected: PExpected<TypeOrVar>) -> PExpectedTypeIndex {
|
||||
Index::push_new(&mut self.pattern_expectations, expected)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -72,8 +72,9 @@ fn constrain_untyped_args(
|
|||
// Untyped args don't need exhaustiveness checking because they are the source of truth!
|
||||
let _ = annotated_mark;
|
||||
|
||||
let pattern_type = Type::Variable(*pattern_var);
|
||||
let pattern_expected = PExpected::NoExpectation(pattern_type.clone());
|
||||
let pattern_type = Variable(*pattern_var);
|
||||
let pattern_type_index = constraints.push_type(Variable(*pattern_var));
|
||||
let pattern_expected = PExpected::NoExpectation(pattern_type_index);
|
||||
|
||||
pattern_types.push(pattern_type);
|
||||
|
||||
|
@ -774,7 +775,6 @@ pub fn constrain_expr(
|
|||
..
|
||||
} => {
|
||||
let branches_cond_var = *branches_cond_var;
|
||||
let branches_cond_type = Variable(branches_cond_var);
|
||||
let branches_cond_index = constraints.push_type(Variable(branches_cond_var));
|
||||
|
||||
let body_var = *expr_var;
|
||||
|
@ -840,7 +840,7 @@ pub fn constrain_expr(
|
|||
index: HumanIndex::zero_based(index),
|
||||
sub_pattern,
|
||||
},
|
||||
branches_cond_type.clone(),
|
||||
branches_cond_index,
|
||||
sub_region,
|
||||
)
|
||||
};
|
||||
|
@ -1790,13 +1790,14 @@ fn constrain_destructure_def(
|
|||
) -> Constraint {
|
||||
let loc_expr = &declarations.expressions[index];
|
||||
let expr_var = declarations.variables[index];
|
||||
let expr_var_index = constraints.push_type(Variable(expr_var));
|
||||
let opt_annotation = &declarations.annotations[index];
|
||||
|
||||
let destructure_def = &declarations.destructs[destructure_def_index.index()];
|
||||
let loc_pattern = &destructure_def.loc_pattern;
|
||||
|
||||
let mut def_pattern_state =
|
||||
constrain_def_pattern(constraints, env, loc_pattern, Type::Variable(expr_var));
|
||||
constrain_def_pattern(constraints, env, loc_pattern, expr_var_index);
|
||||
|
||||
def_pattern_state.vars.push(expr_var);
|
||||
|
||||
|
@ -1899,8 +1900,6 @@ fn constrain_value_def(
|
|||
let expr_var = declarations.variables[index];
|
||||
let opt_annotation = &declarations.annotations[index];
|
||||
|
||||
dbg!(&opt_annotation);
|
||||
|
||||
match opt_annotation {
|
||||
Some(annotation) => {
|
||||
let arity = 1;
|
||||
|
@ -2012,7 +2011,7 @@ fn constrain_when_branch_help(
|
|||
env: &mut Env,
|
||||
region: Region,
|
||||
when_branch: &WhenBranch,
|
||||
pattern_expected: impl Fn(HumanIndex, Region) -> PExpected<Type>,
|
||||
pattern_expected: impl Fn(HumanIndex, Region) -> PExpected<TypeOrVar>,
|
||||
expr_expected: Expected<TypeOrVar>,
|
||||
) -> ConstrainedBranch {
|
||||
let ret_constraint = constrain_expr(
|
||||
|
@ -2275,7 +2274,7 @@ pub(crate) fn constrain_def_pattern(
|
|||
constraints: &mut Constraints,
|
||||
env: &mut Env,
|
||||
loc_pattern: &Loc<Pattern>,
|
||||
expr_type: Type,
|
||||
expr_type: TypeOrVar,
|
||||
) -> PatternState {
|
||||
let pattern_expected = PExpected::NoExpectation(expr_type);
|
||||
|
||||
|
@ -2311,7 +2310,7 @@ fn constrain_typed_def(
|
|||
let expr_type_index = constraints.push_type(Variable(expr_var));
|
||||
|
||||
let mut def_pattern_state =
|
||||
constrain_def_pattern(constraints, env, &def.loc_pattern, expr_type.clone());
|
||||
constrain_def_pattern(constraints, env, &def.loc_pattern, expr_type_index);
|
||||
|
||||
def_pattern_state.vars.push(expr_var);
|
||||
|
||||
|
@ -2536,7 +2535,12 @@ fn constrain_typed_function_arguments(
|
|||
|
||||
let it = arguments.iter().zip(arg_types.iter()).enumerate();
|
||||
for (index, ((pattern_var, annotated_mark, loc_pattern), ann)) in it {
|
||||
let pattern_var_index = constraints.push_type(Variable(*pattern_var));
|
||||
|
||||
if loc_pattern.value.surely_exhaustive() {
|
||||
// TODO coalesce with ann_index below
|
||||
let ann_index = constraints.push_type(ann.clone());
|
||||
|
||||
// OPT: we don't need to perform any type-level exhaustiveness checking.
|
||||
// Check instead only that the pattern unifies with the annotation type.
|
||||
let pattern_expected = PExpected::ForReason(
|
||||
|
@ -2544,7 +2548,7 @@ fn constrain_typed_function_arguments(
|
|||
index: HumanIndex::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
ann.clone(),
|
||||
ann_index,
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
|
@ -2588,7 +2592,7 @@ fn constrain_typed_function_arguments(
|
|||
{
|
||||
// First, solve the type that the pattern is expecting to match in this
|
||||
// position.
|
||||
let pattern_expected = PExpected::NoExpectation(Type::Variable(*pattern_var));
|
||||
let pattern_expected = PExpected::NoExpectation(pattern_var_index);
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
|
@ -2633,7 +2637,7 @@ fn constrain_typed_function_arguments(
|
|||
index: HumanIndex::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
Type::Variable(*pattern_var),
|
||||
pattern_var_index,
|
||||
loc_pattern.region,
|
||||
));
|
||||
let exhaustive_constraint = constraints.exhaustive(
|
||||
|
@ -2663,7 +2667,12 @@ fn constrain_typed_function_arguments_simple(
|
|||
) {
|
||||
let it = arguments.iter().zip(arg_types.iter()).enumerate();
|
||||
for (index, ((pattern_var, annotated_mark, loc_pattern), ann)) in it {
|
||||
let pattern_var_index = constraints.push_type(Variable(*pattern_var));
|
||||
|
||||
if loc_pattern.value.surely_exhaustive() {
|
||||
// TODO coalesce
|
||||
let ann_index = constraints.push_type(ann.clone());
|
||||
|
||||
// OPT: we don't need to perform any type-level exhaustiveness checking.
|
||||
// Check instead only that the pattern unifies with the annotation type.
|
||||
let pattern_expected = PExpected::ForReason(
|
||||
|
@ -2671,7 +2680,7 @@ fn constrain_typed_function_arguments_simple(
|
|||
index: HumanIndex::zero_based(index),
|
||||
opt_name: Some(symbol),
|
||||
},
|
||||
ann.clone(),
|
||||
ann_index,
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
|
@ -2714,7 +2723,7 @@ fn constrain_typed_function_arguments_simple(
|
|||
{
|
||||
// First, solve the type that the pattern is expecting to match in this
|
||||
// position.
|
||||
let pattern_expected = PExpected::NoExpectation(Type::Variable(*pattern_var));
|
||||
let pattern_expected = PExpected::NoExpectation(pattern_var_index);
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
|
@ -2750,7 +2759,7 @@ fn constrain_typed_function_arguments_simple(
|
|||
index: HumanIndex::zero_based(index),
|
||||
opt_name: Some(symbol),
|
||||
},
|
||||
Type::Variable(*pattern_var),
|
||||
pattern_var_index,
|
||||
loc_pattern.region,
|
||||
));
|
||||
let exhaustive_constraint = constraints.exhaustive(
|
||||
|
@ -2790,11 +2799,10 @@ fn constrain_def(
|
|||
Some(annotation) => constrain_typed_def(constraints, env, def, body_con, annotation),
|
||||
None => {
|
||||
let expr_var = def.expr_var;
|
||||
let expr_type = Type::Variable(expr_var);
|
||||
let expr_type_index = constraints.push_type(Variable(expr_var));
|
||||
|
||||
let mut def_pattern_state =
|
||||
constrain_def_pattern(constraints, env, &def.loc_pattern, expr_type.clone());
|
||||
constrain_def_pattern(constraints, env, &def.loc_pattern, expr_type_index);
|
||||
|
||||
def_pattern_state.vars.push(expr_var);
|
||||
// no annotation, so no extra work with rigids
|
||||
|
@ -3516,11 +3524,10 @@ fn rec_defs_help(
|
|||
|
||||
for def in defs {
|
||||
let expr_var = def.expr_var;
|
||||
let expr_type = Type::Variable(expr_var);
|
||||
let expr_type_index = constraints.push_type(Variable(expr_var));
|
||||
|
||||
let mut def_pattern_state =
|
||||
constrain_def_pattern(constraints, env, &def.loc_pattern, expr_type.clone());
|
||||
constrain_def_pattern(constraints, env, &def.loc_pattern, expr_type_index);
|
||||
|
||||
def_pattern_state.vars.push(expr_var);
|
||||
|
||||
|
|
|
@ -50,8 +50,9 @@ fn constrain_symbols_from_requires(
|
|||
};
|
||||
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(loc_symbol.value));
|
||||
|
||||
let type_index = constraints.push_type(loc_type.value);
|
||||
let def_pattern_state =
|
||||
constrain_def_pattern(constraints, &mut env, &pattern, loc_type.value);
|
||||
constrain_def_pattern(constraints, &mut env, &pattern, type_index);
|
||||
|
||||
debug_assert!(env.resolutions_to_make.is_empty());
|
||||
|
||||
|
@ -108,12 +109,11 @@ pub fn frontload_ability_constraints(
|
|||
};
|
||||
let pattern = Loc::at_zero(roc_can::pattern::Pattern::Identifier(*member_name));
|
||||
|
||||
let mut def_pattern_state = constrain_def_pattern(
|
||||
constraints,
|
||||
&mut env,
|
||||
&pattern,
|
||||
Type::Variable(signature_var),
|
||||
);
|
||||
// TODO coalesce
|
||||
let signature_index = constraints.push_type(signature.clone());
|
||||
|
||||
let mut def_pattern_state =
|
||||
constrain_def_pattern(constraints, &mut env, &pattern, signature_index);
|
||||
|
||||
debug_assert!(env.resolutions_to_make.is_empty());
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ pub fn constrain_pattern(
|
|||
env: &mut Env,
|
||||
pattern: &Pattern,
|
||||
region: Region,
|
||||
expected: PExpected<Type>,
|
||||
expected: PExpected<TypeOrVar>,
|
||||
state: &mut PatternState,
|
||||
) {
|
||||
match pattern {
|
||||
|
@ -198,8 +198,8 @@ pub fn constrain_pattern(
|
|||
// A -> ""
|
||||
// _ -> ""
|
||||
// so, we know that "x" (in this case, a tag union) must be open.
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
let type_index = constraints.push_type(expected.get_type());
|
||||
if could_be_a_tag_union(constraints, *expected.get_type_ref()) {
|
||||
let type_index = expected.get_type();
|
||||
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
|
@ -211,9 +211,9 @@ pub fn constrain_pattern(
|
|||
}
|
||||
|
||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||
let type_index = constraints.push_type(expected.get_type_ref().clone());
|
||||
let type_index = *expected.get_type_ref();
|
||||
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
if could_be_a_tag_union(constraints, type_index) {
|
||||
state
|
||||
.delayed_is_open_constraints
|
||||
.push(constraints.is_open_type(type_index));
|
||||
|
@ -232,9 +232,9 @@ pub fn constrain_pattern(
|
|||
ident: symbol,
|
||||
specializes: _,
|
||||
} => {
|
||||
let type_index = constraints.push_type(expected.get_type_ref().clone());
|
||||
let type_index = *expected.get_type_ref();
|
||||
|
||||
if could_be_a_tag_union(expected.get_type_ref()) {
|
||||
if could_be_a_tag_union(constraints, type_index) {
|
||||
state.constraints.push(constraints.is_open_type(type_index));
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,7 @@ pub fn constrain_pattern(
|
|||
{
|
||||
let pat_type = Type::Variable(*var);
|
||||
let pat_type_index = constraints.push_type(pat_type.clone());
|
||||
let expected = PExpected::NoExpectation(pat_type.clone());
|
||||
let expected = PExpected::NoExpectation(pat_type_index);
|
||||
|
||||
if !state.headers.contains_key(symbol) {
|
||||
state
|
||||
|
@ -426,7 +426,7 @@ pub fn constrain_pattern(
|
|||
let expected_pat =
|
||||
constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::PatternGuard,
|
||||
pat_type.clone(),
|
||||
pat_type_index,
|
||||
loc_guard.region,
|
||||
));
|
||||
|
||||
|
@ -454,7 +454,7 @@ pub fn constrain_pattern(
|
|||
let expected_pat =
|
||||
constraints.push_pat_expected_type(PExpected::ForReason(
|
||||
PReason::OptionalField,
|
||||
pat_type.clone(),
|
||||
pat_type_index,
|
||||
loc_expr.region,
|
||||
));
|
||||
|
||||
|
@ -582,7 +582,7 @@ pub fn constrain_pattern(
|
|||
for (index, (pattern_var, loc_pattern)) in arguments.iter().enumerate() {
|
||||
state.vars.push(*pattern_var);
|
||||
|
||||
let pattern_type = Type::Variable(*pattern_var);
|
||||
let pattern_type = constraints.push_type(Type::Variable(*pattern_var));
|
||||
|
||||
let expected = PExpected::ForReason(
|
||||
PReason::TagArg {
|
||||
|
@ -603,7 +603,7 @@ pub fn constrain_pattern(
|
|||
}
|
||||
|
||||
let pat_category = PatternCategory::Ctor(tag_name.clone());
|
||||
let expected_type = constraints.push_type(expected.get_type_ref().clone());
|
||||
let expected_type = *expected.get_type_ref();
|
||||
|
||||
let whole_con = constraints.includes_tag(
|
||||
expected_type,
|
||||
|
@ -635,6 +635,7 @@ pub fn constrain_pattern(
|
|||
// Suppose we are constraining the pattern \@Id who, where Id n := [Id U64 n]
|
||||
let (arg_pattern_var, loc_arg_pattern) = &**argument;
|
||||
let arg_pattern_type = Type::Variable(*arg_pattern_var);
|
||||
let arg_pattern_type_index = constraints.push_type(Type::Variable(*arg_pattern_var));
|
||||
|
||||
let opaque_type = constraints.push_type(Type::Alias {
|
||||
symbol: *opaque,
|
||||
|
@ -652,7 +653,7 @@ pub fn constrain_pattern(
|
|||
});
|
||||
|
||||
// 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_index);
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
|
@ -687,11 +688,13 @@ pub fn constrain_pattern(
|
|||
// `[A k1, B k1] += typeof (A s)`, because we are in a destructure position and not
|
||||
// all constructors are covered in this branch!
|
||||
let arg_pattern_type = constraints.push_type(arg_pattern_type);
|
||||
let specialized_type = constraints
|
||||
.push_pat_expected_type(PExpected::NoExpectation((**specialized_def_type).clone()));
|
||||
let specialized_type_index = constraints.push_type((**specialized_def_type).clone());
|
||||
let specialized_type_expected = constraints
|
||||
.push_pat_expected_type(PExpected::NoExpectation(specialized_type_index));
|
||||
|
||||
let link_type_variables_con = constraints.pattern_presence(
|
||||
arg_pattern_type,
|
||||
specialized_type,
|
||||
specialized_type_expected,
|
||||
PatternCategory::Opaque(*opaque),
|
||||
loc_arg_pattern.region,
|
||||
);
|
||||
|
@ -724,6 +727,18 @@ pub fn constrain_pattern(
|
|||
}
|
||||
}
|
||||
|
||||
fn could_be_a_tag_union(typ: &Type) -> bool {
|
||||
!matches!(typ, Type::Apply(..) | Type::Function(..) | Type::Record(..))
|
||||
fn could_be_a_tag_union(constraints: &mut Constraints, typ: TypeOrVar) -> bool {
|
||||
match typ.split() {
|
||||
Ok(typ_index) => {
|
||||
let typ_cell = &mut constraints.types[typ_index.index()];
|
||||
!matches!(
|
||||
typ_cell.get_mut(),
|
||||
Type::Apply(..) | Type::Function(..) | Type::Record(..)
|
||||
)
|
||||
}
|
||||
Err(_) => {
|
||||
// Variables are opaque at this point, assume yes
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1180,15 +1180,16 @@ fn solve(
|
|||
);
|
||||
|
||||
let expectation = &constraints.pattern_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(),
|
||||
);
|
||||
|
||||
let mode = match constraint {
|
||||
|
@ -1495,22 +1496,10 @@ fn solve(
|
|||
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,
|
||||
branches_var,
|
||||
*expected.get_type_ref(),
|
||||
Ok((category, expected)),
|
||||
)
|
||||
}
|
||||
|
@ -1523,21 +1512,10 @@ fn solve(
|
|||
) = 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,
|
||||
branches_var,
|
||||
*expected.get_type_ref(),
|
||||
Err((category, expected)),
|
||||
)
|
||||
}
|
||||
|
@ -1555,15 +1533,16 @@ fn solve(
|
|||
real_var,
|
||||
);
|
||||
|
||||
let branches_var = type_cell_to_var(
|
||||
let branches_var = either_type_index_to_var(
|
||||
constraints,
|
||||
subs,
|
||||
rank,
|
||||
pools,
|
||||
problems,
|
||||
abilities_store,
|
||||
obligation_cache,
|
||||
pools,
|
||||
aliases,
|
||||
expected_type,
|
||||
branches_var,
|
||||
);
|
||||
|
||||
let cond_source_is_likely_positive_value = category_and_expected.is_ok();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue