mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
Merge remote-tracking branch 'origin/trunk' into low-level-ops
This commit is contained in:
commit
1cd49689c2
29 changed files with 1630 additions and 440 deletions
|
@ -118,8 +118,8 @@ pub fn constrain_expr(
|
|||
let record_type = Type::Record(
|
||||
field_types,
|
||||
// TODO can we avoid doing Box::new on every single one of these?
|
||||
// For example, could we have a single lazy_static global Box they
|
||||
// could all share?
|
||||
// We can put `static EMPTY_REC: Type = Type::EmptyRec`, but that requires a
|
||||
// lifetime parameter on `Type`
|
||||
Box::new(Type::EmptyRec),
|
||||
);
|
||||
let record_con = Eq(record_type, expected.clone(), Category::Record, region);
|
||||
|
@ -600,11 +600,7 @@ pub fn constrain_expr(
|
|||
}
|
||||
}
|
||||
|
||||
// TODO check for exhaustiveness. If this `case` is non-exaustive, then:
|
||||
//
|
||||
// 1. Record a Problem.
|
||||
// 2. Add an extra _ branch at the end which throws a runtime error.
|
||||
|
||||
// exhautiveness checking happens when converting to mono::Expr
|
||||
exists(vec![cond_var, *expr_var], And(constraints))
|
||||
}
|
||||
Access {
|
||||
|
@ -843,7 +839,6 @@ fn constrain_when_branch(
|
|||
constraints: Vec::with_capacity(1),
|
||||
};
|
||||
|
||||
// TODO ensure this is correct
|
||||
// TODO investigate for error messages, is it better to unify all branches with a variable,
|
||||
// then unify that variable with the expectation?
|
||||
for loc_pattern in &when_branch.patterns {
|
||||
|
@ -917,38 +912,35 @@ pub fn constrain_decls(
|
|||
) -> Constraint {
|
||||
let mut constraint = Constraint::SaveTheEnvironment;
|
||||
|
||||
let mut env = Env {
|
||||
home,
|
||||
rigids: ImMap::default(),
|
||||
};
|
||||
|
||||
for decl in decls.iter().rev() {
|
||||
// NOTE: rigids are empty because they are not shared between top-level definitions
|
||||
// Clear the rigids from the previous iteration.
|
||||
// rigids are not shared between top-level definitions
|
||||
env.rigids.clear();
|
||||
|
||||
match decl {
|
||||
Declaration::Declare(def) | Declaration::Builtin(def) => {
|
||||
constraint = exists_with_aliases(
|
||||
aliases.clone(),
|
||||
Vec::new(),
|
||||
constrain_def(
|
||||
&Env {
|
||||
home,
|
||||
rigids: ImMap::default(),
|
||||
},
|
||||
def,
|
||||
constraint,
|
||||
),
|
||||
constrain_def(&env, def, constraint),
|
||||
);
|
||||
}
|
||||
Declaration::DeclareRec(defs) => {
|
||||
constraint = exists_with_aliases(
|
||||
aliases.clone(),
|
||||
Vec::new(),
|
||||
constrain_recursive_defs(
|
||||
&Env {
|
||||
home,
|
||||
rigids: ImMap::default(),
|
||||
},
|
||||
defs,
|
||||
constraint,
|
||||
),
|
||||
constrain_recursive_defs(&env, defs, constraint),
|
||||
);
|
||||
}
|
||||
Declaration::InvalidCycle(_, _) => panic!("TODO handle invalid cycle"),
|
||||
Declaration::InvalidCycle(_, _) => {
|
||||
// invalid cycles give a canonicalization error. we skip them here.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1015,8 +1007,7 @@ fn constrain_def(env: &Env, def: &Def, body_con: Constraint) -> Constraint {
|
|||
expr_type,
|
||||
annotation_expected.clone(),
|
||||
Category::Storage,
|
||||
// TODO proper region
|
||||
Region::zero(),
|
||||
annotation.region,
|
||||
));
|
||||
|
||||
constrain_expr(
|
||||
|
|
|
@ -207,16 +207,7 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
|||
Type::Variable(var)
|
||||
}
|
||||
}
|
||||
Flex(var_id) => {
|
||||
if let Some(var) = free_vars.unnamed_vars.get(&var_id) {
|
||||
Type::Variable(*var)
|
||||
} else {
|
||||
let var = var_store.fresh();
|
||||
free_vars.unnamed_vars.insert(*var_id, var);
|
||||
|
||||
Type::Variable(var)
|
||||
}
|
||||
}
|
||||
Flex(var_id) => Type::Variable(var_id_to_flex_var(*var_id, free_vars, var_store)),
|
||||
Wildcard => {
|
||||
let var = var_store.fresh();
|
||||
free_vars.wildcards.push(var);
|
||||
|
@ -274,11 +265,11 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
|||
}
|
||||
Boolean(SolvedBool::SolvedShared) => Type::Boolean(Bool::Shared),
|
||||
Boolean(SolvedBool::SolvedContainer(solved_cvar, solved_mvars)) => {
|
||||
let cvar = var_id_to_var(*solved_cvar, free_vars, var_store);
|
||||
let cvar = var_id_to_flex_var(*solved_cvar, free_vars, var_store);
|
||||
|
||||
let mvars = solved_mvars
|
||||
.iter()
|
||||
.map(|var_id| var_id_to_var(*var_id, free_vars, var_store));
|
||||
.map(|var_id| var_id_to_flex_var(*var_id, free_vars, var_store));
|
||||
|
||||
Type::Boolean(Bool::container(cvar, mvars))
|
||||
}
|
||||
|
@ -298,7 +289,11 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
|||
}
|
||||
}
|
||||
|
||||
fn var_id_to_var(var_id: VarId, free_vars: &mut FreeVars, var_store: &mut VarStore) -> Variable {
|
||||
fn var_id_to_flex_var(
|
||||
var_id: VarId,
|
||||
free_vars: &mut FreeVars,
|
||||
var_store: &mut VarStore,
|
||||
) -> Variable {
|
||||
if let Some(var) = free_vars.unnamed_vars.get(&var_id) {
|
||||
*var
|
||||
} else {
|
||||
|
|
|
@ -52,6 +52,7 @@ fn headers_from_annotation_help(
|
|||
}
|
||||
Underscore
|
||||
| Shadowed(_, _)
|
||||
| MalformedPattern(_, _)
|
||||
| UnsupportedPattern(_)
|
||||
| NumLiteral(_, _)
|
||||
| IntLiteral(_)
|
||||
|
@ -117,7 +118,7 @@ pub fn constrain_pattern(
|
|||
state: &mut PatternState,
|
||||
) {
|
||||
match pattern {
|
||||
Underscore | UnsupportedPattern(_) | Shadowed(_, _) => {
|
||||
Underscore | UnsupportedPattern(_) | MalformedPattern(_, _) | Shadowed(_, _) => {
|
||||
// Neither the _ pattern nor erroneous ones add any constraints.
|
||||
}
|
||||
|
||||
|
|
|
@ -78,24 +78,33 @@ pub fn constrain_decls(
|
|||
sharing::annotate_usage(&def.loc_expr.value, &mut var_usage);
|
||||
}
|
||||
}
|
||||
Declaration::InvalidCycle(_, _) => panic!("TODO handle invalid cycle"),
|
||||
Declaration::InvalidCycle(_, _) => {
|
||||
// any usage of a value defined in an invalid cycle will blow up
|
||||
// so for the analysis usage by such values doesn't count
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aliases_to_attr_type(var_store, &mut aliases);
|
||||
|
||||
let mut env = Env {
|
||||
home,
|
||||
rigids: ImMap::default(),
|
||||
};
|
||||
|
||||
for decl in decls.iter().rev() {
|
||||
// NOTE: rigids are empty because they are not shared between top-level definitions
|
||||
// clear the set of rigids from the previous iteration.
|
||||
// rigids are not shared between top-level definitions.
|
||||
env.rigids.clear();
|
||||
|
||||
match decl {
|
||||
Declaration::Declare(def) | Declaration::Builtin(def) => {
|
||||
constraint = exists_with_aliases(
|
||||
aliases.clone(),
|
||||
Vec::new(),
|
||||
constrain_def(
|
||||
&Env {
|
||||
home,
|
||||
rigids: ImMap::default(),
|
||||
},
|
||||
&env,
|
||||
var_store,
|
||||
&var_usage,
|
||||
&mut ImSet::default(),
|
||||
|
@ -109,10 +118,7 @@ pub fn constrain_decls(
|
|||
aliases.clone(),
|
||||
Vec::new(),
|
||||
constrain_recursive_defs(
|
||||
&Env {
|
||||
home,
|
||||
rigids: ImMap::default(),
|
||||
},
|
||||
&env,
|
||||
var_store,
|
||||
&var_usage,
|
||||
&mut ImSet::default(),
|
||||
|
@ -121,7 +127,10 @@ pub fn constrain_decls(
|
|||
),
|
||||
);
|
||||
}
|
||||
Declaration::InvalidCycle(_, _) => panic!("TODO handle invalid cycle"),
|
||||
Declaration::InvalidCycle(_, _) => {
|
||||
// invalid cycles give a canonicalization error. we skip them here.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,7 +342,7 @@ fn constrain_pattern(
|
|||
state.constraints.push(tag_con);
|
||||
}
|
||||
|
||||
Underscore | Shadowed(_, _) | UnsupportedPattern(_) => {
|
||||
Underscore | Shadowed(_, _) | MalformedPattern(_, _) | UnsupportedPattern(_) => {
|
||||
// no constraints
|
||||
}
|
||||
}
|
||||
|
@ -1385,10 +1394,7 @@ pub fn constrain_expr(
|
|||
And(vec![Eq(fn_type, expected, category, region), record_con]),
|
||||
)
|
||||
}
|
||||
RuntimeError(_) => {
|
||||
// Runtime Errors have no constraints because they're going to crash.
|
||||
True
|
||||
}
|
||||
RuntimeError(_) => True,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1980,6 +1986,9 @@ fn aliases_to_attr_type(var_store: &mut VarStore, aliases: &mut SendMap<Symbol,
|
|||
_ => unreachable!("`annotation_to_attr_type` always gives back an Attr"),
|
||||
}
|
||||
|
||||
// Check that if the alias is a recursive tag union, all structures containing the
|
||||
// recursion variable get the same uniqueness as the recursion variable (and thus as the
|
||||
// recursive tag union itself)
|
||||
if let Some(b) = &alias.uniqueness {
|
||||
fix_mutual_recursive_alias(&mut alias.typ, b);
|
||||
}
|
||||
|
@ -2407,10 +2416,12 @@ fn fix_mutual_recursive_alias_help_help(rec_var: Variable, attribute: &Type, int
|
|||
}
|
||||
RecursiveTagUnion(_, tags, ext) | TagUnion(tags, ext) => {
|
||||
fix_mutual_recursive_alias_help(rec_var, attribute, ext);
|
||||
tags.iter_mut()
|
||||
.map(|v| v.1.iter_mut())
|
||||
.flatten()
|
||||
.for_each(|arg| fix_mutual_recursive_alias_help(rec_var, attribute, arg));
|
||||
|
||||
for (_tag, args) in tags.iter_mut() {
|
||||
for arg in args.iter_mut() {
|
||||
fix_mutual_recursive_alias_help(rec_var, attribute, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Record(fields, ext) => {
|
||||
|
@ -2420,7 +2431,8 @@ fn fix_mutual_recursive_alias_help_help(rec_var: Variable, attribute: &Type, int
|
|||
.for_each(|arg| fix_mutual_recursive_alias_help(rec_var, attribute, arg));
|
||||
}
|
||||
Alias(_, _, actual_type) => {
|
||||
fix_mutual_recursive_alias_help(rec_var, attribute, actual_type);
|
||||
// call help_help, because actual_type is not wrapped in ATTR
|
||||
fix_mutual_recursive_alias_help_help(rec_var, attribute, actual_type);
|
||||
}
|
||||
Apply(_, args) => {
|
||||
args.iter_mut()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue