mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Coalesce
This commit is contained in:
parent
bd4f004cea
commit
9dac9e4bc2
15 changed files with 502 additions and 207 deletions
|
@ -5,11 +5,11 @@ use crate::pattern::{constrain_pattern, PatternState};
|
|||
use roc_can::annotation::IntroducedVariables;
|
||||
use roc_can::constraint::{Constraint, Constraints};
|
||||
use roc_can::def::{Declaration, Def};
|
||||
use roc_can::exhaustive::{sketch_rows, ExhaustiveContext};
|
||||
use roc_can::exhaustive::{sketch_pattern_to_rows, sketch_when_branches, ExhaustiveContext};
|
||||
use roc_can::expected::Expected::{self, *};
|
||||
use roc_can::expected::PExpected;
|
||||
use roc_can::expr::Expr::{self, *};
|
||||
use roc_can::expr::{AccessorData, ClosureData, Field, WhenBranch};
|
||||
use roc_can::expr::{AccessorData, AnnotatedMark, ClosureData, Field, WhenBranch};
|
||||
use roc_can::pattern::Pattern;
|
||||
use roc_collections::all::{HumanIndex, MutMap, SendMap};
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
|
@ -50,7 +50,7 @@ pub struct Env {
|
|||
fn constrain_untyped_args(
|
||||
constraints: &mut Constraints,
|
||||
env: &Env,
|
||||
arguments: &[(Variable, Loc<Pattern>)],
|
||||
arguments: &[(Variable, AnnotatedMark, Loc<Pattern>)],
|
||||
closure_type: Type,
|
||||
return_type: Type,
|
||||
) -> (Vec<Variable>, PatternState, Type) {
|
||||
|
@ -59,7 +59,10 @@ fn constrain_untyped_args(
|
|||
|
||||
let mut pattern_state = PatternState::default();
|
||||
|
||||
for (pattern_var, loc_pattern) in arguments {
|
||||
for (pattern_var, annotated_mark, loc_pattern) in arguments {
|
||||
// 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());
|
||||
|
||||
|
@ -720,12 +723,14 @@ pub fn constrain_expr(
|
|||
pattern_cons.push(cond_constraint);
|
||||
|
||||
// Now check the condition against the type expected by the branches.
|
||||
let sketched_rows = sketch_rows(real_cond_var, branches_region, branches);
|
||||
let sketched_rows = sketch_when_branches(real_cond_var, branches_region, branches);
|
||||
let cond_matches_branches_constraint = constraints.exhaustive(
|
||||
real_cond_var,
|
||||
loc_cond.region,
|
||||
loc_cond.value.category(),
|
||||
Expected::ForReason(Reason::WhenBranches, branches_cond_type, branches_region),
|
||||
Ok((
|
||||
loc_cond.value.category(),
|
||||
Expected::ForReason(Reason::WhenBranches, branches_cond_type, branches_region),
|
||||
)),
|
||||
sketched_rows,
|
||||
ExhaustiveContext::BadCase,
|
||||
*exhaustive,
|
||||
|
@ -1547,7 +1552,7 @@ fn constrain_typed_function_arguments(
|
|||
def: &Def,
|
||||
def_pattern_state: &mut PatternState,
|
||||
argument_pattern_state: &mut PatternState,
|
||||
arguments: &[(Variable, Loc<Pattern>)],
|
||||
arguments: &[(Variable, AnnotatedMark, Loc<Pattern>)],
|
||||
arg_types: &[Type],
|
||||
) {
|
||||
// ensure type matches the one in the annotation
|
||||
|
@ -1558,38 +1563,113 @@ fn constrain_typed_function_arguments(
|
|||
};
|
||||
|
||||
let it = arguments.iter().zip(arg_types.iter()).enumerate();
|
||||
for (index, ((pattern_var, loc_pattern), loc_ann)) in it {
|
||||
let pattern_expected = PExpected::ForReason(
|
||||
PReason::TypedArg {
|
||||
index: HumanIndex::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
loc_ann.clone(),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
pattern_expected,
|
||||
argument_pattern_state,
|
||||
);
|
||||
|
||||
{
|
||||
// NOTE: because we perform an equality with part of the signature
|
||||
// this constraint must be to the def_pattern_state's constraints
|
||||
def_pattern_state.vars.push(*pattern_var);
|
||||
|
||||
let pattern_con = constraints.equal_types_var(
|
||||
*pattern_var,
|
||||
Expected::NoExpectation(loc_ann.clone()),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
for (index, ((pattern_var, annotated_mark, loc_pattern), ann)) in it {
|
||||
if loc_pattern.value.surely_exhaustive() {
|
||||
// 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(
|
||||
PReason::TypedArg {
|
||||
index: HumanIndex::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
ann.clone(),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(pattern_con);
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
pattern_expected,
|
||||
argument_pattern_state,
|
||||
);
|
||||
|
||||
{
|
||||
// NOTE: because we perform an equality with part of the signature
|
||||
// this constraint must be to the def_pattern_state's constraints
|
||||
def_pattern_state.vars.push(*pattern_var);
|
||||
|
||||
let pattern_con = constraints.equal_types_var(
|
||||
*pattern_var,
|
||||
Expected::NoExpectation(ann.clone()),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(pattern_con);
|
||||
}
|
||||
} else {
|
||||
// We need to check the types, and run exhaustiveness checking.
|
||||
let &AnnotatedMark {
|
||||
annotation_var,
|
||||
exhaustive,
|
||||
} = annotated_mark;
|
||||
|
||||
def_pattern_state.vars.push(*pattern_var);
|
||||
def_pattern_state.vars.push(annotation_var);
|
||||
|
||||
{
|
||||
// First, solve the type that the pattern is expecting to match in this
|
||||
// position.
|
||||
let pattern_expected = PExpected::NoExpectation(Type::Variable(*pattern_var));
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
pattern_expected,
|
||||
argument_pattern_state,
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// Store the actual type in a variable.
|
||||
argument_pattern_state
|
||||
.constraints
|
||||
.push(constraints.equal_types_var(
|
||||
annotation_var,
|
||||
Expected::NoExpectation(ann.clone()),
|
||||
Category::Storage(file!(), line!()),
|
||||
Region::zero(),
|
||||
));
|
||||
}
|
||||
|
||||
{
|
||||
// let pattern_expected = PExpected::ForReason(
|
||||
// PReason::TypedArg {
|
||||
// index: HumanIndex::zero_based(index),
|
||||
// opt_name: opt_label,
|
||||
// },
|
||||
// ann.clone(),
|
||||
// loc_pattern.region,
|
||||
// );
|
||||
|
||||
// Exhaustiveness-check the type in the pattern against what the
|
||||
// annotation wants.
|
||||
let sketched_rows =
|
||||
sketch_pattern_to_rows(annotation_var, loc_pattern.region, &loc_pattern.value);
|
||||
let category = loc_pattern.value.category();
|
||||
let expected = PExpected::ForReason(
|
||||
PReason::TypedArg {
|
||||
index: HumanIndex::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
Type::Variable(*pattern_var),
|
||||
loc_pattern.region,
|
||||
);
|
||||
let exhaustive_constraint = constraints.exhaustive(
|
||||
annotation_var,
|
||||
loc_pattern.region,
|
||||
Err((category, expected)),
|
||||
sketched_rows,
|
||||
ExhaustiveContext::BadArg,
|
||||
exhaustive,
|
||||
);
|
||||
argument_pattern_state
|
||||
.constraints
|
||||
.push(exhaustive_constraint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1894,7 +1974,6 @@ pub fn rec_defs_help(
|
|||
delayed_is_open_constraints: vec![],
|
||||
};
|
||||
let mut vars = Vec::with_capacity(state.vars.capacity() + 1);
|
||||
let mut pattern_types = Vec::with_capacity(state.vars.capacity());
|
||||
let ret_var = *ret_var;
|
||||
let closure_var = *closure_var;
|
||||
let closure_ext_var = *closure_ext_var;
|
||||
|
@ -1904,53 +1983,16 @@ pub fn rec_defs_help(
|
|||
vars.push(closure_var);
|
||||
vars.push(closure_ext_var);
|
||||
|
||||
let it = arguments.iter().zip(arg_types.iter()).enumerate();
|
||||
for (index, ((pattern_var, loc_pattern), loc_ann)) in it {
|
||||
{
|
||||
// ensure type matches the one in the annotation
|
||||
let opt_label =
|
||||
if let Pattern::Identifier(label) = def.loc_pattern.value {
|
||||
Some(label)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let pattern_type: &Type = loc_ann;
|
||||
|
||||
let pattern_expected = PExpected::ForReason(
|
||||
PReason::TypedArg {
|
||||
index: HumanIndex::zero_based(index),
|
||||
opt_name: opt_label,
|
||||
},
|
||||
pattern_type.clone(),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
constrain_pattern(
|
||||
constraints,
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
pattern_expected,
|
||||
&mut state,
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
// NOTE: because we perform an equality with part of the signature
|
||||
// this constraint must be to the def_pattern_state's constraints
|
||||
def_pattern_state.vars.push(*pattern_var);
|
||||
pattern_types.push(Type::Variable(*pattern_var));
|
||||
|
||||
let pattern_con = constraints.equal_types_var(
|
||||
*pattern_var,
|
||||
Expected::NoExpectation(loc_ann.clone()),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
loc_pattern.region,
|
||||
);
|
||||
|
||||
def_pattern_state.constraints.push(pattern_con);
|
||||
}
|
||||
}
|
||||
constrain_typed_function_arguments(
|
||||
constraints,
|
||||
env,
|
||||
def,
|
||||
&mut def_pattern_state,
|
||||
&mut state,
|
||||
&arguments,
|
||||
&arg_types,
|
||||
);
|
||||
let pattern_types = arguments.iter().map(|a| Type::Variable(a.0)).collect();
|
||||
|
||||
let closure_constraint = constrain_closure_size(
|
||||
constraints,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue