1 // Copyright 2021 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 const debugResolve = false
16 // resolveFile walks the given file to resolve identifiers within the file
17 // scope, updating ast.Ident.Obj fields with declaration information.
19 // If declErr is non-nil, it is used to report declaration errors during
20 // resolution. tok is used to format position in error messages.
21 func resolveFile(file *ast.File, handle *token.File, declErr func(token.Pos, string)) {
22 pkgScope := ast.NewScope(nil)
31 for _, decl := range file.Decls {
36 assert(r.topScope == nil, "unbalanced scopes")
37 assert(r.labelScope == nil, "unbalanced label scopes")
39 // resolve global identifiers within the same file
41 for _, ident := range r.unresolved {
42 // i <= index for current ident
43 assert(ident.Obj == unresolved, "object already resolved")
44 ident.Obj = r.pkgScope.Lookup(ident.Name) // also removes unresolved sentinel
46 r.unresolved[i] = ident
48 } else if debugResolve {
49 pos := ident.Obj.Decl.(interface{ Pos() token.Pos }).Pos()
50 r.trace("resolved %s@%v to package object %v", ident.Name, ident.Pos(), pos)
53 file.Scope = r.pkgScope
54 file.Unresolved = r.unresolved[0:i]
57 const maxScopeDepth int = 1e3
59 type resolver struct {
61 declErr func(token.Pos, string)
63 // Ordinary identifier scopes
64 pkgScope *ast.Scope // pkgScope.Outer == nil
65 topScope *ast.Scope // top-most scope; may be pkgScope
66 unresolved []*ast.Ident // unresolved identifiers
67 depth int // scope depth
70 // (maintained by open/close LabelScope)
71 labelScope *ast.Scope // label scope for current function
72 targetStack [][]*ast.Ident // stack of unresolved labels
75 func (r *resolver) trace(format string, args ...any) {
76 fmt.Println(strings.Repeat(". ", r.depth) + r.sprintf(format, args...))
79 func (r *resolver) sprintf(format string, args ...any) string {
80 for i, arg := range args {
81 switch arg := arg.(type) {
83 args[i] = r.handle.Position(arg)
86 return fmt.Sprintf(format, args...)
89 func (r *resolver) openScope(pos token.Pos) {
91 if r.depth > maxScopeDepth {
92 panic(bailout{pos: pos, msg: "exceeded max scope depth during object resolution"})
95 r.trace("opening scope @%v", pos)
97 r.topScope = ast.NewScope(r.topScope)
100 func (r *resolver) closeScope() {
103 r.trace("closing scope")
105 r.topScope = r.topScope.Outer
108 func (r *resolver) openLabelScope() {
109 r.labelScope = ast.NewScope(r.labelScope)
110 r.targetStack = append(r.targetStack, nil)
113 func (r *resolver) closeLabelScope() {
115 n := len(r.targetStack) - 1
116 scope := r.labelScope
117 for _, ident := range r.targetStack[n] {
118 ident.Obj = scope.Lookup(ident.Name)
119 if ident.Obj == nil && r.declErr != nil {
120 r.declErr(ident.Pos(), fmt.Sprintf("label %s undefined", ident.Name))
124 r.targetStack = r.targetStack[0:n]
125 r.labelScope = r.labelScope.Outer
128 func (r *resolver) declare(decl, data any, scope *ast.Scope, kind ast.ObjKind, idents ...*ast.Ident) {
129 for _, ident := range idents {
130 if ident.Obj != nil {
131 panic(fmt.Sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
133 obj := ast.NewObj(kind, ident.Name)
134 // remember the corresponding declaration for redeclaration
135 // errors and global variable resolution/typechecking phase
138 // Identifiers (for receiver type parameters) are written to the scope, but
139 // never set as the resolved object. See issue #50956.
140 if _, ok := decl.(*ast.Ident); !ok {
143 if ident.Name != "_" {
145 r.trace("declaring %s@%v", ident.Name, ident.Pos())
147 if alt := scope.Insert(obj); alt != nil && r.declErr != nil {
149 if pos := alt.Pos(); pos.IsValid() {
150 prevDecl = r.sprintf("\n\tprevious declaration at %v", pos)
152 r.declErr(ident.Pos(), fmt.Sprintf("%s redeclared in this block%s", ident.Name, prevDecl))
158 func (r *resolver) shortVarDecl(decl *ast.AssignStmt) {
159 // Go spec: A short variable declaration may redeclare variables
160 // provided they were originally declared in the same block with
161 // the same type, and at least one of the non-blank variables is new.
162 n := 0 // number of new variables
163 for _, x := range decl.Lhs {
164 if ident, isIdent := x.(*ast.Ident); isIdent {
165 assert(ident.Obj == nil, "identifier already declared or resolved")
166 obj := ast.NewObj(ast.Var, ident.Name)
167 // remember corresponding assignment for other tools
170 if ident.Name != "_" {
172 r.trace("declaring %s@%v", ident.Name, ident.Pos())
174 if alt := r.topScope.Insert(obj); alt != nil {
175 ident.Obj = alt // redeclaration
177 n++ // new declaration
182 if n == 0 && r.declErr != nil {
183 r.declErr(decl.Lhs[0].Pos(), "no new variables on left side of :=")
187 // The unresolved object is a sentinel to mark identifiers that have been added
188 // to the list of unresolved identifiers. The sentinel is only used for verifying
189 // internal consistency.
190 var unresolved = new(ast.Object)
192 // If x is an identifier, resolve attempts to resolve x by looking up
193 // the object it denotes. If no object is found and collectUnresolved is
194 // set, x is marked as unresolved and collected in the list of unresolved
196 func (r *resolver) resolve(ident *ast.Ident, collectUnresolved bool) {
197 if ident.Obj != nil {
198 panic(r.sprintf("%v: identifier %s already declared or resolved", ident.Pos(), ident.Name))
200 // '_' should never refer to existing declarations, because it has special
201 // handling in the spec.
202 if ident.Name == "_" {
205 for s := r.topScope; s != nil; s = s.Outer {
206 if obj := s.Lookup(ident.Name); obj != nil {
208 r.trace("resolved %v:%s to %v", ident.Pos(), ident.Name, obj)
210 assert(obj.Name != "", "obj with no name")
211 // Identifiers (for receiver type parameters) are written to the scope,
212 // but never set as the resolved object. See issue #50956.
213 if _, ok := obj.Decl.(*ast.Ident); !ok {
219 // all local scopes are known, so any unresolved identifier
220 // must be found either in the file scope, package scope
221 // (perhaps in another file), or universe scope --- collect
222 // them so that they can be resolved later
223 if collectUnresolved {
224 ident.Obj = unresolved
225 r.unresolved = append(r.unresolved, ident)
229 func (r *resolver) walkExprs(list []ast.Expr) {
230 for _, node := range list {
235 func (r *resolver) walkLHS(list []ast.Expr) {
236 for _, expr := range list {
237 expr := ast.Unparen(expr)
238 if _, ok := expr.(*ast.Ident); !ok && expr != nil {
244 func (r *resolver) walkStmts(list []ast.Stmt) {
245 for _, stmt := range list {
250 func (r *resolver) Visit(node ast.Node) ast.Visitor {
251 if debugResolve && node != nil {
252 r.trace("node %T@%v", node, node.Pos())
255 switch n := node.(type) {
264 r.walkFuncType(n.Type)
267 case *ast.SelectorExpr:
269 // Note: don't try to resolve n.Sel, as we don't support qualified
272 case *ast.StructType:
275 r.walkFieldList(n.Fields, ast.Var)
282 case *ast.CompositeLit:
286 for _, e := range n.Elts {
287 if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
288 // See issue #45160: try to resolve composite lit keys, but don't
289 // collect them as unresolved if resolution failed. This replicates
290 // existing behavior when resolving during parsing.
291 if ident, _ := kv.Key.(*ast.Ident); ident != nil {
292 r.resolve(ident, false)
296 ast.Walk(r, kv.Value)
302 case *ast.InterfaceType:
305 r.walkFieldList(n.Methods, ast.Fun)
308 case *ast.LabeledStmt:
309 r.declare(n, nil, r.labelScope, ast.Lbl, n.Label)
312 case *ast.AssignStmt:
314 if n.Tok == token.DEFINE {
320 case *ast.BranchStmt:
321 // add to list of unresolved targets
322 if n.Tok != token.FALLTHROUGH && n.Label != nil {
323 depth := len(r.targetStack) - 1
324 r.targetStack[depth] = append(r.targetStack[depth], n.Label)
344 case *ast.CaseClause:
350 case *ast.SwitchStmt:
357 // The scope below reproduces some unnecessary behavior of the parser,
358 // opening an extra scope in case this is a type switch. It's not needed
359 // for expression switches.
360 // TODO: remove this once we've matched the parser resolution exactly.
362 r.openScope(n.Tag.Pos())
368 r.walkStmts(n.Body.List)
371 case *ast.TypeSwitchStmt:
377 r.openScope(n.Assign.Pos())
379 ast.Walk(r, n.Assign)
380 // s.Body consists only of case clauses, so does not get its own
383 r.walkStmts(n.Body.List)
386 case *ast.CommClause:
394 case *ast.SelectStmt:
395 // as for switch statements, select statement bodies don't get their own
398 r.walkStmts(n.Body.List)
421 lhs = append(lhs, n.Key)
424 lhs = append(lhs, n.Value)
427 if n.Tok == token.DEFINE {
428 // Note: we can't exactly match the behavior of object resolution
429 // during the parsing pass here, as it uses the position of the RANGE
430 // token for the RHS OpPos. That information is not contained within
432 as := &ast.AssignStmt{
436 Rhs: []ast.Expr{&ast.UnaryExpr{Op: token.RANGE, X: n.X}},
438 // TODO(rFindley): this walkLHS reproduced the parser resolution, but
439 // is it necessary? By comparison, for a normal AssignStmt we don't
440 // walk the LHS in case there is an invalid identifier list.
452 case token.CONST, token.VAR:
453 for i, spec := range n.Specs {
454 spec := spec.(*ast.ValueSpec)
456 if n.Tok == token.VAR {
459 r.walkExprs(spec.Values)
460 if spec.Type != nil {
461 ast.Walk(r, spec.Type)
463 r.declare(spec, i, r.topScope, kind, spec.Names...)
466 for _, spec := range n.Specs {
467 spec := spec.(*ast.TypeSpec)
468 // Go spec: The scope of a type identifier declared inside a function begins
469 // at the identifier in the TypeSpec and ends at the end of the innermost
471 r.declare(spec, nil, r.topScope, ast.Typ, spec.Name)
472 if spec.TypeParams != nil {
473 r.openScope(spec.Pos())
475 r.walkTParams(spec.TypeParams)
477 ast.Walk(r, spec.Type)
482 // Open the function scope.
488 // Type parameters are walked normally: they can reference each other, and
489 // can be referenced by normal parameters.
490 if n.Type.TypeParams != nil {
491 r.walkTParams(n.Type.TypeParams)
492 // TODO(rFindley): need to address receiver type parameters.
495 // Resolve and declare parameters in a specific order to get duplicate
496 // declaration errors in the correct location.
497 r.resolveList(n.Type.Params)
498 r.resolveList(n.Type.Results)
499 r.declareList(n.Recv, ast.Var)
500 r.declareList(n.Type.Params, ast.Var)
501 r.declareList(n.Type.Results, ast.Var)
504 if n.Recv == nil && n.Name.Name != "init" {
505 r.declare(n, nil, r.pkgScope, ast.Fun, n.Name)
515 func (r *resolver) walkFuncType(typ *ast.FuncType) {
516 // typ.TypeParams must be walked separately for FuncDecls.
517 r.resolveList(typ.Params)
518 r.resolveList(typ.Results)
519 r.declareList(typ.Params, ast.Var)
520 r.declareList(typ.Results, ast.Var)
523 func (r *resolver) resolveList(list *ast.FieldList) {
527 for _, f := range list.List {
534 func (r *resolver) declareList(list *ast.FieldList, kind ast.ObjKind) {
538 for _, f := range list.List {
539 r.declare(f, nil, r.topScope, kind, f.Names...)
543 func (r *resolver) walkRecv(recv *ast.FieldList) {
544 // If our receiver has receiver type parameters, we must declare them before
545 // trying to resolve the rest of the receiver, and avoid re-resolving the
546 // type parameter identifiers.
547 if recv == nil || len(recv.List) == 0 {
548 return // nothing to do
550 typ := recv.List[0].Type
551 if ptr, ok := typ.(*ast.StarExpr); ok {
555 var declareExprs []ast.Expr // exprs to declare
556 var resolveExprs []ast.Expr // exprs to resolve
557 switch typ := typ.(type) {
559 declareExprs = []ast.Expr{typ.Index}
560 resolveExprs = append(resolveExprs, typ.X)
561 case *ast.IndexListExpr:
562 declareExprs = typ.Indices
563 resolveExprs = append(resolveExprs, typ.X)
565 resolveExprs = append(resolveExprs, typ)
567 for _, expr := range declareExprs {
568 if id, _ := expr.(*ast.Ident); id != nil {
569 r.declare(expr, nil, r.topScope, ast.Typ, id)
571 // The receiver type parameter expression is invalid, but try to resolve
572 // it anyway for consistency.
573 resolveExprs = append(resolveExprs, expr)
576 for _, expr := range resolveExprs {
581 // The receiver is invalid, but try to resolve it anyway for consistency.
582 for _, f := range recv.List[1:] {
589 func (r *resolver) walkFieldList(list *ast.FieldList, kind ast.ObjKind) {
594 r.declareList(list, kind)
597 // walkTParams is like walkFieldList, but declares type parameters eagerly so
598 // that they may be resolved in the constraint expressions held in the field
600 func (r *resolver) walkTParams(list *ast.FieldList) {
601 r.declareList(list, ast.Typ)
605 func (r *resolver) walkBody(body *ast.BlockStmt) {
610 defer r.closeLabelScope()
611 r.walkStmts(body.List)