From dd56fdb61cdb726d5cbeb605dfd8f6540f776fc0 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Fri, 8 Apr 2022 21:31:19 -0400 Subject: [PATCH] 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. --- compiler/constrain/src/expr.rs | 134 +++++++++++++++------------------ 1 file changed, 60 insertions(+), 74 deletions(-) diff --git a/compiler/constrain/src/expr.rs b/compiler/constrain/src/expr.rs index 893860290b..f3932cf06b 100644 --- a/compiler/constrain/src/expr.rs +++ b/compiler/constrain/src/expr.rs @@ -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, - region: Region, - variant_var: Variable, - ext_var: Variable, - name: &TagName, - arguments: &[(Variable, Loc)], -) -> 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) -}