Skip to content

Commit 5cd4c38

Browse files
authored
fix bug fusing option-type fields (#6900)
With the new design for option types, the fuser needs to fuse optional fields such that the option type of the field is pushed into the field's fusion type so we have fusion(...|none) instead of none|fusion(...). This problem was causing upcast to fail on such patterns. We've added test coverage to catch this.
1 parent f0f35f7 commit 5cd4c38

2 files changed

Lines changed: 20 additions & 2 deletions

File tree

runtime/sam/expr/agg/fuser.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func (f *Fuser) fuse(a, b super.Type) super.Type {
6060
// First change all fields to optional that are in "a" but not in "b".
6161
for k, field := range fields {
6262
if _, ok := indexOfField(b.Fields, field.Name); !ok {
63-
fields[k].Type = f.sctx.Option(fields[k].Type)
63+
fields[k].Type = f.makeOption(fields[k].Type)
6464
}
6565
}
6666
// Now fuse all the fields in "b" that are also in "a" and add the fields
@@ -70,7 +70,7 @@ func (f *Fuser) fuse(a, b super.Type) super.Type {
7070
if ok {
7171
fields[i].Type = f.fuse(fields[i].Type, field.Type)
7272
} else {
73-
typ := f.sctx.Option(field.Type)
73+
typ := f.makeOption(field.Type)
7474
fields = append(fields, super.NewField(field.Name, typ))
7575
}
7676
}
@@ -144,6 +144,13 @@ func (f *Fuser) fuse(a, b super.Type) super.Type {
144144
return f.fusion(union)
145145
}
146146

147+
func (f *Fuser) makeOption(t super.Type) super.Type {
148+
if fusion, ok := t.(*super.TypeFusion); ok {
149+
return f.sctx.LookupTypeFusion(f.makeOption(fusion.Type))
150+
}
151+
return f.sctx.Option(t)
152+
}
153+
147154
func isAll(t super.Type) bool {
148155
_, ok := t.(*super.TypeOfAll)
149156
return ok

runtime/ztests/expr/fuser.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,14 @@ input: &input |
5959
[{id:1,s:"foo"},{id:2,s:null}]
6060

6161
output: *input
62+
63+
---
64+
65+
spq: fuse | defuse(this)
66+
67+
input: &input |
68+
{x:1,y:{z:"foo"}}
69+
{x:2,y:{z:"bar",w:true}}
70+
{x:3}
71+
72+
output: *input

0 commit comments

Comments
 (0)