mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
constrain whole_var
This commit is contained in:
parent
2e697ee8f9
commit
38c93c001f
2 changed files with 89 additions and 26 deletions
|
@ -58,7 +58,7 @@ fn headers_from_annotation_help(
|
||||||
| FloatLiteral(_)
|
| FloatLiteral(_)
|
||||||
| StrLiteral(_) => true,
|
| StrLiteral(_) => true,
|
||||||
|
|
||||||
RecordDestructure(_, destructs) => match annotation.value.shallow_dealias() {
|
RecordDestructure { destructs, .. } => match annotation.value.shallow_dealias() {
|
||||||
Type::Record(fields, _) => {
|
Type::Record(fields, _) => {
|
||||||
for destruct in destructs {
|
for destruct in destructs {
|
||||||
// NOTE ignores the .guard field.
|
// NOTE ignores the .guard field.
|
||||||
|
@ -77,7 +77,11 @@ fn headers_from_annotation_help(
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
|
||||||
AppliedTag(_, tag_name, arguments) => match annotation.value.shallow_dealias() {
|
AppliedTag {
|
||||||
|
tag_name,
|
||||||
|
arguments,
|
||||||
|
..
|
||||||
|
} => match annotation.value.shallow_dealias() {
|
||||||
Type::TagUnion(tags, _) => {
|
Type::TagUnion(tags, _) => {
|
||||||
if let Some((_, arg_types)) = tags.iter().find(|(name, _)| name == tag_name) {
|
if let Some((_, arg_types)) = tags.iter().find(|(name, _)| name == tag_name) {
|
||||||
if !arguments.len() == arg_types.len() {
|
if !arguments.len() == arg_types.len() {
|
||||||
|
@ -164,7 +168,12 @@ pub fn constrain_pattern(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordDestructure(ext_var, patterns) => {
|
RecordDestructure {
|
||||||
|
whole_var,
|
||||||
|
ext_var,
|
||||||
|
destructs,
|
||||||
|
} => {
|
||||||
|
state.vars.push(*whole_var);
|
||||||
state.vars.push(*ext_var);
|
state.vars.push(*ext_var);
|
||||||
let ext_type = Type::Variable(*ext_var);
|
let ext_type = Type::Variable(*ext_var);
|
||||||
|
|
||||||
|
@ -179,7 +188,7 @@ pub fn constrain_pattern(
|
||||||
guard,
|
guard,
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} in patterns
|
} in destructs
|
||||||
{
|
{
|
||||||
let pat_type = Type::Variable(*var);
|
let pat_type = Type::Variable(*var);
|
||||||
let expected = PExpected::NoExpectation(pat_type.clone());
|
let expected = PExpected::NoExpectation(pat_type.clone());
|
||||||
|
@ -207,14 +216,31 @@ pub fn constrain_pattern(
|
||||||
}
|
}
|
||||||
|
|
||||||
let record_type = Type::Record(field_types, Box::new(ext_type));
|
let record_type = Type::Record(field_types, Box::new(ext_type));
|
||||||
let record_con =
|
|
||||||
Constraint::Pattern(region, PatternCategory::Record, record_type, expected);
|
|
||||||
|
|
||||||
|
let whole_con = Constraint::Eq(
|
||||||
|
Type::Variable(*whole_var),
|
||||||
|
Expected::NoExpectation(record_type),
|
||||||
|
region,
|
||||||
|
);
|
||||||
|
|
||||||
|
let record_con = Constraint::Pattern(
|
||||||
|
region,
|
||||||
|
PatternCategory::Record,
|
||||||
|
Type::Variable(*whole_var),
|
||||||
|
expected,
|
||||||
|
);
|
||||||
|
|
||||||
|
state.constraints.push(whole_con);
|
||||||
state.constraints.push(record_con);
|
state.constraints.push(record_con);
|
||||||
}
|
}
|
||||||
AppliedTag(ext_var, tag_name, patterns) => {
|
AppliedTag {
|
||||||
let mut argument_types = Vec::with_capacity(patterns.len());
|
whole_var,
|
||||||
for (pattern_var, loc_pattern) in patterns {
|
ext_var,
|
||||||
|
tag_name,
|
||||||
|
arguments,
|
||||||
|
} => {
|
||||||
|
let mut argument_types = Vec::with_capacity(arguments.len());
|
||||||
|
for (pattern_var, loc_pattern) in arguments {
|
||||||
state.vars.push(*pattern_var);
|
state.vars.push(*pattern_var);
|
||||||
|
|
||||||
let pattern_type = Type::Variable(*pattern_var);
|
let pattern_type = Type::Variable(*pattern_var);
|
||||||
|
@ -224,17 +250,25 @@ pub fn constrain_pattern(
|
||||||
constrain_pattern(&loc_pattern.value, loc_pattern.region, expected, state);
|
constrain_pattern(&loc_pattern.value, loc_pattern.region, expected, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let whole_con = Constraint::Eq(
|
||||||
|
Type::Variable(*whole_var),
|
||||||
|
Expected::NoExpectation(Type::TagUnion(
|
||||||
|
vec![(tag_name.clone(), argument_types)],
|
||||||
|
Box::new(Type::Variable(*ext_var)),
|
||||||
|
)),
|
||||||
|
region,
|
||||||
|
);
|
||||||
|
|
||||||
let tag_con = Constraint::Pattern(
|
let tag_con = Constraint::Pattern(
|
||||||
region,
|
region,
|
||||||
PatternCategory::Ctor(tag_name.clone()),
|
PatternCategory::Ctor(tag_name.clone()),
|
||||||
Type::TagUnion(
|
Type::Variable(*whole_var),
|
||||||
vec![(tag_name.clone(), argument_types)],
|
|
||||||
Box::new(Type::Variable(*ext_var)),
|
|
||||||
),
|
|
||||||
expected,
|
expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.vars.push(*whole_var);
|
||||||
state.vars.push(*ext_var);
|
state.vars.push(*ext_var);
|
||||||
|
state.constraints.push(whole_con);
|
||||||
state.constraints.push(tag_con);
|
state.constraints.push(tag_con);
|
||||||
}
|
}
|
||||||
Shadowed(_, _) => {
|
Shadowed(_, _) => {
|
||||||
|
|
|
@ -143,6 +143,8 @@ fn constrain_pattern(
|
||||||
use roc_can::pattern::Pattern::*;
|
use roc_can::pattern::Pattern::*;
|
||||||
use roc_types::types::PatternCategory;
|
use roc_types::types::PatternCategory;
|
||||||
|
|
||||||
|
let region = pattern.region;
|
||||||
|
|
||||||
match &pattern.value {
|
match &pattern.value {
|
||||||
Identifier(symbol) => {
|
Identifier(symbol) => {
|
||||||
state.headers.insert(
|
state.headers.insert(
|
||||||
|
@ -190,10 +192,15 @@ fn constrain_pattern(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordDestructure(ext_var, patterns) => {
|
RecordDestructure {
|
||||||
|
whole_var,
|
||||||
|
ext_var,
|
||||||
|
destructs,
|
||||||
|
} => {
|
||||||
// TODO if a subpattern doesn't bind any identifiers, it doesn't count for uniqueness
|
// TODO if a subpattern doesn't bind any identifiers, it doesn't count for uniqueness
|
||||||
let mut pattern_uniq_vars = Vec::with_capacity(patterns.len());
|
let mut pattern_uniq_vars = Vec::with_capacity(destructs.len());
|
||||||
|
|
||||||
|
state.vars.push(*whole_var);
|
||||||
state.vars.push(*ext_var);
|
state.vars.push(*ext_var);
|
||||||
let ext_type = Type::Variable(*ext_var);
|
let ext_type = Type::Variable(*ext_var);
|
||||||
|
|
||||||
|
@ -207,7 +214,7 @@ fn constrain_pattern(
|
||||||
guard,
|
guard,
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
} in patterns
|
} in destructs
|
||||||
{
|
{
|
||||||
let pat_uniq_var = var_store.fresh();
|
let pat_uniq_var = var_store.fresh();
|
||||||
pattern_uniq_vars.push(pat_uniq_var);
|
pattern_uniq_vars.push(pat_uniq_var);
|
||||||
|
@ -251,22 +258,35 @@ fn constrain_pattern(
|
||||||
record_uniq_type,
|
record_uniq_type,
|
||||||
Type::Record(field_types, Box::new(ext_type)),
|
Type::Record(field_types, Box::new(ext_type)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let whole_con = Constraint::Eq(
|
||||||
|
Type::Variable(*whole_var),
|
||||||
|
Expected::NoExpectation(record_type),
|
||||||
|
region,
|
||||||
|
);
|
||||||
|
|
||||||
let record_con = Constraint::Pattern(
|
let record_con = Constraint::Pattern(
|
||||||
pattern.region,
|
region,
|
||||||
PatternCategory::Record,
|
PatternCategory::Record,
|
||||||
record_type,
|
Type::Variable(*whole_var),
|
||||||
expected,
|
expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.constraints.push(whole_con);
|
||||||
state.constraints.push(record_con);
|
state.constraints.push(record_con);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppliedTag(ext_var, symbol, patterns) => {
|
AppliedTag {
|
||||||
|
whole_var,
|
||||||
|
ext_var,
|
||||||
|
tag_name,
|
||||||
|
arguments,
|
||||||
|
} => {
|
||||||
// TODO if a subpattern doesn't bind any identifiers, it doesn't count for uniqueness
|
// TODO if a subpattern doesn't bind any identifiers, it doesn't count for uniqueness
|
||||||
let mut argument_types = Vec::with_capacity(patterns.len());
|
let mut argument_types = Vec::with_capacity(arguments.len());
|
||||||
let mut pattern_uniq_vars = Vec::with_capacity(patterns.len());
|
let mut pattern_uniq_vars = Vec::with_capacity(arguments.len());
|
||||||
|
|
||||||
for (pattern_var, loc_pattern) in patterns {
|
for (pattern_var, loc_pattern) in arguments {
|
||||||
state.vars.push(*pattern_var);
|
state.vars.push(*pattern_var);
|
||||||
|
|
||||||
let pat_uniq_var = var_store.fresh();
|
let pat_uniq_var = var_store.fresh();
|
||||||
|
@ -292,19 +312,28 @@ fn constrain_pattern(
|
||||||
let union_type = attr_type(
|
let union_type = attr_type(
|
||||||
tag_union_uniq_type,
|
tag_union_uniq_type,
|
||||||
Type::TagUnion(
|
Type::TagUnion(
|
||||||
vec![(symbol.clone(), argument_types)],
|
vec![(tag_name.clone(), argument_types)],
|
||||||
Box::new(Type::Variable(*ext_var)),
|
Box::new(Type::Variable(*ext_var)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let whole_con = Constraint::Eq(
|
||||||
|
Type::Variable(*whole_var),
|
||||||
|
Expected::NoExpectation(union_type),
|
||||||
|
region,
|
||||||
|
);
|
||||||
|
|
||||||
let tag_con = Constraint::Pattern(
|
let tag_con = Constraint::Pattern(
|
||||||
pattern.region,
|
region,
|
||||||
PatternCategory::Ctor(symbol.clone()),
|
PatternCategory::Ctor(tag_name.clone()),
|
||||||
union_type,
|
Type::Variable(*whole_var),
|
||||||
expected,
|
expected,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
state.vars.push(*whole_var);
|
||||||
state.vars.push(*ext_var);
|
state.vars.push(*ext_var);
|
||||||
|
|
||||||
|
state.constraints.push(whole_con);
|
||||||
state.constraints.push(tag_con);
|
state.constraints.push(tag_con);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue