...
Run Format

Source file src/go/types/decl.go

     1	// Copyright 2014 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.
     4	
     5	package types
     6	
     7	import (
     8		"go/ast"
     9		"go/constant"
    10		"go/token"
    11	)
    12	
    13	func (check *Checker) reportAltDecl(obj Object) {
    14		if pos := obj.Pos(); pos.IsValid() {
    15			// We use "other" rather than "previous" here because
    16			// the first declaration seen may not be textually
    17			// earlier in the source.
    18			check.errorf(pos, "\tother declaration of %s", obj.Name()) // secondary error, \t indented
    19		}
    20	}
    21	
    22	func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token.Pos) {
    23		// spec: "The blank identifier, represented by the underscore
    24		// character _, may be used in a declaration like any other
    25		// identifier but the declaration does not introduce a new
    26		// binding."
    27		if obj.Name() != "_" {
    28			if alt := scope.Insert(obj); alt != nil {
    29				check.errorf(obj.Pos(), "%s redeclared in this block", obj.Name())
    30				check.reportAltDecl(alt)
    31				return
    32			}
    33			obj.setScopePos(pos)
    34		}
    35		if id != nil {
    36			check.recordDef(id, obj)
    37		}
    38	}
    39	
    40	// objDecl type-checks the declaration of obj in its respective (file) context.
    41	// See check.typ for the details on def and path.
    42	func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
    43		if obj.Type() != nil {
    44			return // already checked - nothing to do
    45		}
    46	
    47		if trace {
    48			check.trace(obj.Pos(), "-- declaring %s", obj.Name())
    49			check.indent++
    50			defer func() {
    51				check.indent--
    52				check.trace(obj.Pos(), "=> %s", obj)
    53			}()
    54		}
    55	
    56		d := check.objMap[obj]
    57		if d == nil {
    58			check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
    59			unreachable()
    60		}
    61	
    62		// save/restore current context and setup object context
    63		defer func(ctxt context) {
    64			check.context = ctxt
    65		}(check.context)
    66		check.context = context{
    67			scope: d.file,
    68		}
    69	
    70		// Const and var declarations must not have initialization
    71		// cycles. We track them by remembering the current declaration
    72		// in check.decl. Initialization expressions depending on other
    73		// consts, vars, or functions, add dependencies to the current
    74		// check.decl.
    75		switch obj := obj.(type) {
    76		case *Const:
    77			check.decl = d // new package-level const decl
    78			check.constDecl(obj, d.typ, d.init)
    79		case *Var:
    80			check.decl = d // new package-level var decl
    81			check.varDecl(obj, d.lhs, d.typ, d.init)
    82		case *TypeName:
    83			// invalid recursive types are detected via path
    84			check.typeDecl(obj, d.typ, def, path)
    85		case *Func:
    86			// functions may be recursive - no need to track dependencies
    87			check.funcDecl(obj, d)
    88		// Alias-related code. Keep for now.
    89		// case *Alias:
    90		// 	// aliases cannot be recursive - no need to track dependencies
    91		// 	check.aliasDecl(obj, d)
    92		default:
    93			unreachable()
    94		}
    95	}
    96	
    97	func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
    98		assert(obj.typ == nil)
    99	
   100		if obj.visited {
   101			obj.typ = Typ[Invalid]
   102			return
   103		}
   104		obj.visited = true
   105	
   106		// use the correct value of iota
   107		assert(check.iota == nil)
   108		check.iota = obj.val
   109		defer func() { check.iota = nil }()
   110	
   111		// provide valid constant value under all circumstances
   112		obj.val = constant.MakeUnknown()
   113	
   114		// determine type, if any
   115		if typ != nil {
   116			t := check.typ(typ)
   117			if !isConstType(t) {
   118				check.errorf(typ.Pos(), "invalid constant type %s", t)
   119				obj.typ = Typ[Invalid]
   120				return
   121			}
   122			obj.typ = t
   123		}
   124	
   125		// check initialization
   126		var x operand
   127		if init != nil {
   128			check.expr(&x, init)
   129		}
   130		check.initConst(obj, &x)
   131	}
   132	
   133	func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
   134		assert(obj.typ == nil)
   135	
   136		if obj.visited {
   137			obj.typ = Typ[Invalid]
   138			return
   139		}
   140		obj.visited = true
   141	
   142		// var declarations cannot use iota
   143		assert(check.iota == nil)
   144	
   145		// determine type, if any
   146		if typ != nil {
   147			obj.typ = check.typ(typ)
   148			// We cannot spread the type to all lhs variables if there
   149			// are more than one since that would mark them as checked
   150			// (see Checker.objDecl) and the assignment of init exprs,
   151			// if any, would not be checked.
   152			//
   153			// TODO(gri) If we have no init expr, we should distribute
   154			// a given type otherwise we need to re-evalate the type
   155			// expr for each lhs variable, leading to duplicate work.
   156		}
   157	
   158		// check initialization
   159		if init == nil {
   160			if typ == nil {
   161				// error reported before by arityMatch
   162				obj.typ = Typ[Invalid]
   163			}
   164			return
   165		}
   166	
   167		if lhs == nil || len(lhs) == 1 {
   168			assert(lhs == nil || lhs[0] == obj)
   169			var x operand
   170			check.expr(&x, init)
   171			check.initVar(obj, &x, "variable declaration")
   172			return
   173		}
   174	
   175		if debug {
   176			// obj must be one of lhs
   177			found := false
   178			for _, lhs := range lhs {
   179				if obj == lhs {
   180					found = true
   181					break
   182				}
   183			}
   184			if !found {
   185				panic("inconsistent lhs")
   186			}
   187		}
   188	
   189		// We have multiple variables on the lhs and one init expr.
   190		// Make sure all variables have been given the same type if
   191		// one was specified, otherwise they assume the type of the
   192		// init expression values (was issue #15755).
   193		if typ != nil {
   194			for _, lhs := range lhs {
   195				lhs.typ = obj.typ
   196			}
   197		}
   198	
   199		check.initVars(lhs, []ast.Expr{init}, token.NoPos)
   200	}
   201	
   202	// underlying returns the underlying type of typ; possibly by following
   203	// forward chains of named types. Such chains only exist while named types
   204	// are incomplete.
   205	func underlying(typ Type) Type {
   206		for {
   207			n, _ := typ.(*Named)
   208			if n == nil {
   209				break
   210			}
   211			typ = n.underlying
   212		}
   213		return typ
   214	}
   215	
   216	func (n *Named) setUnderlying(typ Type) {
   217		if n != nil {
   218			n.underlying = typ
   219		}
   220	}
   221	
   222	func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName) {
   223		assert(obj.typ == nil)
   224	
   225		// type declarations cannot use iota
   226		assert(check.iota == nil)
   227	
   228		named := &Named{obj: obj}
   229		def.setUnderlying(named)
   230		obj.typ = named // make sure recursive type declarations terminate
   231	
   232		// determine underlying type of named
   233		check.typExpr(typ, named, append(path, obj))
   234	
   235		// The underlying type of named may be itself a named type that is
   236		// incomplete:
   237		//
   238		//	type (
   239		//		A B
   240		//		B *C
   241		//		C A
   242		//	)
   243		//
   244		// The type of C is the (named) type of A which is incomplete,
   245		// and which has as its underlying type the named type B.
   246		// Determine the (final, unnamed) underlying type by resolving
   247		// any forward chain (they always end in an unnamed type).
   248		named.underlying = underlying(named.underlying)
   249	
   250		// check and add associated methods
   251		// TODO(gri) It's easy to create pathological cases where the
   252		// current approach is incorrect: In general we need to know
   253		// and add all methods _before_ type-checking the type.
   254		// See https://play.golang.org/p/WMpE0q2wK8
   255		check.addMethodDecls(obj)
   256	}
   257	
   258	func (check *Checker) addMethodDecls(obj *TypeName) {
   259		// get associated methods
   260		methods := check.methods[obj.name]
   261		if len(methods) == 0 {
   262			return // no methods
   263		}
   264		delete(check.methods, obj.name)
   265	
   266		// use an objset to check for name conflicts
   267		var mset objset
   268	
   269		// spec: "If the base type is a struct type, the non-blank method
   270		// and field names must be distinct."
   271		base := obj.typ.(*Named)
   272		if t, _ := base.underlying.(*Struct); t != nil {
   273			for _, fld := range t.fields {
   274				if fld.name != "_" {
   275					assert(mset.insert(fld) == nil)
   276				}
   277			}
   278		}
   279	
   280		// Checker.Files may be called multiple times; additional package files
   281		// may add methods to already type-checked types. Add pre-existing methods
   282		// so that we can detect redeclarations.
   283		for _, m := range base.methods {
   284			assert(m.name != "_")
   285			assert(mset.insert(m) == nil)
   286		}
   287	
   288		// type-check methods
   289		for _, m := range methods {
   290			// spec: "For a base type, the non-blank names of methods bound
   291			// to it must be unique."
   292			if m.name != "_" {
   293				if alt := mset.insert(m); alt != nil {
   294					switch alt.(type) {
   295					case *Var:
   296						check.errorf(m.pos, "field and method with the same name %s", m.name)
   297					case *Func:
   298						check.errorf(m.pos, "method %s already declared for %s", m.name, base)
   299					default:
   300						unreachable()
   301					}
   302					check.reportAltDecl(alt)
   303					continue
   304				}
   305			}
   306			check.objDecl(m, nil, nil)
   307			// methods with blank _ names cannot be found - don't keep them
   308			if m.name != "_" {
   309				base.methods = append(base.methods, m)
   310			}
   311		}
   312	}
   313	
   314	func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
   315		assert(obj.typ == nil)
   316	
   317		// func declarations cannot use iota
   318		assert(check.iota == nil)
   319	
   320		sig := new(Signature)
   321		obj.typ = sig // guard against cycles
   322		fdecl := decl.fdecl
   323		check.funcType(sig, fdecl.Recv, fdecl.Type)
   324		if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) {
   325			check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
   326			// ok to continue
   327		}
   328	
   329		// function body must be type-checked after global declarations
   330		// (functions implemented elsewhere have no body)
   331		if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
   332			check.later(obj.name, decl, sig, fdecl.Body)
   333		}
   334	}
   335	
   336	// original returns the original Object if obj is an Alias;
   337	// otherwise it returns obj. The result is never an Alias,
   338	// but it may be nil.
   339	func original(obj Object) Object {
   340		// an alias stands for the original object; use that one instead
   341		if alias, _ := obj.(*disabledAlias); alias != nil {
   342			obj = alias.orig
   343			// aliases always refer to non-alias originals
   344			if _, ok := obj.(*disabledAlias); ok {
   345				panic("original is an alias")
   346			}
   347		}
   348		return obj
   349	}
   350	
   351	func (check *Checker) aliasDecl(obj *disabledAlias, decl *declInfo) {
   352		assert(obj.typ == nil)
   353	
   354		// alias declarations cannot use iota
   355		assert(check.iota == nil)
   356	
   357		// assume alias is invalid to start with
   358		obj.typ = Typ[Invalid]
   359	
   360		// rhs must be package-qualified identifer pkg.sel (see also call.go: checker.selector)
   361		// TODO(gri) factor this code out and share with checker.selector
   362		rhs := decl.init
   363		var pkg *Package
   364		var sel *ast.Ident
   365		if sexpr, ok := rhs.(*ast.SelectorExpr); ok {
   366			if ident, ok := sexpr.X.(*ast.Ident); ok {
   367				_, obj := check.scope.LookupParent(ident.Name, check.pos)
   368				if pname, _ := obj.(*PkgName); pname != nil {
   369					assert(pname.pkg == check.pkg)
   370					check.recordUse(ident, pname)
   371					pname.used = true
   372					pkg = pname.imported
   373					sel = sexpr.Sel
   374				}
   375			}
   376		}
   377		if pkg == nil {
   378			check.errorf(rhs.Pos(), "invalid alias: %v is not a package-qualified identifier", rhs)
   379			return
   380		}
   381	
   382		// qualified identifier must denote an exported object
   383		orig := pkg.scope.Lookup(sel.Name)
   384		if orig == nil || !orig.Exported() {
   385			if !pkg.fake {
   386				check.errorf(rhs.Pos(), "%s is not exported by package %s", sel.Name, pkg.name)
   387			}
   388			return
   389		}
   390		check.recordUse(sel, orig)
   391		orig = original(orig)
   392	
   393		// avoid further errors if the imported object is an alias that's broken
   394		if orig == nil {
   395			return
   396		}
   397	
   398		// An alias declaration must not refer to package unsafe.
   399		if orig.Pkg() == Unsafe {
   400			check.errorf(rhs.Pos(), "invalid alias: %s refers to package unsafe (%v)", obj.Name(), orig)
   401			return
   402		}
   403	
   404		// The original must be of the same kind as the alias declaration.
   405		var why string
   406		switch obj.kind {
   407		case token.CONST:
   408			if _, ok := orig.(*Const); !ok {
   409				why = "constant"
   410			}
   411		case token.TYPE:
   412			if _, ok := orig.(*TypeName); !ok {
   413				why = "type"
   414			}
   415		case token.VAR:
   416			if _, ok := orig.(*Var); !ok {
   417				why = "variable"
   418			}
   419		case token.FUNC:
   420			if _, ok := orig.(*Func); !ok {
   421				why = "function"
   422			}
   423		default:
   424			unreachable()
   425		}
   426		if why != "" {
   427			check.errorf(rhs.Pos(), "invalid alias: %v is not a %s", orig, why)
   428			return
   429		}
   430	
   431		// alias is valid
   432		obj.typ = orig.Type()
   433		obj.orig = orig
   434	}
   435	
   436	func (check *Checker) declStmt(decl ast.Decl) {
   437		pkg := check.pkg
   438	
   439		switch d := decl.(type) {
   440		case *ast.BadDecl:
   441			// ignore
   442	
   443		case *ast.GenDecl:
   444			var last *ast.ValueSpec // last ValueSpec with type or init exprs seen
   445			for iota, spec := range d.Specs {
   446				switch s := spec.(type) {
   447				case *ast.ValueSpec:
   448					switch d.Tok {
   449					case token.CONST:
   450						// determine which init exprs to use
   451						switch {
   452						case s.Type != nil || len(s.Values) > 0:
   453							last = s
   454						case last == nil:
   455							last = new(ast.ValueSpec) // make sure last exists
   456						}
   457	
   458						// declare all constants
   459						lhs := make([]*Const, len(s.Names))
   460						for i, name := range s.Names {
   461							obj := NewConst(name.Pos(), pkg, name.Name, nil, constant.MakeInt64(int64(iota)))
   462							lhs[i] = obj
   463	
   464							var init ast.Expr
   465							if i < len(last.Values) {
   466								init = last.Values[i]
   467							}
   468	
   469							check.constDecl(obj, last.Type, init)
   470						}
   471	
   472						check.arityMatch(s, last)
   473	
   474						// spec: "The scope of a constant or variable identifier declared
   475						// inside a function begins at the end of the ConstSpec or VarSpec
   476						// (ShortVarDecl for short variable declarations) and ends at the
   477						// end of the innermost containing block."
   478						scopePos := s.End()
   479						for i, name := range s.Names {
   480							check.declare(check.scope, name, lhs[i], scopePos)
   481						}
   482	
   483					case token.VAR:
   484						lhs0 := make([]*Var, len(s.Names))
   485						for i, name := range s.Names {
   486							lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil)
   487						}
   488	
   489						// initialize all variables
   490						for i, obj := range lhs0 {
   491							var lhs []*Var
   492							var init ast.Expr
   493							switch len(s.Values) {
   494							case len(s.Names):
   495								// lhs and rhs match
   496								init = s.Values[i]
   497							case 1:
   498								// rhs is expected to be a multi-valued expression
   499								lhs = lhs0
   500								init = s.Values[0]
   501							default:
   502								if i < len(s.Values) {
   503									init = s.Values[i]
   504								}
   505							}
   506							check.varDecl(obj, lhs, s.Type, init)
   507							if len(s.Values) == 1 {
   508								// If we have a single lhs variable we are done either way.
   509								// If we have a single rhs expression, it must be a multi-
   510								// valued expression, in which case handling the first lhs
   511								// variable will cause all lhs variables to have a type
   512								// assigned, and we are done as well.
   513								if debug {
   514									for _, obj := range lhs0 {
   515										assert(obj.typ != nil)
   516									}
   517								}
   518								break
   519							}
   520						}
   521	
   522						check.arityMatch(s, nil)
   523	
   524						// declare all variables
   525						// (only at this point are the variable scopes (parents) set)
   526						scopePos := s.End() // see constant declarations
   527						for i, name := range s.Names {
   528							// see constant declarations
   529							check.declare(check.scope, name, lhs0[i], scopePos)
   530						}
   531	
   532					default:
   533						check.invalidAST(s.Pos(), "invalid token %s", d.Tok)
   534					}
   535	
   536				case *ast.TypeSpec:
   537					obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Name, nil)
   538					// spec: "The scope of a type identifier declared inside a function
   539					// begins at the identifier in the TypeSpec and ends at the end of
   540					// the innermost containing block."
   541					scopePos := s.Name.Pos()
   542					check.declare(check.scope, s.Name, obj, scopePos)
   543					check.typeDecl(obj, s.Type, nil, nil)
   544	
   545				default:
   546					check.invalidAST(s.Pos(), "const, type, or var declaration expected")
   547				}
   548			}
   549	
   550		default:
   551			check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d)
   552		}
   553	}
   554	

View as plain text