mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
add Store constraint that does not report errors
This commit is contained in:
parent
75d18eb8ba
commit
bde82c3bb6
10 changed files with 109 additions and 26 deletions
|
@ -765,6 +765,13 @@ fn variable_usage_help(con: &Constraint, declared: &mut SeenVariables, used: &mu
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Store(tipe, var, _, _) => {
|
||||||
|
for v in tipe.variables() {
|
||||||
|
used.insert(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
used.insert(*var);
|
||||||
|
}
|
||||||
Lookup(_, expectation, _) => {
|
Lookup(_, expectation, _) => {
|
||||||
for v in expectation.get_type_ref().variables() {
|
for v in expectation.get_type_ref().variables() {
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
|
|
|
@ -8,6 +8,7 @@ use roc_types::types::{Category, PatternCategory, Type};
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Constraint {
|
pub enum Constraint {
|
||||||
Eq(Type, Expected<Type>, Category, Region),
|
Eq(Type, Expected<Type>, Category, Region),
|
||||||
|
Store(Type, Variable, &'static str, u32),
|
||||||
Lookup(Symbol, Expected<Type>, Region),
|
Lookup(Symbol, Expected<Type>, Region),
|
||||||
Pattern(Region, PatternCategory, Type, PExpected<Type>),
|
Pattern(Region, PatternCategory, Type, PExpected<Type>),
|
||||||
True, // Used for things that always unify, e.g. blanks and runtime errors
|
True, // Used for things that always unify, e.g. blanks and runtime errors
|
||||||
|
|
|
@ -1221,19 +1221,9 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
||||||
})),
|
})),
|
||||||
// "the closure's type is equal to expected type"
|
// "the closure's type is equal to expected type"
|
||||||
Eq(fn_type.clone(), expected.clone(), Category::Lambda, region),
|
Eq(fn_type.clone(), expected.clone(), 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
|
||||||
Eq(
|
Store(signature.clone(), *fn_var, std::file!(), std::line!()),
|
||||||
Type::Variable(*fn_var),
|
Store(signature, expr_var, std::file!(), std::line!()),
|
||||||
NoExpectation(Type::Variable(expr_var)),
|
|
||||||
Category::Storage(std::file!(), std::line!()),
|
|
||||||
region,
|
|
||||||
),
|
|
||||||
Eq(
|
|
||||||
Type::Variable(expr_var),
|
|
||||||
expected,
|
|
||||||
Category::Storage(std::file!(), std::line!()),
|
|
||||||
region,
|
|
||||||
),
|
|
||||||
closure_constraint,
|
closure_constraint,
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
|
@ -1579,18 +1569,9 @@ pub fn rec_defs_help(
|
||||||
})),
|
})),
|
||||||
Eq(fn_type.clone(), expected.clone(), Category::Lambda, region),
|
Eq(fn_type.clone(), expected.clone(), 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
|
||||||
Eq(
|
// Store type into AST vars. We use Store so errors aren't reported twice
|
||||||
Type::Variable(*fn_var),
|
Store(signature.clone(), *fn_var, std::file!(), std::line!()),
|
||||||
NoExpectation(fn_type),
|
Store(signature, expr_var, std::file!(), std::line!()),
|
||||||
Category::Storage(std::file!(), std::line!()),
|
|
||||||
region,
|
|
||||||
),
|
|
||||||
Eq(
|
|
||||||
Type::Variable(expr_var),
|
|
||||||
expected,
|
|
||||||
Category::Storage(std::file!(), std::line!()),
|
|
||||||
region,
|
|
||||||
),
|
|
||||||
closure_constraint,
|
closure_constraint,
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
|
@ -389,6 +389,13 @@ fn variable_usage_help(con: &Constraint, declared: &mut SeenVariables, used: &mu
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Store(tipe, var, _, _) => {
|
||||||
|
for v in tipe.variables() {
|
||||||
|
used.insert(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
used.insert(*var);
|
||||||
|
}
|
||||||
Lookup(_, expectation, _) => {
|
Lookup(_, expectation, _) => {
|
||||||
for v in expectation.get_type_ref().variables() {
|
for v in expectation.get_type_ref().variables() {
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
|
|
|
@ -402,6 +402,13 @@ fn variable_usage_help(con: &Constraint, declared: &mut SeenVariables, used: &mu
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Store(tipe, var, _, _) => {
|
||||||
|
for v in tipe.variables() {
|
||||||
|
used.insert(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
used.insert(*var);
|
||||||
|
}
|
||||||
Lookup(_, expectation, _) => {
|
Lookup(_, expectation, _) => {
|
||||||
for v in expectation.get_type_ref().variables() {
|
for v in expectation.get_type_ref().variables() {
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
|
|
|
@ -244,6 +244,34 @@ fn solve(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Store(source, target, _filename, _linenr) => {
|
||||||
|
// a special version of Eq that is used to store types in the AST.
|
||||||
|
// IT DOES NOT REPORT ERRORS!
|
||||||
|
let actual = type_to_var(subs, rank, pools, cached_aliases, source);
|
||||||
|
let target = *target;
|
||||||
|
|
||||||
|
match unify(subs, actual, target) {
|
||||||
|
Success(vars) => {
|
||||||
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
Failure(vars, _actual_type, _expected_type) => {
|
||||||
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
// ERROR NOT REPORTED
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
BadType(vars, _problem) => {
|
||||||
|
introduce(subs, rank, pools, &vars);
|
||||||
|
|
||||||
|
// ERROR NOT REPORTED
|
||||||
|
|
||||||
|
state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Lookup(symbol, expectation, region) => {
|
Lookup(symbol, expectation, region) => {
|
||||||
let var = *env.vars_by_symbol.get(&symbol).unwrap_or_else(|| {
|
let var = *env.vars_by_symbol.get(&symbol).unwrap_or_else(|| {
|
||||||
// TODO Instead of panicking, solve this as True and record
|
// TODO Instead of panicking, solve this as True and record
|
||||||
|
|
|
@ -417,6 +417,13 @@ fn variable_usage_help(con: &Constraint, declared: &mut SeenVariables, used: &mu
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Store(tipe, var, _, _) => {
|
||||||
|
for v in tipe.variables() {
|
||||||
|
used.insert(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
used.insert(*var);
|
||||||
|
}
|
||||||
Lookup(_, expectation, _) => {
|
Lookup(_, expectation, _) => {
|
||||||
for v in expectation.get_type_ref().variables() {
|
for v in expectation.get_type_ref().variables() {
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
|
|
|
@ -3481,4 +3481,42 @@ mod solve_expr {
|
||||||
"Dict Int Int",
|
"Dict Int Int",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn quicksort_partition_help() {
|
||||||
|
infer_eq_without_problem(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
app Test provides [ partitionHelp ] imports []
|
||||||
|
|
||||||
|
swap : Int, Int, List a -> List a
|
||||||
|
swap = \i, j, list ->
|
||||||
|
when Pair (List.get list i) (List.get list j) is
|
||||||
|
Pair (Ok atI) (Ok atJ) ->
|
||||||
|
list
|
||||||
|
|> List.set i atJ
|
||||||
|
|> List.set j atI
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
[]
|
||||||
|
|
||||||
|
partitionHelp : Int, Int, List (Num a), Int, (Num a) -> [ Pair Int (List (Num a)) ]
|
||||||
|
partitionHelp = \i, j, list, high, pivot ->
|
||||||
|
if j < high then
|
||||||
|
when List.get list j is
|
||||||
|
Ok value ->
|
||||||
|
if value <= pivot then
|
||||||
|
partitionHelp (i + 1) (j + 1) (swap (i + 1) j list) high pivot
|
||||||
|
else
|
||||||
|
partitionHelp i (j + 1) list high pivot
|
||||||
|
|
||||||
|
Err _ ->
|
||||||
|
Pair i list
|
||||||
|
else
|
||||||
|
Pair i list
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
"Int, Int, List (Num a), Int, Num a -> [ Pair Int (List (Num a)) ]",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1089,7 +1089,7 @@ fn unify_rigid(subs: &mut Subs, ctx: &Context, name: &Lowercase, other: &Content
|
||||||
RigidVar(_) | RecursionVar { .. } | Structure(_) | Alias(_, _, _) => {
|
RigidVar(_) | RecursionVar { .. } | Structure(_) | Alias(_, _, _) => {
|
||||||
// Type mismatch! Rigid can only unify with flex, even if the
|
// Type mismatch! Rigid can only unify with flex, even if the
|
||||||
// rigid names are the same.
|
// rigid names are the same.
|
||||||
mismatch!("Rigid with {:?}", &other)
|
mismatch!("Rigid {:?} with {:?}", ctx.first, &other)
|
||||||
}
|
}
|
||||||
Error => {
|
Error => {
|
||||||
// Error propagates.
|
// Error propagates.
|
||||||
|
|
|
@ -414,6 +414,13 @@ fn variable_usage_help(con: &Constraint, declared: &mut SeenVariables, used: &mu
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Store(tipe, var, _, _) => {
|
||||||
|
for v in tipe.variables() {
|
||||||
|
used.insert(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
used.insert(*var);
|
||||||
|
}
|
||||||
Lookup(_, expectation, _) => {
|
Lookup(_, expectation, _) => {
|
||||||
for v in expectation.get_type_ref().variables() {
|
for v in expectation.get_type_ref().variables() {
|
||||||
used.insert(v);
|
used.insert(v);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue