Fix regression with ZeroArgumentTag constraint gen

Turns out it can't share quite that much code with Tag,
because doing so skips the important function-based
constraints.
This commit is contained in:
Richard Feldman 2022-04-08 21:31:19 -04:00
parent b2ff785a5e
commit dd56fdb61c
No known key found for this signature in database
GPG Key ID: 7E4127D1E4241798

View File

@ -880,31 +880,70 @@ pub fn constrain_expr(
ext_var,
name,
arguments,
} => constrain_tag(
constraints,
env,
expected,
region,
*variant_var,
*ext_var,
name,
arguments,
),
} => {
// +2 because we push all the arguments, plus variant_var and ext_var
let num_vars = arguments.len() + 2;
let mut vars = Vec::with_capacity(num_vars);
let mut types = Vec::with_capacity(arguments.len());
let mut arg_cons = Vec::with_capacity(arguments.len());
for (var, loc_expr) in arguments {
let arg_con = constrain_expr(
constraints,
env,
loc_expr.region,
&loc_expr.value,
Expected::NoExpectation(Type::Variable(*var)),
);
arg_cons.push(arg_con);
vars.push(*var);
types.push(Type::Variable(*var));
}
let union_con = constraints.equal_types_with_storage(
Type::TagUnion(
vec![(name.clone(), types)],
TypeExtension::from_type(Type::Variable(*ext_var)),
),
expected.clone(),
Category::TagApply {
tag_name: name.clone(),
args_count: arguments.len(),
},
region,
*variant_var,
);
vars.push(*variant_var);
vars.push(*ext_var);
arg_cons.push(union_con);
constraints.exists_many(vars, arg_cons)
}
ZeroArgumentTag {
variant_var,
ext_var,
name,
closure_name: _,
} => constrain_tag(
constraints,
env,
expected,
region,
*variant_var,
*ext_var,
name,
&[],
),
closure_name,
} => {
let union_con = constraints.equal_types_with_storage(
Type::FunctionOrTagUnion(
name.clone(),
*closure_name,
TypeExtension::from_type(Type::Variable(*ext_var)),
),
expected.clone(),
Category::TagApply {
tag_name: name.clone(),
args_count: 0,
},
region,
*variant_var,
);
constraints.exists_many(vec![*variant_var, *ext_var], vec![union_con])
}
OpaqueRef {
opaque_var,
name,
@ -1986,56 +2025,3 @@ fn constrain_field_update(
(var, field_type, con)
}
#[allow(clippy::too_many_arguments)]
fn constrain_tag(
constraints: &mut Constraints,
env: &Env,
expected: Expected<Type>,
region: Region,
variant_var: Variable,
ext_var: Variable,
name: &TagName,
arguments: &[(Variable, Loc<Expr>)],
) -> Constraint {
// +2 because we push all the arguments, plus variant_var and ext_var
let num_vars = arguments.len() + 2;
let mut vars = Vec::with_capacity(num_vars);
let mut types = Vec::with_capacity(arguments.len());
let mut arg_cons = Vec::with_capacity(arguments.len());
for (var, loc_expr) in arguments {
let arg_con = constrain_expr(
constraints,
env,
loc_expr.region,
&loc_expr.value,
Expected::NoExpectation(Type::Variable(*var)),
);
arg_cons.push(arg_con);
vars.push(*var);
types.push(Type::Variable(*var));
}
let union_con = constraints.equal_types_with_storage(
Type::TagUnion(
vec![(name.clone(), types)],
TypeExtension::from_type(Type::Variable(ext_var)),
),
expected,
Category::TagApply {
tag_name: name.clone(),
args_count: arguments.len(),
},
region,
variant_var,
);
vars.push(variant_var);
vars.push(ext_var);
arg_cons.push(union_con);
constraints.exists_many(vars, arg_cons)
}