From 28c206da182ad09a64d6db3c579fce06c475ffdd Mon Sep 17 00:00:00 2001 From: James Shubin Date: Mon, 25 Sep 2023 15:40:55 -0400 Subject: [PATCH] lang: ast: structs: Remove value lookup from if expr type This is really not needed and makes our future API changes to Value more difficult. --- lang/ast/structs.go | 48 +++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/lang/ast/structs.go b/lang/ast/structs.go index 3948f927..19149ed1 100644 --- a/lang/ast/structs.go +++ b/lang/ast/structs.go @@ -8903,22 +8903,46 @@ func (obj *ExprIf) SetType(typ *types.Type) error { // Type returns the type of this expression. func (obj *ExprIf) Type() (*types.Type, error) { - boolValue, err := obj.Condition.Value() // attempt early speculation - if err == nil && obj.typ == nil { - branch := obj.ElseBranch - if boolValue.Bool() { // must not panic - branch = obj.ThenBranch - } - return branch.Type() + if obj.typ != nil { + return obj.typ, nil } - if obj.typ == nil { - if err != nil { - return nil, errwrap.Wrapf(interfaces.ErrTypeCurrentlyUnknown, err.Error()) + var typ *types.Type + testAndSet := func(t *types.Type) error { + if t == nil { + return nil // skip } - return nil, interfaces.ErrTypeCurrentlyUnknown + if typ == nil { + return nil // it's ok + } + + if typ.Cmp(t) != nil { + return fmt.Errorf("inconsistent branch") + } + typ = t // save + + return nil } - return obj.typ, nil + + if obj.ThenBranch != nil { + if t, err := obj.ThenBranch.Type(); err != nil { + if err := testAndSet(t); err != nil { + return nil, err + } + } + } + if obj.ElseBranch != nil { + if t, err := obj.ElseBranch.Type(); err != nil { + if err := testAndSet(t); err != nil { + return nil, err + } + } + } + + if typ != nil { + return typ, nil + } + return nil, interfaces.ErrTypeCurrentlyUnknown } // Unify returns the list of invariants that this node produces. It recursively