mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-24 20:42:29 +00:00
Prevent confusion between separate instances of RecursivePointer
This commit is contained in:
parent
ad95ea4a3b
commit
456bda0895
3 changed files with 134 additions and 0 deletions
|
@ -231,6 +231,8 @@ impl<'a> CodeGenHelp<'a> {
|
|||
) -> Symbol {
|
||||
use HelperOp::*;
|
||||
|
||||
let layout = self.replace_rec_ptr(ctx, layout);
|
||||
|
||||
let found = self
|
||||
.specializations
|
||||
.iter()
|
||||
|
@ -329,6 +331,56 @@ impl<'a> CodeGenHelp<'a> {
|
|||
let ident_id = ident_ids.add(Ident::from(debug_name));
|
||||
Symbol::new(self.home, ident_id)
|
||||
}
|
||||
|
||||
// When creating or looking up Specializations, we need to replace RecursivePointer
|
||||
// with the particular Union layout it represents at this point in the tree.
|
||||
// For example if a program uses `RoseTree a : [ Tree a (List (RoseTree a)) ]`
|
||||
// then it could have both `RoseTree I64` and `RoseTree Str`. In this case it
|
||||
// needs *two* specializations for `List(RecursivePointer)`, not just one.
|
||||
fn replace_rec_ptr(&self, ctx: &Context<'a>, layout: Layout<'a>) -> Layout<'a> {
|
||||
match layout {
|
||||
Layout::Builtin(Builtin::Dict(k, v)) => Layout::Builtin(Builtin::Dict(
|
||||
self.arena.alloc(self.replace_rec_ptr(ctx, *k)),
|
||||
self.arena.alloc(self.replace_rec_ptr(ctx, *v)),
|
||||
)),
|
||||
|
||||
Layout::Builtin(Builtin::Set(k)) => Layout::Builtin(Builtin::Set(
|
||||
self.arena.alloc(self.replace_rec_ptr(ctx, *k)),
|
||||
)),
|
||||
|
||||
Layout::Builtin(Builtin::List(v)) => Layout::Builtin(Builtin::List(
|
||||
self.arena.alloc(self.replace_rec_ptr(ctx, *v)),
|
||||
)),
|
||||
|
||||
Layout::Builtin(_) => layout,
|
||||
|
||||
Layout::Struct(fields) => {
|
||||
let new_fields_iter = fields.iter().map(|f| self.replace_rec_ptr(ctx, *f));
|
||||
Layout::Struct(self.arena.alloc_slice_fill_iter(new_fields_iter))
|
||||
}
|
||||
|
||||
Layout::Union(UnionLayout::NonRecursive(tags)) => {
|
||||
let mut new_tags = Vec::with_capacity_in(tags.len(), self.arena);
|
||||
for fields in tags {
|
||||
let mut new_fields = Vec::with_capacity_in(fields.len(), self.arena);
|
||||
for field in fields.iter() {
|
||||
new_fields.push(self.replace_rec_ptr(ctx, *field))
|
||||
}
|
||||
new_tags.push(new_fields.into_bump_slice());
|
||||
}
|
||||
Layout::Union(UnionLayout::NonRecursive(new_tags.into_bump_slice()))
|
||||
}
|
||||
|
||||
Layout::Union(_) => layout,
|
||||
|
||||
Layout::LambdaSet(lambda_set) => {
|
||||
self.replace_rec_ptr(ctx, lambda_set.runtime_representation())
|
||||
}
|
||||
|
||||
// This line is the whole point of the function
|
||||
Layout::RecursivePointer => Layout::Union(ctx.recursive_union.unwrap()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn let_lowlevel<'a>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue