mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 15:27:45 +03:00
Constrain optional record fields
This commit is contained in:
parent
8fc9a450b3
commit
1409421de2
@ -9,7 +9,7 @@ use roc_region::all::{Located, Region};
|
||||
use roc_types::boolean_algebra::Bool;
|
||||
use roc_types::solved_types::{BuiltinAlias, SolvedBool, SolvedType};
|
||||
use roc_types::subs::{VarId, VarStore, Variable};
|
||||
use roc_types::types::{Alias, Problem, Type};
|
||||
use roc_types::types::{Alias, Problem, RecordField, Type};
|
||||
|
||||
pub type SubsByModule = MutMap<ModuleId, ExposedModuleTypes>;
|
||||
|
||||
@ -214,10 +214,17 @@ fn to_type(solved_type: &SolvedType, free_vars: &mut FreeVars, var_store: &mut V
|
||||
Type::Variable(var)
|
||||
}
|
||||
Record { fields, ext } => {
|
||||
use RecordField::*;
|
||||
|
||||
let mut new_fields = SendMap::default();
|
||||
|
||||
for (label, typ) in fields {
|
||||
new_fields.insert(label.clone(), to_type(&typ, free_vars, var_store));
|
||||
for (label, field) in fields {
|
||||
let field_val = match field {
|
||||
Required(typ) => Required(to_type(&typ, free_vars, var_store)),
|
||||
Optional(typ) => Optional(to_type(&typ, free_vars, var_store)),
|
||||
};
|
||||
|
||||
new_fields.insert(label.clone(), field_val);
|
||||
}
|
||||
|
||||
Type::Record(new_fields, Box::new(to_type(ext, free_vars, var_store)))
|
||||
|
@ -2,13 +2,13 @@ use crate::builtins;
|
||||
use roc_can::constraint::Constraint;
|
||||
use roc_can::expected::{Expected, PExpected};
|
||||
use roc_can::pattern::Pattern::{self, *};
|
||||
use roc_can::pattern::RecordDestruct;
|
||||
use roc_can::pattern::{DestructType, RecordDestruct};
|
||||
use roc_collections::all::{Index, SendMap};
|
||||
use roc_module::ident::Lowercase;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_region::all::{Located, Region};
|
||||
use roc_types::subs::Variable;
|
||||
use roc_types::types::{Category, PReason, PatternCategory, Type};
|
||||
use roc_types::types::{Category, PReason, PatternCategory, RecordField, Type};
|
||||
|
||||
pub struct PatternState {
|
||||
pub headers: SendMap<Symbol, Located<Type>>,
|
||||
@ -61,12 +61,20 @@ fn headers_from_annotation_help(
|
||||
|
||||
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
||||
Type::Record(fields, _) => {
|
||||
for destruct in destructs {
|
||||
// NOTE ignores the .guard field.
|
||||
if let Some(field_type) = fields.get(&destruct.value.label) {
|
||||
for loc_destruct in destructs {
|
||||
let destruct = &loc_destruct.value;
|
||||
|
||||
// NOTE: We ignore both Guard and optionality when
|
||||
// determining the type of the assigned def (which is what
|
||||
// gets added to the header here).
|
||||
//
|
||||
// For example, no matter whether it's `{ x } = rec` or
|
||||
// `{ 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) {
|
||||
headers.insert(
|
||||
destruct.value.symbol,
|
||||
Located::at(annotation.region, field_type.clone()),
|
||||
destruct.symbol,
|
||||
Located::at(annotation.region, field_type.clone().into_inner()),
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
@ -179,7 +187,7 @@ pub fn constrain_pattern(
|
||||
state.vars.push(*ext_var);
|
||||
let ext_type = Type::Variable(*ext_var);
|
||||
|
||||
let mut field_types: SendMap<Lowercase, Type> = SendMap::default();
|
||||
let mut field_types: SendMap<Lowercase, RecordField<Type>> = SendMap::default();
|
||||
|
||||
for Located {
|
||||
value:
|
||||
@ -187,7 +195,7 @@ pub fn constrain_pattern(
|
||||
var,
|
||||
label,
|
||||
symbol,
|
||||
guard,
|
||||
typ,
|
||||
},
|
||||
..
|
||||
} in destructs
|
||||
@ -201,9 +209,8 @@ pub fn constrain_pattern(
|
||||
.insert(*symbol, Located::at(region, pat_type.clone()));
|
||||
}
|
||||
|
||||
field_types.insert(label.clone(), pat_type.clone());
|
||||
|
||||
if let Some((guard_var, loc_guard)) = guard {
|
||||
let field_type = match typ {
|
||||
DestructType::Guard(guard_var, loc_guard) => {
|
||||
state.constraints.push(Constraint::Pattern(
|
||||
region,
|
||||
PatternCategory::PatternGuard,
|
||||
@ -217,7 +224,21 @@ pub fn constrain_pattern(
|
||||
state.vars.push(*guard_var);
|
||||
|
||||
constrain_pattern(&loc_guard.value, loc_guard.region, expected, state);
|
||||
|
||||
RecordField::Required(pat_type)
|
||||
}
|
||||
DestructType::Optional(_var) => {
|
||||
todo!("Add a constraint for the default value.");
|
||||
|
||||
// RecordField::Optional(pat_type)
|
||||
}
|
||||
DestructType::Required => {
|
||||
// No extra constraints necessary.
|
||||
RecordField::Required(pat_type)
|
||||
}
|
||||
};
|
||||
|
||||
field_types.insert(label.clone(), field_type);
|
||||
|
||||
state.vars.push(*var);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user