-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathcheckfunclit.go
62 lines (56 loc) · 1.45 KB
/
checkfunclit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package eval
import (
"go/ast"
"reflect"
)
func checkFuncLit(lit *ast.FuncLit, env Env) (*FuncLit, []error) {
alit := &FuncLit{FuncLit: lit}
atype, t, _, errs := checkType(lit.Type, env)
alit.Type = atype.(*FuncType)
if t != nil {
alit.knownType = knownType{t}
}
// Create a new environment containing all valid params and results.
seen := map[string]bool{}
invalid := map[string]bool{}
env = env.PushScope()
fields := alit.Type.Params
// Type.Results may be nil
for i := 0; i < 2 && fields != nil; i += 1 {
for _, field := range fields.List {
var z reflect.Value
if len(field.KnownType()) != 0 {
z = reflect.New(field.KnownType()[0])
}
for _, name := range field.Names {
if name.Name == "_" {
continue
}
if !z.IsValid() {
invalid[name.Name] = true
} else {
env.AddVar(name.Name, z)
}
if seen[name.Name] {
errs = append(errs, ErrDuplicateArg{name})
}
seen[name.Name] = true
}
}
fields = alit.Type.Results
}
// t may be nil, in this case return statements won't be checked
block, moreErrs := checkBlock(lit.Body, env, checkCtx{outerFunc: t})
alit.Body = block
// Filter out undefined errors caused by invalid params
var filtered []error
for _, err := range moreErrs {
if undef, ok := err.(ErrUndefined); ok {
if ident, ok := undef.Expr.(*Ident); ok && invalid[ident.Name] {
continue
}
}
filtered = append(filtered, err)
}
return alit, append(errs, filtered...)
}