fix: do type check on assignment (#738)
* fix: do type check on assignment * fix: check for recursive type rather than field
This commit is contained in:
11
_test/assign15.go
Normal file
11
_test/assign15.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var c chan<- struct{} = make(chan struct{})
|
||||
var d <-chan struct{} = c
|
||||
|
||||
_ = d
|
||||
}
|
||||
|
||||
// Error:
|
||||
// _test/assign15.go:5:26: cannot use type chan<- struct{} as type <-chan struct{} in assignment
|
||||
@@ -518,6 +518,22 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
|
||||
err = src.cfgErrorf("invalid float truncate")
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Rudimentary type check at this point,
|
||||
// improvements need to be made to make it better.
|
||||
switch {
|
||||
case dest.typ.untyped || src.typ.untyped:
|
||||
// Both side of the assignment must be typed.
|
||||
case isRecursiveType(dest.typ, dest.typ.rtype) || isRecursiveType(src.typ, src.typ.rtype):
|
||||
// Recursive types cannot be type checked.
|
||||
case t0.Kind() == reflect.Interface || t0.Kind() == reflect.Func:
|
||||
// We have no way of checking interfaces and functions.
|
||||
case t1.AssignableTo(t0):
|
||||
// All is well when they are assignable.
|
||||
default:
|
||||
err = src.cfgErrorf("cannot use type %s as type %s in assignment", src.typ.id(), dest.typ.id())
|
||||
return
|
||||
}
|
||||
}
|
||||
n.findex = dest.findex
|
||||
n.level = dest.level
|
||||
@@ -1157,6 +1173,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
|
||||
case n.ident == "iota":
|
||||
n.rval = reflect.ValueOf(sc.iota)
|
||||
n.kind = basicLit
|
||||
n.typ.untyped = true
|
||||
case n.ident == "nil":
|
||||
n.kind = basicLit
|
||||
case sym.kind == binSym:
|
||||
|
||||
@@ -35,6 +35,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
|
||||
if filepath.Ext(file.Name()) != ".go" ||
|
||||
file.Name() == "assign11.go" || // expect error
|
||||
file.Name() == "assign12.go" || // expect error
|
||||
file.Name() == "assign15.go" || // expect error
|
||||
file.Name() == "bad0.go" || // expect error
|
||||
file.Name() == "const9.go" || // expect error
|
||||
file.Name() == "export1.go" || // non-main package
|
||||
|
||||
@@ -1013,7 +1013,11 @@ func (t *itype) id() (res string) {
|
||||
case arrayT:
|
||||
res = "[" + strconv.Itoa(t.size) + "]" + t.val.id()
|
||||
case chanT:
|
||||
res = "<-" + t.val.id()
|
||||
res = "chan " + t.val.id()
|
||||
case chanSendT:
|
||||
res = "chan<- " + t.val.id()
|
||||
case chanRecvT:
|
||||
res = "<-chan " + t.val.id()
|
||||
case funcT:
|
||||
res = "func("
|
||||
for _, t := range t.arg {
|
||||
|
||||
Reference in New Issue
Block a user