// checkObj type checks an object. func (c *checker) checkObj(obj *ast.Object, ref bool) { if obj.Type != nil { // object has already been type checked return } switch obj.Kind { case ast.Bad: // ignore case ast.Con: // TODO(gri) complete this case ast.Typ: typ := &Name{Obj: obj} obj.Type = typ // "mark" object so recursion terminates typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref)) case ast.Var: // TODO(gri) complete this case ast.Fun: // TODO(gri) complete this default: panic("unreachable") } }
func (tc *typechecker) resolve(obj *ast.Object) { // check for declaration cycles if tc.cyclemap[obj] { tc.Errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name) obj.Kind = ast.Bad return } tc.cyclemap[obj] = true defer func() { delete(tc.cyclemap, obj) }() // resolve non-type objects typ, _ := obj.Type.(*Type) if typ == nil { switch obj.Kind { case ast.Bad: // ignore case ast.Con: tc.declConst(obj) case ast.Var: tc.declVar(obj) obj.Type = tc.typeFor(nil, obj.Decl.(*ast.ValueSpec).Type, false) case ast.Fun: obj.Type = NewType(Function) t := obj.Decl.(*ast.FuncDecl).Type tc.declSignature(obj.Type.(*Type), nil, t.Params, t.Results) default: // type objects have non-nil types when resolve is called if debug { fmt.Printf("kind = %s\n", obj.Kind) } panic("unreachable") } return } // resolve type objects if typ.Form == Unresolved { tc.typeFor(typ, typ.Obj.Decl.(*ast.TypeSpec).Type, false) // provide types for all methods for _, obj := range typ.Scope.Objects { if obj.Kind == ast.Fun { assert(obj.Type == nil) obj.Type = NewType(Method) f := obj.Decl.(*ast.FuncDecl) t := f.Type tc.declSignature(obj.Type.(*Type), f.Recv, t.Params, t.Results) } } } }