mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Simplify pattern constraint generation
At the time we introduced presence constraints for tag unions, I added a "destruct_position" variable so that we didn't change the typechecking semantics for everything all at once, and because I wasn't totally sure what I was doing was correct. But now we're more confident in this approach, and every pattern is by definition a destructuring, so there is no need for this flag. Also should fix some potential bugs we didn't notice before with presence constraints in closure variables, though I can't find a good test to reproduce this, since closure variables are hidden from the user.
This commit is contained in:
parent
7e70f2e9ad
commit
f8c7349193
2 changed files with 39 additions and 90 deletions
|
@ -121,23 +121,6 @@ fn headers_from_annotation_help(
|
|||
}
|
||||
}
|
||||
|
||||
fn make_pattern_constraint(
|
||||
region: Region,
|
||||
category: PatternCategory,
|
||||
actual: Type,
|
||||
expected: PExpected<Type>,
|
||||
presence_con: bool,
|
||||
) -> Constraint {
|
||||
if presence_con {
|
||||
Constraint::Present(
|
||||
actual,
|
||||
PresenceConstraint::Pattern(region, category, expected),
|
||||
)
|
||||
} else {
|
||||
Constraint::Pattern(region, category, actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
/// This accepts PatternState (rather than returning it) so that the caller can
|
||||
/// initialize the Vecs in PatternState using with_capacity
|
||||
/// based on its knowledge of their lengths.
|
||||
|
@ -147,10 +130,9 @@ pub fn constrain_pattern(
|
|||
region: Region,
|
||||
expected: PExpected<Type>,
|
||||
state: &mut PatternState,
|
||||
destruct_position: bool,
|
||||
) {
|
||||
match pattern {
|
||||
Underscore if destruct_position => {
|
||||
Underscore => {
|
||||
// This is an underscore in a position where we destruct a variable,
|
||||
// like a when expression:
|
||||
// when x is
|
||||
|
@ -162,17 +144,15 @@ pub fn constrain_pattern(
|
|||
PresenceConstraint::IsOpen,
|
||||
));
|
||||
}
|
||||
Underscore | UnsupportedPattern(_) | MalformedPattern(_, _) | OpaqueNotInScope(..) => {
|
||||
// Neither the _ pattern nor erroneous ones add any constraints.
|
||||
UnsupportedPattern(_) | MalformedPattern(_, _) | OpaqueNotInScope(..) => {
|
||||
// Erroneous patterns don't add any constraints.
|
||||
}
|
||||
|
||||
Identifier(symbol) | Shadowed(_, _, symbol) => {
|
||||
if destruct_position {
|
||||
state.constraints.push(Constraint::Present(
|
||||
expected.get_type_ref().clone(),
|
||||
PresenceConstraint::IsOpen,
|
||||
));
|
||||
}
|
||||
state.constraints.push(Constraint::Present(
|
||||
expected.get_type_ref().clone(),
|
||||
PresenceConstraint::IsOpen,
|
||||
));
|
||||
state.headers.insert(
|
||||
*symbol,
|
||||
Loc {
|
||||
|
@ -305,41 +285,36 @@ pub fn constrain_pattern(
|
|||
|
||||
let field_type = match typ {
|
||||
DestructType::Guard(guard_var, loc_guard) => {
|
||||
state.constraints.push(make_pattern_constraint(
|
||||
region,
|
||||
PatternCategory::PatternGuard,
|
||||
state.constraints.push(Constraint::Present(
|
||||
Type::Variable(*guard_var),
|
||||
PExpected::ForReason(
|
||||
PReason::PatternGuard,
|
||||
pat_type.clone(),
|
||||
loc_guard.region,
|
||||
PresenceConstraint::Pattern(
|
||||
region,
|
||||
PatternCategory::PatternGuard,
|
||||
PExpected::ForReason(
|
||||
PReason::PatternGuard,
|
||||
pat_type.clone(),
|
||||
loc_guard.region,
|
||||
),
|
||||
),
|
||||
destruct_position,
|
||||
));
|
||||
state.vars.push(*guard_var);
|
||||
|
||||
constrain_pattern(
|
||||
env,
|
||||
&loc_guard.value,
|
||||
loc_guard.region,
|
||||
expected,
|
||||
state,
|
||||
destruct_position,
|
||||
);
|
||||
constrain_pattern(env, &loc_guard.value, loc_guard.region, expected, state);
|
||||
|
||||
RecordField::Demanded(pat_type)
|
||||
}
|
||||
DestructType::Optional(expr_var, loc_expr) => {
|
||||
state.constraints.push(make_pattern_constraint(
|
||||
region,
|
||||
PatternCategory::PatternDefault,
|
||||
state.constraints.push(Constraint::Present(
|
||||
Type::Variable(*expr_var),
|
||||
PExpected::ForReason(
|
||||
PReason::OptionalField,
|
||||
pat_type.clone(),
|
||||
loc_expr.region,
|
||||
PresenceConstraint::Pattern(
|
||||
region,
|
||||
PatternCategory::PatternDefault,
|
||||
PExpected::ForReason(
|
||||
PReason::OptionalField,
|
||||
pat_type.clone(),
|
||||
loc_expr.region,
|
||||
),
|
||||
),
|
||||
destruct_position,
|
||||
));
|
||||
|
||||
state.vars.push(*expr_var);
|
||||
|
@ -376,12 +351,9 @@ pub fn constrain_pattern(
|
|||
region,
|
||||
);
|
||||
|
||||
let record_con = make_pattern_constraint(
|
||||
region,
|
||||
PatternCategory::Record,
|
||||
let record_con = Constraint::Present(
|
||||
Type::Variable(*whole_var),
|
||||
expected,
|
||||
destruct_position,
|
||||
PresenceConstraint::Pattern(region, PatternCategory::Record, expected),
|
||||
);
|
||||
|
||||
state.constraints.push(whole_con);
|
||||
|
@ -408,39 +380,21 @@ pub fn constrain_pattern(
|
|||
pattern_type,
|
||||
region,
|
||||
);
|
||||
constrain_pattern(
|
||||
env,
|
||||
&loc_pattern.value,
|
||||
loc_pattern.region,
|
||||
expected,
|
||||
state,
|
||||
destruct_position,
|
||||
);
|
||||
constrain_pattern(env, &loc_pattern.value, loc_pattern.region, expected, state);
|
||||
}
|
||||
|
||||
let whole_con = if destruct_position {
|
||||
Constraint::Present(
|
||||
expected.clone().get_type(),
|
||||
PresenceConstraint::IncludesTag(tag_name.clone(), argument_types.clone()),
|
||||
)
|
||||
} else {
|
||||
Constraint::Eq(
|
||||
Type::Variable(*whole_var),
|
||||
Expected::NoExpectation(Type::TagUnion(
|
||||
vec![(tag_name.clone(), argument_types)],
|
||||
Box::new(Type::Variable(*ext_var)),
|
||||
)),
|
||||
Category::Storage(std::file!(), std::line!()),
|
||||
region,
|
||||
)
|
||||
};
|
||||
let whole_con = Constraint::Present(
|
||||
expected.clone().get_type(),
|
||||
PresenceConstraint::IncludesTag(tag_name.clone(), argument_types.clone()),
|
||||
);
|
||||
|
||||
let tag_con = make_pattern_constraint(
|
||||
region,
|
||||
PatternCategory::Ctor(tag_name.clone()),
|
||||
let tag_con = Constraint::Present(
|
||||
Type::Variable(*whole_var),
|
||||
expected,
|
||||
destruct_position,
|
||||
PresenceConstraint::Pattern(
|
||||
region,
|
||||
PatternCategory::Ctor(tag_name.clone()),
|
||||
expected,
|
||||
),
|
||||
);
|
||||
|
||||
state.vars.push(*whole_var);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue