mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-21 15:59:20 +03:00
Merge pull request #5028 from roc-lang/i5026
Do not fixup recursion pointers in non-recursive lambda sets
This commit is contained in:
commit
c8d418218e
@ -1,4 +1,5 @@
|
||||
use crate::ir::Parens;
|
||||
use crate::layout::intern::NeedsRecursionPointerFixup;
|
||||
use bitvec::vec::BitVec;
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
@ -1883,12 +1884,16 @@ impl<'a> LambdaSet<'a> {
|
||||
);
|
||||
cache_criteria.and(criteria);
|
||||
|
||||
let needs_recursive_fixup = NeedsRecursionPointerFixup(
|
||||
opt_recursion_var.is_some() && set_captures_have_naked_rec_ptr,
|
||||
);
|
||||
|
||||
let lambda_set = env.cache.interner.insert_lambda_set(
|
||||
env.arena,
|
||||
fn_args,
|
||||
ret,
|
||||
env.arena.alloc(set.into_bump_slice()),
|
||||
set_captures_have_naked_rec_ptr,
|
||||
needs_recursive_fixup,
|
||||
representation,
|
||||
);
|
||||
|
||||
@ -1902,7 +1907,7 @@ impl<'a> LambdaSet<'a> {
|
||||
fn_args,
|
||||
ret,
|
||||
&(&[] as &[(Symbol, &[InLayout])]),
|
||||
false,
|
||||
NeedsRecursionPointerFixup(false),
|
||||
Layout::UNIT,
|
||||
);
|
||||
Cacheable(Ok(lambda_set), cache_criteria)
|
||||
|
@ -121,6 +121,13 @@ impl<'a> Layout<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a recursive lambda set being inserted into an interner needs fixing-up of naked
|
||||
/// recursion pointers in the capture set.
|
||||
/// Applicable only if
|
||||
/// - the lambda set is indeed recursive, and
|
||||
/// - its capture set contain naked pointer references
|
||||
pub struct NeedsRecursionPointerFixup(pub bool);
|
||||
|
||||
pub trait LayoutInterner<'a>: Sized {
|
||||
/// Interns a value, returning its interned representation.
|
||||
/// If the value has been interned before, the old interned representation will be re-used.
|
||||
@ -139,7 +146,7 @@ pub trait LayoutInterner<'a>: Sized {
|
||||
args: &'a &'a [InLayout<'a>],
|
||||
ret: InLayout<'a>,
|
||||
set: &'a &'a [(Symbol, &'a [InLayout<'a>])],
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
representation: InLayout<'a>,
|
||||
) -> LambdaSet<'a>;
|
||||
|
||||
@ -550,7 +557,7 @@ impl<'a> GlobalLayoutInterner<'a> {
|
||||
&self,
|
||||
arena: &'a Bump,
|
||||
normalized: LambdaSet<'a>,
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
normalized_hash: u64,
|
||||
) -> WrittenGlobalLambdaSet<'a> {
|
||||
let mut normalized_lambda_set_map = self.0.normalized_lambda_set_map.lock();
|
||||
@ -574,7 +581,7 @@ impl<'a> GlobalLayoutInterner<'a> {
|
||||
let slot = unsafe { InLayout::from_index(vec.len()) };
|
||||
vec.push(Layout::VOID_NAKED);
|
||||
|
||||
let set = if set_may_have_naked_rec_ptr {
|
||||
let set = if needs_recursive_fixup.0 {
|
||||
let mut interner = LockedGlobalInterner {
|
||||
map: &mut map,
|
||||
normalized_lambda_set_map: &mut normalized_lambda_set_map,
|
||||
@ -708,7 +715,7 @@ impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> {
|
||||
args: &'a &'a [InLayout<'a>],
|
||||
ret: InLayout<'a>,
|
||||
set: &'a &'a [(Symbol, &'a [InLayout<'a>])],
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
representation: InLayout<'a>,
|
||||
) -> LambdaSet<'a> {
|
||||
// The tricky bit of inserting a lambda set is we need to fill in the `full_layout` only
|
||||
@ -737,7 +744,7 @@ impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> {
|
||||
} = global.get_or_insert_hashed_normalized_lambda_set(
|
||||
arena,
|
||||
normalized,
|
||||
set_may_have_naked_rec_ptr,
|
||||
needs_recursive_fixup,
|
||||
normalized_hash,
|
||||
);
|
||||
|
||||
@ -865,7 +872,7 @@ macro_rules! st_impl {
|
||||
args: &'a &'a [InLayout<'a>],
|
||||
ret: InLayout<'a>,
|
||||
set: &'a &'a [(Symbol, &'a [InLayout<'a>])],
|
||||
set_may_have_naked_rec_ptr: bool,
|
||||
needs_recursive_fixup: NeedsRecursionPointerFixup,
|
||||
representation: InLayout<'a>,
|
||||
) -> LambdaSet<'a> {
|
||||
// IDEA:
|
||||
@ -884,7 +891,7 @@ macro_rules! st_impl {
|
||||
let slot = unsafe { InLayout::from_index(self.vec.len()) };
|
||||
self.vec.push(Layout::VOID_NAKED);
|
||||
|
||||
let set = if set_may_have_naked_rec_ptr {
|
||||
let set = if needs_recursive_fixup.0 {
|
||||
reify::reify_lambda_set_captures(arena, self, slot, set)
|
||||
} else {
|
||||
set
|
||||
@ -957,7 +964,7 @@ mod reify {
|
||||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner};
|
||||
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
// TODO: if recursion becomes a problem we could make this iterative
|
||||
pub fn reify_recursive_layout<'a>(
|
||||
@ -1103,7 +1110,8 @@ mod reify {
|
||||
arena.alloc(args),
|
||||
ret,
|
||||
arena.alloc(set),
|
||||
true,
|
||||
// All nested recursive pointers should been fixed up, since we just did that above.
|
||||
NeedsRecursionPointerFixup(false),
|
||||
representation,
|
||||
)
|
||||
}
|
||||
@ -1420,7 +1428,7 @@ mod insert_lambda_set {
|
||||
|
||||
use crate::layout::{LambdaSet, Layout};
|
||||
|
||||
use super::{GlobalLayoutInterner, InLayout, LayoutInterner};
|
||||
use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64();
|
||||
const TEST_SET: &&[(Symbol, &[InLayout])] =
|
||||
@ -1428,6 +1436,8 @@ mod insert_lambda_set {
|
||||
const TEST_ARGS: &&[InLayout] = &(&[Layout::UNIT] as &[_]);
|
||||
const TEST_RET: InLayout = Layout::UNIT;
|
||||
|
||||
const FIXUP: NeedsRecursionPointerFixup = NeedsRecursionPointerFixup(true);
|
||||
|
||||
#[test]
|
||||
fn two_threads_write() {
|
||||
for _ in 0..100 {
|
||||
@ -1440,7 +1450,7 @@ mod insert_lambda_set {
|
||||
for arena in arenas.iter_mut() {
|
||||
let mut interner = global.fork();
|
||||
handles.push(s.spawn(move || {
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr)
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr)
|
||||
}))
|
||||
}
|
||||
let ins: Vec<LambdaSet> = handles.into_iter().map(|t| t.join().unwrap()).collect();
|
||||
@ -1457,7 +1467,7 @@ mod insert_lambda_set {
|
||||
let mut interner = global.fork();
|
||||
|
||||
let lambda_set =
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, true, Layout::UNIT);
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, FIXUP, Layout::UNIT);
|
||||
let lambda_set_layout_in = interner.insert(Layout::LambdaSet(lambda_set));
|
||||
assert_eq!(lambda_set.full_layout, lambda_set_layout_in);
|
||||
}
|
||||
@ -1471,12 +1481,12 @@ mod insert_lambda_set {
|
||||
|
||||
let in1 = {
|
||||
let mut interner = global.fork();
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr)
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr)
|
||||
};
|
||||
|
||||
let in2 = {
|
||||
let mut st_interner = global.unwrap().unwrap();
|
||||
st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr)
|
||||
st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr)
|
||||
};
|
||||
|
||||
assert_eq!(in1, in2);
|
||||
@ -1491,12 +1501,12 @@ mod insert_lambda_set {
|
||||
let set = TEST_SET;
|
||||
let repr = Layout::UNIT;
|
||||
|
||||
let in1 = st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr);
|
||||
let in1 = st_interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr);
|
||||
|
||||
let global = st_interner.into_global();
|
||||
let mut interner = global.fork();
|
||||
|
||||
let in2 = interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, true, repr);
|
||||
let in2 = interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, set, FIXUP, repr);
|
||||
|
||||
assert_eq!(in1, in2);
|
||||
}
|
||||
|
@ -7805,8 +7805,8 @@ mod solve_expr {
|
||||
),
|
||||
@r###"
|
||||
const : Str -[[const(2)]]-> (Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str)
|
||||
compose : (Str -a-> Str), (Str -[[]]-> Str) -[[compose(1)]]-> (Str -a-> Str)
|
||||
\c1, c2 -> compose c1 c2 : (Str -a-> Str), (Str -[[]]-> Str) -[[11]]-> (Str -a-> Str)
|
||||
compose : (Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str), (Str -[[]]-> Str) -[[compose(1)]]-> (Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str)
|
||||
\c1, c2 -> compose c1 c2 : (Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str), (Str -[[]]-> Str) -[[11]]-> (Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str)
|
||||
res : Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str
|
||||
res : Str -[[closCompose(7) (Str -a-> Str) (Str -[[]]-> Str), closConst(10) Str] as a]-> Str
|
||||
"###
|
||||
@ -8330,7 +8330,7 @@ mod solve_expr {
|
||||
"#
|
||||
),
|
||||
@r###"
|
||||
job : { lst : List [Bar, FromG a] } -[[job(0)]]-> [G { lst : List [Bar, FromG a] }] as a
|
||||
job : { lst : List [Bar, FromG ([G { lst : List [Bar, FromG a] }] as a)] } -[[job(0)]]-> [G { lst : List [Bar, FromG a] }] as a
|
||||
config : { lst : List [Bar, FromG ([G { lst : List [Bar, FromG a] }] as a)] }
|
||||
G config : [G { lst : List [Bar, FromG a] }] as a
|
||||
"###
|
||||
|
@ -0,0 +1,55 @@
|
||||
procedure Bool.2 ():
|
||||
let Bool.23 : Int1 = true;
|
||||
ret Bool.23;
|
||||
|
||||
procedure Test.10 (Test.28):
|
||||
let Test.32 : Int1 = CallByName Bool.2;
|
||||
if Test.32 then
|
||||
let Test.33 : [<rnu><null>, C {}] = CallByName Test.0;
|
||||
ret Test.33;
|
||||
else
|
||||
let Test.29 : [<rnu><null>, C {}] = TagId(1) ;
|
||||
ret Test.29;
|
||||
|
||||
procedure Test.11 (Test.30):
|
||||
let Test.31 : Str = "done";
|
||||
ret Test.31;
|
||||
|
||||
procedure Test.2 (Test.5):
|
||||
let Test.17 : [<rnu><null>, C {}] = TagId(0) Test.5;
|
||||
ret Test.17;
|
||||
|
||||
procedure Test.3 (Test.7):
|
||||
let Test.14 : [<rnu><null>, C {}] = CallByName Test.2 Test.7;
|
||||
ret Test.14;
|
||||
|
||||
procedure Test.6 (Test.16, #Attr.12):
|
||||
let Test.5 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
dec #Attr.12;
|
||||
let Test.19 : {} = Struct {};
|
||||
let Test.25 : Str = "foobar";
|
||||
let Test.20 : [<rnu><null>, C {}] = CallByName Test.8 Test.25 Test.5;
|
||||
dec Test.25;
|
||||
let Test.21 : U8 = GetTagId Test.20;
|
||||
joinpoint Test.22 Test.18:
|
||||
ret Test.18;
|
||||
in
|
||||
switch Test.21:
|
||||
case 0:
|
||||
let Test.23 : Str = CallByName Test.6 Test.19 Test.20;
|
||||
jump Test.22 Test.23;
|
||||
|
||||
default:
|
||||
dec Test.20;
|
||||
let Test.24 : Str = CallByName Test.11 Test.19;
|
||||
jump Test.22 Test.24;
|
||||
|
||||
|
||||
procedure Test.8 (Test.9, Test.7):
|
||||
let Test.27 : [<rnu><null>, C {}] = CallByName Test.10 Test.9;
|
||||
ret Test.27;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.13 : {} = Struct {};
|
||||
let Test.12 : [<rnu><null>, C {}] = CallByName Test.3 Test.13;
|
||||
ret Test.12;
|
@ -2551,3 +2551,23 @@ fn recursively_build_effect() {
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
||||
#[mono_test]
|
||||
fn recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026() {
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [looper] to "./platform"
|
||||
|
||||
Effect : {} -> Str
|
||||
|
||||
after = \buildNext ->
|
||||
afterInner = \{} -> (buildNext "foobar") {}
|
||||
afterInner
|
||||
|
||||
await : (Str -> Effect) -> Effect
|
||||
await = \cont -> after (\result -> cont result)
|
||||
|
||||
looper = await \_ -> if Bool.true then looper else \{} -> "done"
|
||||
"#
|
||||
)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use crate::types::{
|
||||
name_type_var, name_type_var_with_hint, AbilitySet, Polarity, RecordField, Uls,
|
||||
};
|
||||
use roc_collections::all::MutMap;
|
||||
use roc_collections::VecSet;
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
|
||||
@ -404,7 +405,7 @@ fn find_names_needed(
|
||||
}
|
||||
|
||||
struct NamedResult {
|
||||
recursion_structs_to_expand: Vec<Variable>,
|
||||
recursion_structs_to_expand: VecSet<Variable>,
|
||||
}
|
||||
|
||||
fn name_all_type_vars(variable: Variable, subs: &mut Subs, debug_print: DebugPrint) -> NamedResult {
|
||||
@ -423,20 +424,27 @@ fn name_all_type_vars(variable: Variable, subs: &mut Subs, debug_print: DebugPri
|
||||
debug_print.print_only_under_alias,
|
||||
);
|
||||
|
||||
let mut recursion_structs_to_expand = vec![];
|
||||
let mut recursion_structs_to_expand = VecSet::default();
|
||||
|
||||
for root in roots {
|
||||
// show the type variable number instead of `*`. useful for debugging
|
||||
// set_root_name(root, (format!("<{:?}>", root).into()), subs);
|
||||
match appearances.get(&root) {
|
||||
Some(Appearances::Multiple) => {
|
||||
if let Content::RecursionVar { structure, .. } =
|
||||
subs.get_content_without_compacting(root)
|
||||
{
|
||||
recursion_structs_to_expand
|
||||
.insert(subs.get_root_key_without_compacting(*structure));
|
||||
}
|
||||
letters_used = name_root(letters_used, root, subs, &mut taken, debug_print);
|
||||
}
|
||||
Some(Appearances::Single) => {
|
||||
if let Content::RecursionVar { structure, .. } =
|
||||
subs.get_content_without_compacting(root)
|
||||
{
|
||||
recursion_structs_to_expand.push(*structure);
|
||||
recursion_structs_to_expand
|
||||
.insert(subs.get_root_key_without_compacting(*structure));
|
||||
letters_used = name_root(letters_used, root, subs, &mut taken, debug_print);
|
||||
} else if debug_print.print_weakened_vars && is_weakened_unbound(subs, root) {
|
||||
letters_used = name_root(letters_used, root, subs, &mut taken, debug_print);
|
||||
@ -554,11 +562,11 @@ fn set_root_name(root: Variable, name: Lowercase, subs: &mut Subs) {
|
||||
#[derive(Default)]
|
||||
struct Context<'a> {
|
||||
able_variables: Vec<(&'a str, AbilitySet)>,
|
||||
recursion_structs_to_expand: Vec<Variable>,
|
||||
recursion_structs_to_expand: VecSet<Variable>,
|
||||
}
|
||||
|
||||
fn content_to_string(
|
||||
content: &Content,
|
||||
fn variable_to_string(
|
||||
var: Variable,
|
||||
subs: &Subs,
|
||||
home: ModuleId,
|
||||
interns: &Interns,
|
||||
@ -580,7 +588,7 @@ fn content_to_string(
|
||||
write_content(
|
||||
&env,
|
||||
&mut ctx,
|
||||
content,
|
||||
var,
|
||||
subs,
|
||||
&mut buf,
|
||||
Parens::Unnecessary,
|
||||
@ -613,9 +621,8 @@ pub fn name_and_print_var(
|
||||
debug_print: DebugPrint,
|
||||
) -> String {
|
||||
let named_result = name_all_type_vars(var, subs, debug_print);
|
||||
let content = subs.get_content_without_compacting(var);
|
||||
content_to_string(
|
||||
content,
|
||||
variable_to_string(
|
||||
var,
|
||||
subs,
|
||||
home,
|
||||
interns,
|
||||
@ -625,21 +632,20 @@ pub fn name_and_print_var(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_single_arg<'a>(subs: &'a Subs, args: &'a AliasVariables) -> &'a Content {
|
||||
pub fn get_single_arg<'a>(subs: &'a Subs, args: &'a AliasVariables) -> Variable {
|
||||
debug_assert_eq!(args.len(), 1);
|
||||
|
||||
let arg_var_index = args
|
||||
.into_iter()
|
||||
.next()
|
||||
.expect("Num was not applied to a type argument!");
|
||||
let arg_var = subs[arg_var_index];
|
||||
subs.get_content_without_compacting(arg_var)
|
||||
subs[arg_var_index]
|
||||
}
|
||||
|
||||
fn write_content<'a>(
|
||||
env: &Env,
|
||||
ctx: &mut Context<'a>,
|
||||
content: &Content,
|
||||
var: Variable,
|
||||
subs: &'a Subs,
|
||||
buf: &mut String,
|
||||
parens: Parens,
|
||||
@ -647,7 +653,7 @@ fn write_content<'a>(
|
||||
) {
|
||||
use crate::subs::Content::*;
|
||||
|
||||
match content {
|
||||
match subs.get_content_without_compacting(var) {
|
||||
FlexVar(Some(name_index)) => {
|
||||
let name = &subs.field_names[name_index.index as usize];
|
||||
buf.push_str(name.as_str())
|
||||
@ -676,22 +682,11 @@ fn write_content<'a>(
|
||||
structure,
|
||||
} => match opt_name {
|
||||
Some(name_index) => {
|
||||
if let Some(idx) = ctx
|
||||
.recursion_structs_to_expand
|
||||
.iter()
|
||||
.position(|v| v == structure)
|
||||
{
|
||||
ctx.recursion_structs_to_expand.swap_remove(idx);
|
||||
let structure_root = subs.get_root_key_without_compacting(*structure);
|
||||
if ctx.recursion_structs_to_expand.remove(&structure_root) {
|
||||
write_content(env, ctx, *structure, subs, buf, parens, pol);
|
||||
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*structure),
|
||||
subs,
|
||||
buf,
|
||||
parens,
|
||||
pol,
|
||||
);
|
||||
ctx.recursion_structs_to_expand.insert(structure_root);
|
||||
} else {
|
||||
let name = &subs.field_names[name_index.index as usize];
|
||||
buf.push_str(name.as_str())
|
||||
@ -701,14 +696,14 @@ fn write_content<'a>(
|
||||
unreachable!("This should always be filled in!")
|
||||
}
|
||||
},
|
||||
Structure(flat_type) => write_flat_type(env, ctx, flat_type, subs, buf, parens, pol),
|
||||
Structure(flat_type) => write_flat_type(env, ctx, var, flat_type, subs, buf, parens, pol),
|
||||
Alias(symbol, args, actual, _kind) => {
|
||||
let write_parens = parens == Parens::InTypeParam && !args.is_empty();
|
||||
|
||||
match *symbol {
|
||||
Symbol::NUM_NUM => {
|
||||
let content = get_single_arg(subs, args);
|
||||
match *content {
|
||||
match *subs.get_content_without_compacting(content) {
|
||||
Alias(nested, args, _actual, _kind) => match nested {
|
||||
Symbol::NUM_INTEGER => {
|
||||
write_integer(
|
||||
@ -769,8 +764,7 @@ fn write_content<'a>(
|
||||
|| args.any_infer_ext_var_is_material(subs) =>
|
||||
{
|
||||
write_parens!(write_parens, buf, {
|
||||
let content = subs.get_content_without_compacting(*actual);
|
||||
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||
write_content(env, ctx, *actual, subs, buf, parens, pol)
|
||||
})
|
||||
}
|
||||
|
||||
@ -780,21 +774,12 @@ fn write_content<'a>(
|
||||
for var_index in args.named_type_arguments() {
|
||||
let var = subs[var_index];
|
||||
buf.push(' ');
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::InTypeParam,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, var, subs, buf, Parens::InTypeParam, pol);
|
||||
}
|
||||
|
||||
roc_debug_flags::dbg_do!(roc_debug_flags::ROC_PRETTY_PRINT_ALIAS_CONTENTS, {
|
||||
buf.push_str("[[ but really ");
|
||||
let content = subs.get_content_without_compacting(*actual);
|
||||
write_content(env, ctx, content, subs, buf, parens, pol);
|
||||
write_content(env, ctx, *actual, subs, buf, parens, pol);
|
||||
buf.push_str("]]");
|
||||
});
|
||||
}),
|
||||
@ -846,28 +831,12 @@ fn write_content<'a>(
|
||||
|
||||
if let Some(rec_var) = recursion_var.into_variable() {
|
||||
buf.push_str(" as ");
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(rec_var),
|
||||
subs,
|
||||
buf,
|
||||
parens,
|
||||
pol,
|
||||
)
|
||||
write_content(env, ctx, rec_var, subs, buf, parens, pol)
|
||||
}
|
||||
|
||||
for Uls(var, member, region) in subs.get_subs_slice(*unspecialized) {
|
||||
buf.push_str(" + ");
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::Unnecessary,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, *var, subs, buf, Parens::Unnecessary, pol);
|
||||
buf.push(':');
|
||||
buf.push_str(&print_symbol(member));
|
||||
buf.push(':');
|
||||
@ -882,15 +851,7 @@ fn write_content<'a>(
|
||||
if i > 0 {
|
||||
buf.push_str(", ");
|
||||
}
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::Unnecessary,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, var, subs, buf, Parens::Unnecessary, pol);
|
||||
}
|
||||
buf.push(')');
|
||||
}
|
||||
@ -901,7 +862,7 @@ fn write_content<'a>(
|
||||
fn write_float<'a>(
|
||||
env: &Env,
|
||||
ctx: &mut Context<'a>,
|
||||
content: &Content,
|
||||
var: Variable,
|
||||
subs: &'a Subs,
|
||||
buf: &mut String,
|
||||
parens: Parens,
|
||||
@ -909,13 +870,13 @@ fn write_float<'a>(
|
||||
pol: Polarity,
|
||||
) {
|
||||
use crate::subs::Content::*;
|
||||
match content {
|
||||
match subs.get_content_without_compacting(var) {
|
||||
Alias(Symbol::NUM_BINARY32, _, _, _) => buf.push_str("F32"),
|
||||
Alias(Symbol::NUM_BINARY64, _, _, _) => buf.push_str("F64"),
|
||||
Alias(Symbol::NUM_DECIMAL, _, _, _) => buf.push_str("Dec"),
|
||||
_ => write_parens!(write_parens, buf, {
|
||||
buf.push_str("Float ");
|
||||
write_content(env, ctx, content, subs, buf, parens, pol);
|
||||
write_content(env, ctx, var, subs, buf, parens, pol);
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -923,7 +884,7 @@ fn write_float<'a>(
|
||||
fn write_integer<'a>(
|
||||
env: &Env,
|
||||
ctx: &mut Context<'a>,
|
||||
content: &Content,
|
||||
var: Variable,
|
||||
subs: &'a Subs,
|
||||
buf: &mut String,
|
||||
parens: Parens,
|
||||
@ -934,19 +895,19 @@ fn write_integer<'a>(
|
||||
|
||||
macro_rules! derive_num_writes {
|
||||
($($lit:expr, $tag:path)*) => {
|
||||
match content {
|
||||
match subs.get_content_without_compacting(var) {
|
||||
$(
|
||||
&Alias($tag, _, _, _) => {
|
||||
buf.push_str($lit)
|
||||
},
|
||||
)*
|
||||
actual => {
|
||||
_ => {
|
||||
write_parens!(
|
||||
write_parens,
|
||||
buf,
|
||||
{
|
||||
buf.push_str("Int ");
|
||||
write_content(env, ctx, actual, subs, buf, parens, pol);
|
||||
write_content(env, ctx, var, subs, buf, parens, pol);
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -1008,13 +969,13 @@ fn write_ext_content<'a>(
|
||||
parens: Parens,
|
||||
pol: Polarity,
|
||||
) {
|
||||
if let ExtContent::Content(_, content) = ext_content {
|
||||
if let ExtContent::Content(var, _) = ext_content {
|
||||
// This is an open record or tag union, so print the variable
|
||||
// right after the '}' or ']'
|
||||
//
|
||||
// e.g. the "*" at the end of `{ x: I64 }*`
|
||||
// or the "r" at the end of `{ x: I64 }r`
|
||||
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||
write_content(env, ctx, var, subs, buf, parens, pol)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1046,15 +1007,7 @@ fn write_sorted_tags2<'a, L>(
|
||||
|
||||
for var in vars {
|
||||
buf.push(' ');
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::InTypeParam,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, *var, subs, buf, Parens::InTypeParam, pol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1099,15 +1052,7 @@ fn write_sorted_tags<'a>(
|
||||
|
||||
for var in vars {
|
||||
buf.push(' ');
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::InTypeParam,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, *var, subs, buf, Parens::InTypeParam, pol);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1117,6 +1062,7 @@ fn write_sorted_tags<'a>(
|
||||
fn write_flat_type<'a>(
|
||||
env: &Env,
|
||||
ctx: &mut Context<'a>,
|
||||
var: Variable,
|
||||
flat_type: &FlatType,
|
||||
subs: &'a Subs,
|
||||
buf: &mut String,
|
||||
@ -1185,15 +1131,7 @@ fn write_flat_type<'a>(
|
||||
Required(_) | Demanded(_) | RigidRequired(_) => buf.push_str(" : "),
|
||||
};
|
||||
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::Unnecessary,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, var, subs, buf, Parens::Unnecessary, pol);
|
||||
}
|
||||
|
||||
buf.push_str(" }");
|
||||
@ -1203,13 +1141,13 @@ fn write_flat_type<'a>(
|
||||
Content::Structure(EmptyRecord) => {
|
||||
// This is a closed record. We're done!
|
||||
}
|
||||
content => {
|
||||
_ => {
|
||||
// This is an open record, so print the variable
|
||||
// right after the '}'
|
||||
//
|
||||
// e.g. the "*" at the end of `{ x: I64 }*`
|
||||
// or the "r" at the end of `{ x: I64 }r`
|
||||
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||
write_content(env, ctx, ext_var, subs, buf, parens, pol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1247,15 +1185,7 @@ fn write_flat_type<'a>(
|
||||
}
|
||||
expected_next_index = index + 1;
|
||||
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(var),
|
||||
subs,
|
||||
buf,
|
||||
Parens::Unnecessary,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, var, subs, buf, Parens::Unnecessary, pol);
|
||||
}
|
||||
|
||||
buf.push_str(" )");
|
||||
@ -1264,13 +1194,13 @@ fn write_flat_type<'a>(
|
||||
Content::Structure(EmptyTuple) => {
|
||||
// This is a closed tuple. We're done!
|
||||
}
|
||||
content => {
|
||||
_ => {
|
||||
// This is an open tuple, so print the variable
|
||||
// right after the ')'
|
||||
//
|
||||
// e.g. the "*" at the end of `( I64, I64 )*`
|
||||
// or the "r" at the end of `( I64, I64 )r`
|
||||
write_content(env, ctx, content, subs, buf, parens, pol)
|
||||
write_content(env, ctx, ext_var, subs, buf, parens, pol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1319,6 +1249,9 @@ fn write_flat_type<'a>(
|
||||
}
|
||||
|
||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||
ctx.recursion_structs_to_expand
|
||||
.remove(&subs.get_root_key_without_compacting(var));
|
||||
|
||||
write_parens!(parens == Parens::InTypeParam, buf, {
|
||||
buf.push('[');
|
||||
|
||||
@ -1346,15 +1279,7 @@ fn write_flat_type<'a>(
|
||||
);
|
||||
|
||||
buf.push_str(" as ");
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*rec_var),
|
||||
subs,
|
||||
buf,
|
||||
parens,
|
||||
pol,
|
||||
)
|
||||
write_content(env, ctx, *rec_var, subs, buf, parens, pol)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1474,9 +1399,9 @@ fn write_apply<'a>(
|
||||
Symbol::NUM_FLOATINGPOINT if nested_args.len() == 1 => {
|
||||
buf.push_str("F64");
|
||||
}
|
||||
_ => default_case(subs, arg_content),
|
||||
_ => default_case(subs, *arg),
|
||||
},
|
||||
_ => default_case(subs, arg_content),
|
||||
_ => default_case(subs, *arg),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -1488,15 +1413,7 @@ fn write_apply<'a>(
|
||||
|
||||
for arg in args {
|
||||
buf.push(' ');
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*arg),
|
||||
subs,
|
||||
buf,
|
||||
Parens::InTypeParam,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, *arg, subs, buf, Parens::InTypeParam, pol);
|
||||
}
|
||||
|
||||
if write_parens {
|
||||
@ -1532,42 +1449,18 @@ fn write_fn<'a>(
|
||||
needs_comma = true;
|
||||
}
|
||||
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(*arg),
|
||||
subs,
|
||||
buf,
|
||||
Parens::InFn,
|
||||
Polarity::Neg,
|
||||
);
|
||||
write_content(env, ctx, *arg, subs, buf, Parens::InFn, Polarity::Neg);
|
||||
}
|
||||
|
||||
if !env.debug.print_lambda_sets {
|
||||
buf.push_str(" -> ");
|
||||
} else {
|
||||
buf.push_str(" -");
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(closure),
|
||||
subs,
|
||||
buf,
|
||||
parens,
|
||||
pol,
|
||||
);
|
||||
write_content(env, ctx, closure, subs, buf, parens, pol);
|
||||
buf.push_str("-> ");
|
||||
}
|
||||
|
||||
write_content(
|
||||
env,
|
||||
ctx,
|
||||
subs.get_content_without_compacting(ret),
|
||||
subs,
|
||||
buf,
|
||||
Parens::InFn,
|
||||
Polarity::Pos,
|
||||
);
|
||||
write_content(env, ctx, ret, subs, buf, Parens::InFn, Polarity::Pos);
|
||||
|
||||
if use_parens {
|
||||
buf.push(')');
|
||||
|
Loading…
Reference in New Issue
Block a user