diff --git a/compiler/constrain/src/expr.rs b/compiler/constrain/src/expr.rs index eac7d8f1fc..c0356f2368 100644 --- a/compiler/constrain/src/expr.rs +++ b/compiler/constrain/src/expr.rs @@ -739,11 +739,10 @@ pub fn constrain_expr( region, ); - let ext = Type::Variable(*closure_var); - let lambda_set = Type::TagUnion( - vec![(TagName::Closure(*closure_name), vec![])], - Box::new(ext), - ); + let lambda_set = Type::ClosureTag { + name: *closure_name, + ext: *closure_var, + }; let function_type = Type::Function( vec![record_type], @@ -1416,7 +1415,7 @@ fn constrain_closure_size( )); } - let tag_name = roc_module::ident::TagName::Closure(name); + let tag_name = TagName::Closure(name); let closure_type = Type::TagUnion( vec![(tag_name, tag_arguments)], Box::new(Type::Variable(closure_ext_var)), diff --git a/compiler/solve/src/solve.rs b/compiler/solve/src/solve.rs index c4a4eb98dc..d9ce0d3153 100644 --- a/compiler/solve/src/solve.rs +++ b/compiler/solve/src/solve.rs @@ -690,6 +690,19 @@ fn type_to_variable<'a>( EmptyRec => Variable::EMPTY_RECORD, EmptyTagUnion => Variable::EMPTY_TAG_UNION, + ClosureTag { name, ext } => { + let tag_name = TagName::Closure(*name); + let tag_names = SubsSlice::new(subs.tag_names.len() as u32, 1); + + subs.tag_names.push(tag_name); + + let union_tags = UnionTags::from_slices(tag_names, SubsSlice::default()); + + let content = Content::Structure(FlatType::TagUnion(union_tags, *ext)); + + register(subs, rank, pools, content) + } + // This case is important for the rank of boolean variables Function(arguments, closure_type, ret_type) => { let new_arguments = VariableSubsSlice::reserve_into_subs(subs, arguments.len()); diff --git a/compiler/types/src/solved_types.rs b/compiler/types/src/solved_types.rs index 2473597a35..3fe67edf2f 100644 --- a/compiler/types/src/solved_types.rs +++ b/compiler/types/src/solved_types.rs @@ -130,6 +130,11 @@ impl SolvedType { ext: Box::new(solved_ext), } } + ClosureTag { name, ext } => { + let solved_ext = Self::from_type(solved_subs, &Type::Variable(*ext)); + let solved_tags = vec![(TagName::Closure(*name), vec![])]; + SolvedType::TagUnion(solved_tags, Box::new(solved_ext)) + } TagUnion(tags, box_ext) => { let solved_ext = Self::from_type(solved_subs, box_ext); let mut solved_tags = Vec::with_capacity(tags.len()); diff --git a/compiler/types/src/types.rs b/compiler/types/src/types.rs index 96e0190a43..04130e2484 100644 --- a/compiler/types/src/types.rs +++ b/compiler/types/src/types.rs @@ -169,6 +169,11 @@ pub enum Type { Record(SendMap>, Box), TagUnion(Vec<(TagName, Vec)>, Box), FunctionOrTagUnion(TagName, Symbol, Box), + /// A function name that is used in our defunctionalization algorithm + ClosureTag { + name: Symbol, + ext: Variable, + }, Alias { symbol: Symbol, type_arguments: Vec<(Lowercase, Type)>, @@ -378,6 +383,15 @@ impl fmt::Debug for Type { } } } + Type::ClosureTag { name, ext } => { + write!(f, "ClosureTag(")?; + + name.fmt(f)?; + write!(f, ", ")?; + ext.fmt(f)?; + + write!(f, ")") + } Type::RecursiveTagUnion(rec, tags, ext) => { write!(f, "[")?; @@ -462,7 +476,7 @@ impl Type { use Type::*; match self { - Variable(v) => { + ClosureTag { ext: v, .. } | Variable(v) => { if let Some(replacement) = substitutions.get(v) { *self = replacement.clone(); } @@ -590,7 +604,7 @@ impl Type { arg.substitute_alias(rep_symbol, actual); } } - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => {} + EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {} } } @@ -627,7 +641,7 @@ impl Type { } Apply(symbol, _) if *symbol == rep_symbol => true, Apply(_, args) => args.iter().any(|arg| arg.contains_symbol(rep_symbol)), - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => false, + EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => false, } } @@ -635,7 +649,7 @@ impl Type { use Type::*; match self { - Variable(v) => *v == rep_variable, + ClosureTag { ext: v, .. } | Variable(v) => *v == rep_variable, Function(args, closure, ret) => { ret.contains_variable(rep_variable) || closure.contains_variable(rep_variable) @@ -819,7 +833,7 @@ impl Type { } } } - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => {} + EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {} } } } @@ -872,7 +886,7 @@ fn symbols_help(tipe: &Type, accum: &mut ImSet) { accum.insert(*symbol); args.iter().for_each(|arg| symbols_help(arg, accum)); } - EmptyRec | EmptyTagUnion | Erroneous(_) | Variable(_) => {} + EmptyRec | EmptyTagUnion | ClosureTag { .. } | Erroneous(_) | Variable(_) => {} } } @@ -882,7 +896,7 @@ fn variables_help(tipe: &Type, accum: &mut ImSet) { match tipe { EmptyRec | EmptyTagUnion | Erroneous(_) => (), - Variable(v) => { + ClosureTag { ext: v, .. } | Variable(v) => { accum.insert(*v); } @@ -979,7 +993,7 @@ fn variables_help_detailed(tipe: &Type, accum: &mut VariableDetail) { match tipe { EmptyRec | EmptyTagUnion | Erroneous(_) => (), - Variable(v) => { + ClosureTag { ext: v, .. } | Variable(v) => { accum.type_variables.insert(*v); }