Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(gnovm): correct type for shift expression #1775

Open
wants to merge 146 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
146 commits
Select commit Hold shift + click to select a range
e22a43c
outOfGas log clearly
ltzmaxwell Nov 17, 2023
b9aa15e
patch up
ltzmaxwell Nov 20, 2023
9f57ef7
more test, cover more cases
ltzmaxwell Nov 21, 2023
55e3af8
fix assign type check
ltzmaxwell Nov 21, 2023
af75c9e
fixup
ltzmaxwell Nov 27, 2023
2603f34
more test
ltzmaxwell Nov 28, 2023
1275f9d
fixup
ltzmaxwell Nov 29, 2023
814354b
make test work
ltzmaxwell Nov 30, 2023
0f53121
fixup
ltzmaxwell Dec 1, 2023
ddd2c71
refactor
ltzmaxwell Dec 3, 2023
7acaec6
fixup
ltzmaxwell Dec 4, 2023
e291e56
comparable
ltzmaxwell Dec 5, 2023
ad87127
compare
ltzmaxwell Dec 5, 2023
7d21ff8
unary
ltzmaxwell Dec 5, 2023
9b0ace9
fixup
ltzmaxwell Dec 6, 2023
eed16b7
optimize
ltzmaxwell Dec 7, 2023
1c93d2c
inc,dec
ltzmaxwell Dec 7, 2023
5f0ac87
fixup
ltzmaxwell Dec 7, 2023
d6000c5
fixup
ltzmaxwell Dec 7, 2023
812e64d
fixup
ltzmaxwell Dec 7, 2023
fe948bb
doc
ltzmaxwell Dec 7, 2023
52d8221
more test
ltzmaxwell Dec 8, 2023
ec6fd0e
readme
ltzmaxwell Dec 8, 2023
cde9ed5
fixup
ltzmaxwell Dec 8, 2023
80508da
fixup
ltzmaxwell Dec 8, 2023
7af6623
restore unwanted
ltzmaxwell Dec 8, 2023
55e6cc0
restore
ltzmaxwell Dec 8, 2023
6d56167
Merge remote-tracking branch 'upstream/master' into ltzmaxwell/fix/in…
ltzmaxwell Dec 8, 2023
fa7f8d4
restore
ltzmaxwell Dec 8, 2023
6a31cb8
restore
ltzmaxwell Dec 8, 2023
0b095c3
restore
ltzmaxwell Dec 8, 2023
34588a1
restore
ltzmaxwell Dec 8, 2023
edc8c5b
restore
ltzmaxwell Dec 8, 2023
1513d78
restore
ltzmaxwell Dec 8, 2023
5dbf7f4
sync
ltzmaxwell Dec 8, 2023
9656056
fix inc float
ltzmaxwell Dec 8, 2023
fa3acd0
fixup
ltzmaxwell Dec 8, 2023
068e368
fixup
ltzmaxwell Dec 8, 2023
2f4136f
fmt
ltzmaxwell Dec 8, 2023
1497c4a
lint
ltzmaxwell Dec 8, 2023
709e13a
lint
ltzmaxwell Dec 8, 2023
8fd16fc
fix map comparable
ltzmaxwell Dec 8, 2023
8a63e0c
fixup
ltzmaxwell Dec 10, 2023
ad8768b
fix slice type
ltzmaxwell Dec 11, 2023
0f828f5
fix comparable
ltzmaxwell Dec 11, 2023
937723e
fixup
ltzmaxwell Dec 11, 2023
218c834
fixup
ltzmaxwell Dec 11, 2023
8c5ce24
fixup
ltzmaxwell Dec 12, 2023
abff073
fixup
ltzmaxwell Dec 12, 2023
af0de11
fixup
ltzmaxwell Dec 12, 2023
e673dac
fixup
ltzmaxwell Dec 12, 2023
cfcbdda
restore
ltzmaxwell Dec 12, 2023
268e849
fix shift
ltzmaxwell Dec 12, 2023
097244e
fixup
ltzmaxwell Dec 12, 2023
6858e80
fixup
ltzmaxwell Dec 13, 2023
db12d88
tidy
ltzmaxwell Dec 13, 2023
fe2cb7d
fixup
ltzmaxwell Dec 14, 2023
5f58979
fixup
ltzmaxwell Dec 14, 2023
c936fea
fix special case relate to nil type
ltzmaxwell Dec 18, 2023
ee408c2
fixup
ltzmaxwell Dec 19, 2023
2771649
fixup
ltzmaxwell Dec 20, 2023
005b370
fixup
ltzmaxwell Dec 22, 2023
c1f4dda
fixup
ltzmaxwell Dec 22, 2023
f94e4fd
add test
ltzmaxwell Dec 22, 2023
635decd
fixup
ltzmaxwell Dec 24, 2023
95214af
add new test
ltzmaxwell Jan 9, 2024
7464ac9
fixup
ltzmaxwell Jan 11, 2024
4f370a2
clean
ltzmaxwell Jan 11, 2024
54b255d
add comments
ltzmaxwell Jan 11, 2024
184f526
add comment
ltzmaxwell Jan 11, 2024
6aa1c04
add comments
ltzmaxwell Jan 11, 2024
46ced47
add test
ltzmaxwell Jan 11, 2024
5e9c783
add test
ltzmaxwell Jan 11, 2024
9e47ced
fixup
ltzmaxwell Jan 11, 2024
937a725
update
ltzmaxwell Jan 12, 2024
57bd724
update
ltzmaxwell Jan 13, 2024
e9a3a0a
fixup
ltzmaxwell Jan 13, 2024
ef21103
fixup
ltzmaxwell Jan 13, 2024
37f00df
improve name
ltzmaxwell Jan 13, 2024
1791a34
fixup
ltzmaxwell Jan 14, 2024
073bd48
fixup
ltzmaxwell Jan 14, 2024
df4d4c7
fixup
ltzmaxwell Jan 15, 2024
ef25c1f
fixup
ltzmaxwell Jan 15, 2024
6f59149
fixup
ltzmaxwell Jan 15, 2024
33ec34f
fixup
ltzmaxwell Jan 16, 2024
836941d
sync and test
ltzmaxwell Jan 16, 2024
8d3d855
fixup
ltzmaxwell Jan 17, 2024
e4e5e2a
check nil
ltzmaxwell Jan 17, 2024
8ee9724
fixup
ltzmaxwell Jan 17, 2024
292b038
clear
ltzmaxwell Jan 18, 2024
cd8caa9
fixup
ltzmaxwell Jan 18, 2024
87f3a8e
fixup
ltzmaxwell Jan 18, 2024
792a368
fixup
ltzmaxwell Jan 18, 2024
7a9b8a4
add check
ltzmaxwell Jan 20, 2024
94262aa
clean most debug log, can be revert here
ltzmaxwell Jan 31, 2024
afde8b0
escape op on render side
ltzmaxwell Feb 8, 2024
40ec493
migrate logic to type_check.go; move compatibility check as method of…
ltzmaxwell Mar 1, 2024
5f0cf8b
make test pass
ltzmaxwell Mar 1, 2024
cbdc979
done refactor to type_checker
ltzmaxwell Mar 4, 2024
118598d
clean
ltzmaxwell Mar 5, 2024
33a3c9d
prepared for split
ltzmaxwell Mar 5, 2024
6d6590a
mv some check logic to type_check
ltzmaxwell Mar 5, 2024
218fff0
fix binary non-const native handling
ltzmaxwell Mar 7, 2024
a6838b6
fix compatible check for assign in type_check
ltzmaxwell Mar 7, 2024
4744d09
make rhs native type check in type_check
ltzmaxwell Mar 8, 2024
5631d3a
try handle checking declared type against native interface, temp her…
ltzmaxwell Mar 11, 2024
a2862ba
consolidate delay handling for untyped shift expr logic
ltzmaxwell Mar 13, 2024
7bd03e1
cache better; clear unused logic
ltzmaxwell Mar 14, 2024
432a32f
#cherry-pick. rm logic of check declared type against native interfac…
ltzmaxwell Mar 14, 2024
be25502
cherry pick this. rm remained logic for check against native interfac…
ltzmaxwell Mar 14, 2024
2a17f6c
default cherry pick commit this branch if not marked as not. fixup
ltzmaxwell Mar 14, 2024
4acbc36
fix shift with 1.0
ltzmaxwell Mar 14, 2024
0b64bee
sync master
ltzmaxwell Jul 1, 2024
30212d4
Merge remote-tracking branch 'upstream/master' into fix/shift-expr-ty…
ltzmaxwell Jul 1, 2024
64a04cd
rename tests
ltzmaxwell Jul 1, 2024
77b0dc2
sync
ltzmaxwell Jul 1, 2024
c59eeab
fixup:
ltzmaxwell Jul 31, 2024
4e62421
sync
ltzmaxwell Jul 31, 2024
920c032
shift work
ltzmaxwell Jul 31, 2024
a5f689f
fixup
ltzmaxwell Aug 1, 2024
8966cb6
Merge remote-tracking branch 'main/master' into fix/shift-expr-typecheck
ltzmaxwell Aug 1, 2024
89923ee
test pass
ltzmaxwell Aug 1, 2024
a9e0f5d
fixup
ltzmaxwell Aug 1, 2024
61aeeb6
fixup
ltzmaxwell Aug 1, 2024
10184ce
fixup
ltzmaxwell Aug 2, 2024
a126dae
reorgnize test files
ltzmaxwell Aug 2, 2024
6ab6f2e
add test
ltzmaxwell Aug 5, 2024
8404a9e
fix
ltzmaxwell Aug 5, 2024
40491d1
fix lint
ltzmaxwell Aug 5, 2024
dbc5010
fix rhs type
ltzmaxwell Aug 7, 2024
e596b1c
fix lint
ltzmaxwell Aug 7, 2024
40369a2
fixup
ltzmaxwell Aug 8, 2024
f73a51d
fixup
ltzmaxwell Aug 8, 2024
6b90216
save
ltzmaxwell Aug 8, 2024
dd1c416
fixup
ltzmaxwell Aug 9, 2024
3dff9b0
clean
ltzmaxwell Aug 9, 2024
6bcb88d
clean
ltzmaxwell Aug 9, 2024
1716d10
fixup
ltzmaxwell Aug 9, 2024
686acd0
clean
ltzmaxwell Aug 9, 2024
0ab1c69
add test
ltzmaxwell Aug 12, 2024
a7552ae
Update gnovm/pkg/gnolang/values.go
ltzmaxwell Oct 7, 2024
687efeb
fixup
ltzmaxwell Oct 7, 2024
0070fb4
fixup
ltzmaxwell Oct 8, 2024
e3c0c50
todo
ltzmaxwell Oct 8, 2024
555518e
fixup
ltzmaxwell Oct 9, 2024
664c88e
merge master
ltzmaxwell Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gnovm/pkg/gnolang/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2119,6 +2119,7 @@ const (
ATTR_IOTA GnoAttribute = "ATTR_IOTA"
ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED"
ATTR_INJECTED GnoAttribute = "ATTR_INJECTED"
ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS"
)

var rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]+$`)
Expand Down
2 changes: 2 additions & 0 deletions gnovm/pkg/gnolang/op_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,7 @@ func xorAssign(lv, rv *TypedValue) {

// for doOpShl and doOpShlAssign.
func shlAssign(lv, rv *TypedValue) {
rv.AssertNonNegative("runtime error: negative shift amount")
// set the result in lv.
// NOTE: baseOf(rv.T) is always UintType.
switch baseOf(lv.T) {
Expand Down Expand Up @@ -1136,6 +1137,7 @@ func shlAssign(lv, rv *TypedValue) {

// for doOpShr and doOpShrAssign.
func shrAssign(lv, rv *TypedValue) {
rv.AssertNonNegative("runtime error: negative shift amount")
// set the result in lv.
// NOTE: baseOf(rv.T) is always UintType.
switch baseOf(lv.T) {
Expand Down
5 changes: 5 additions & 0 deletions gnovm/pkg/gnolang/op_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ func (m *Machine) doOpPrecall() {
case TypeValue:
// Do not pop type yet.
// No need for frames.
xv := m.PeekValue(1)
if cx.GetAttribute(ATTR_SHIFT_RHS) == true {
xv.AssertNonNegative("runtime error: negative shift amount")
}

m.PushOp(OpConvert)
deelawn marked this conversation as resolved.
Show resolved Hide resolved
if debug {
if len(cx.Args) != 1 {
Expand Down
194 changes: 154 additions & 40 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
isShift := n.Op == SHL || n.Op == SHR
if isShift {
// check LHS type compatibility
n.checkShiftLhs(lt)
n.assertShiftExprCompatible1(store, last, lt, rt)
// checkOrConvert RHS
if baseOf(rt) != UintType {
// convert n.Right to (gno) uint type,
Expand All @@ -1036,6 +1036,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
Op: n.Op,
Right: rn,
}
n2.Right.SetAttribute(ATTR_SHIFT_RHS, true)
resn := Preprocess(store, last, n2)
return resn, TRANS_CONTINUE
}
Expand Down Expand Up @@ -1097,12 +1098,34 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
// NOTE: binary operations are always computed in
// gno, never with reflect.
} else {
// convert n.Left to right type.
checkOrConvertType(store, last, &n.Left, rt, false)
// right is untyped const, left is not const, typed/untyped
checkUntypedShiftExpr := func(x Expr) {
if bx, ok := x.(*BinaryExpr); ok {
slt := evalStaticTypeOf(store, last, bx.Left)
if bx.Op == SHL || bx.Op == SHR {
srt := evalStaticTypeOf(store, last, bx.Right)
bx.assertShiftExprCompatible1(store, last, slt, srt)
}
}
}

if !isUntyped(rt) { // right is typed
checkOrConvertType(store, last, &n.Left, rt, false)
} else {
if shouldSwapOnSpecificity(lt, rt) {
checkUntypedShiftExpr(n.Right)
} else {
checkUntypedShiftExpr(n.Left)
}
}
}
} else if lcx.T == nil { // LHS is nil.
// convert n.Left to typed-nil type.
checkOrConvertType(store, last, &n.Left, rt, false)
} else {
if isUntyped(rt) {
checkOrConvertType(store, last, &n.Right, lt, false)
}
}
} else if ric { // right is const, left is not
if isUntyped(rcx.T) {
Expand Down Expand Up @@ -1134,12 +1157,33 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
// NOTE: binary operations are always computed in
// gno, never with reflect.
} else {
// convert n.Right to left type.
checkOrConvertType(store, last, &n.Right, lt, false)
// right is untyped const, left is not const, typed or untyped
checkUntypedShiftExpr := func(x Expr) {
if bx, ok := x.(*BinaryExpr); ok {
if bx.Op == SHL || bx.Op == SHR {
srt := evalStaticTypeOf(store, last, bx.Right)
bx.assertShiftExprCompatible1(store, last, rt, srt)
}
}
}
// both untyped, e.g. 1<<s != 1.0
if !isUntyped(lt) { // left is typed
checkOrConvertType(store, last, &n.Right, lt, false)
} else { // if one side is untyped shift expression, check type with lower specificity
if shouldSwapOnSpecificity(lt, rt) {
checkUntypedShiftExpr(n.Right)
} else {
checkUntypedShiftExpr(n.Left)
}
}
}
} else if rcx.T == nil { // RHS is nil
// refer to tests/files/types/eql_0f20.gno
checkOrConvertType(store, last, &n.Right, lt, false)
} else { // left is not const, right is typed const
if isUntyped(lt) {
checkOrConvertType(store, last, &n.Left, rt, false)
}
}
} else {
// Left not const, Right not const ------------------
Expand Down Expand Up @@ -1267,27 +1311,28 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
panic("type conversion requires single argument")
}
n.NumArgs = 1
if arg0, ok := n.Args[0].(*ConstExpr); ok {
var constConverted bool
ct := evalStaticType(store, last, n.Func)
ct := evalStaticType(store, last, n.Func)
at := evalStaticTypeOf(store, last, n.Args[0])
var constConverted bool
switch arg0 := n.Args[0].(type) {
case *ConstExpr:
// As a special case, if a decimal cannot
// be represented as an integer, it cannot be converted to one,
// and the error is handled here.
// Out of bounds errors are usually handled during evalConst().
switch ct.Kind() {
case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind,
UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind,
BigintKind:
if isIntNum(ct) {
if bd, ok := arg0.TypedValue.V.(BigdecValue); ok {
if !isInteger(bd.V) {
panic(fmt.Sprintf(
"cannot convert %s to integer type",
arg0))
}
}
convertConst(store, last, arg0, ct)
constConverted = true
case SliceKind:
if isNumeric(at) {
ltzmaxwell marked this conversation as resolved.
Show resolved Hide resolved
convertConst(store, last, arg0, ct)
constConverted = true
}
} else if ct.Kind() == SliceKind {
if ct.Elem().Kind() == Uint8Kind { // bypass []byte("xxx")
n.SetAttribute(ATTR_TYPEOF_VALUE, ct)
return n, TRANS_CONTINUE
Expand All @@ -1298,18 +1343,34 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
if !constConverted {
convertConst(store, last, arg0, nil)
}

// evaluate the new expression.
cx := evalConst(store, last, n)
// Though cx may be undefined if ct is interface,
// the ATTR_TYPEOF_VALUE is still interface.
cx.SetAttribute(ATTR_TYPEOF_VALUE, ct)
return cx, TRANS_CONTINUE
} else {
ct := evalStaticType(store, last, n.Func)
n.SetAttribute(ATTR_TYPEOF_VALUE, ct)
return n, TRANS_CONTINUE
case *BinaryExpr: // special case to evaluate type of binaryExpr/UnaryExpr which has untyped shift nested
if isUntyped(at) {
switch arg0.Op {
case EQL, NEQ, LSS, GTR, LEQ, GEQ:
assertAssignableTo(at, ct, false)
break
default:
checkOrConvertType(store, last, &n.Args[0], ct, false)
}
}
case *UnaryExpr:
if isUntyped(at) {
checkOrConvertType(store, last, &n.Args[0], ct, false)
}
default:
// do nothing
}
// general case, for non-const untyped && no nested untyped shift
// after handling const, and special cases recursively, set the target node type
// ct := evalStaticType(store, last, n.Func)
n.SetAttribute(ATTR_TYPEOF_VALUE, ct)
return n, TRANS_CONTINUE
default:
panic(fmt.Sprintf(
"unexpected func type %v (%v)",
Expand Down Expand Up @@ -1479,7 +1540,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
}
}
} else {
for i := range n.Args {
for i := range n.Args { // iterate args
if hasVarg {
if (len(spts) - 1) <= i {
if isVarg {
Expand Down Expand Up @@ -1929,6 +1990,10 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
} else {
last.Define(ln, anyValue(rt))
}
// if rhs is untyped
if isUntyped(rt) {
deelawn marked this conversation as resolved.
Show resolved Hide resolved
checkOrConvertType(store, last, &n.Rhs[i], nil, false)
}
}
}
} else { // ASSIGN, or assignment operation (+=, -=, <<=, etc.)
Expand Down Expand Up @@ -2018,9 +2083,6 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
}
} else { // len(Lhs) == len(Rhs)
if n.Op == SHL_ASSIGN || n.Op == SHR_ASSIGN {
if len(n.Lhs) != 1 || len(n.Rhs) != 1 {
panic("should not happen")
}
// Special case if shift assign <<= or >>=.
convertType(store, last, &n.Rhs[0], UintType)
} else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN {
Expand Down Expand Up @@ -2281,10 +2343,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node {
vt := evalStaticTypeOf(store, last, vx)
sts[i] = vt
}
} else {
} else { // T is nil, n not const
// convert n.Value to default type.
for i, vx := range n.Values {
convertIfConst(store, last, vx)
if cx, ok := vx.(*ConstExpr); ok {
convertConst(store, last, cx, nil)
// convertIfConst(store, last, vx)
} else {
checkOrConvertType(store, last, &vx, nil, false)
}
vt := evalStaticTypeOf(store, last, vx)
sts[i] = vt
}
Expand Down Expand Up @@ -2840,9 +2907,25 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative
assertAssignableTo(cx.T, t, autoNative)
}
} else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) {
// "push" expected type into shift binary's left operand. recursively.
checkOrConvertType(store, last, &bx.Left, t, autoNative)
} else if *x != nil { // XXX if x != nil && t != nil {
xt := evalStaticTypeOf(store, last, *x)
if debug {
debug.Printf("shift, xt: %v, Op: %v, t: %v \n", xt, bx.Op, t)
}
if isUntyped(xt) {
// check assignable first, see: types/shift_b6.gno
assertAssignableTo(xt, t, autoNative)

if t == nil || t.Kind() == InterfaceKind {
t = defaultTypeOf(xt)
}

bx.assertShiftExprCompatible2(t)
checkOrConvertType(store, last, &bx.Left, t, autoNative)
} else {
assertAssignableTo(xt, t, autoNative)
}
return
} else if *x != nil {
xt := evalStaticTypeOf(store, last, *x)
if t != nil {
assertAssignableTo(xt, t, autoNative)
Expand All @@ -2853,19 +2936,53 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative
switch bx.Op {
case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR,
BAND_NOT, LAND, LOR:
// push t into bx.Left and bx.Right
checkOrConvertType(store, last, &bx.Left, t, autoNative)
checkOrConvertType(store, last, &bx.Right, t, autoNative)
return
case SHL, SHR:
// push t into bx.Left
checkOrConvertType(store, last, &bx.Left, t, autoNative)
lt := evalStaticTypeOf(store, last, bx.Left)
rt := evalStaticTypeOf(store, last, bx.Right)
if t != nil {
// push t into bx.Left and bx.Right
checkOrConvertType(store, last, &bx.Left, t, autoNative)
checkOrConvertType(store, last, &bx.Right, t, autoNative)
return
} else {
if shouldSwapOnSpecificity(lt, rt) {
// e.g. 1.0<<s + 1
// The expression '1.0<<s' does not trigger assertions of
// incompatible types when evaluated alone.
// However, when evaluating the full expression '1.0<<s + 1'
// without a specific context type, '1.0<<s' is checked against
// its default type, the BigDecKind, will trigger assertion failure.
// so here in checkOrConvertType, shift expression is "finally" checked.
checkOrConvertType(store, last, &bx.Left, lt, autoNative)
checkOrConvertType(store, last, &bx.Right, lt, autoNative)
} else {
checkOrConvertType(store, last, &bx.Left, rt, autoNative)
checkOrConvertType(store, last, &bx.Right, rt, autoNative)
}
}
return
case EQL, LSS, GTR, NEQ, LEQ, GEQ:
// do nothing
lt := evalStaticTypeOf(store, last, bx.Left)
rt := evalStaticTypeOf(store, last, bx.Right)
if shouldSwapOnSpecificity(lt, rt) {
checkOrConvertType(store, last, &bx.Left, lt, autoNative)
checkOrConvertType(store, last, &bx.Right, lt, autoNative)
} else {
checkOrConvertType(store, last, &bx.Left, rt, autoNative)
checkOrConvertType(store, last, &bx.Right, rt, autoNative)
}
default:
// do nothing
}
} else if ux, ok := (*x).(*UnaryExpr); ok {
xt := evalStaticTypeOf(store, last, *x)
// check assignable first
assertAssignableTo(xt, t, autoNative)

if t == nil || t.Kind() == InterfaceKind {
t = defaultTypeOf(xt)
}
checkOrConvertType(store, last, &ux.X, t, autoNative)
return
}
}
}
Expand All @@ -2891,9 +3008,6 @@ func convertType(store Store, last BlockNode, x *Expr, t Type) {
if t == nil {
t = defaultTypeOf(xt)
}
if debug {
debug.Printf("default type of t: %v \n", t)
}
// convert x to destination type t
doConvertType(store, last, x, t)
} else {
Expand Down
Loading
Loading