...
Run Format

Source file src/go/types/typexpr.go

Documentation: go/types

     1  // Copyright 2013 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  // This file implements type-checking of identifiers and type expressions.
     6  
     7  package types
     8  
     9  import (
    10  	"go/ast"
    11  	"go/constant"
    12  	"go/token"
    13  	"sort"
    14  	"strconv"
    15  )
    16  
    17  // ident type-checks identifier e and initializes x with the value or type of e.
    18  // If an error occurred, x.mode is set to invalid.
    19  // For the meaning of def and path, see check.typ, below.
    20  //
    21  func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeName) {
    22  	x.mode = invalid
    23  	x.expr = e
    24  
    25  	// Note that we cannot use check.lookup here because the returned scope
    26  	// may be different from obj.Parent(). See also Scope.LookupParent doc.
    27  	scope, obj := check.scope.LookupParent(e.Name, check.pos)
    28  	if obj == nil {
    29  		if e.Name == "_" {
    30  			check.errorf(e.Pos(), "cannot use _ as value or type")
    31  		} else {
    32  			check.errorf(e.Pos(), "undeclared name: %s", e.Name)
    33  		}
    34  		return
    35  	}
    36  	check.recordUse(e, obj)
    37  
    38  	check.objDecl(obj, def, path)
    39  	typ := obj.Type()
    40  	assert(typ != nil)
    41  
    42  	// The object may be dot-imported: If so, remove its package from
    43  	// the map of unused dot imports for the respective file scope.
    44  	// (This code is only needed for dot-imports. Without them,
    45  	// we only have to mark variables, see *Var case below).
    46  	if pkg := obj.Pkg(); pkg != check.pkg && pkg != nil {
    47  		delete(check.unusedDotImports[scope], pkg)
    48  	}
    49  
    50  	switch obj := obj.(type) {
    51  	case *PkgName:
    52  		check.errorf(e.Pos(), "use of package %s not in selector", obj.name)
    53  		return
    54  
    55  	case *Const:
    56  		check.addDeclDep(obj)
    57  		if typ == Typ[Invalid] {
    58  			return
    59  		}
    60  		if obj == universeIota {
    61  			if check.iota == nil {
    62  				check.errorf(e.Pos(), "cannot use iota outside constant declaration")
    63  				return
    64  			}
    65  			x.val = check.iota
    66  		} else {
    67  			x.val = obj.val
    68  		}
    69  		assert(x.val != nil)
    70  		x.mode = constant_
    71  
    72  	case *TypeName:
    73  		x.mode = typexpr
    74  		// package-level alias cycles are now checked by Checker.objDecl
    75  		if useCycleMarking {
    76  			if check.objMap[obj] != nil {
    77  				break
    78  			}
    79  		}
    80  		if check.cycle(obj, path, true) {
    81  			// maintain x.mode == typexpr despite error
    82  			typ = Typ[Invalid]
    83  			break
    84  		}
    85  
    86  	case *Var:
    87  		// It's ok to mark non-local variables, but ignore variables
    88  		// from other packages to avoid potential race conditions with
    89  		// dot-imported variables.
    90  		if obj.pkg == check.pkg {
    91  			obj.used = true
    92  		}
    93  		check.addDeclDep(obj)
    94  		if typ == Typ[Invalid] {
    95  			return
    96  		}
    97  		x.mode = variable
    98  
    99  	case *Func:
   100  		check.addDeclDep(obj)
   101  		x.mode = value
   102  
   103  	case *Builtin:
   104  		x.id = obj.id
   105  		x.mode = builtin
   106  
   107  	case *Nil:
   108  		x.mode = value
   109  
   110  	default:
   111  		unreachable()
   112  	}
   113  
   114  	x.typ = typ
   115  }
   116  
   117  // cycle reports whether obj appears in path or not.
   118  // If it does, and report is set, it also reports a cycle error.
   119  func (check *Checker) cycle(obj *TypeName, path []*TypeName, report bool) bool {
   120  	// (it's ok to iterate forward because each named type appears at most once in path)
   121  	for i, prev := range path {
   122  		if prev == obj {
   123  			if report {
   124  				check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
   125  				// print cycle
   126  				for _, obj := range path[i:] {
   127  					check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
   128  				}
   129  				check.errorf(obj.Pos(), "\t%s", obj.Name())
   130  			}
   131  			return true
   132  		}
   133  	}
   134  	return false
   135  }
   136  
   137  // typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
   138  // If def != nil, e is the type specification for the named type def, declared
   139  // in a type declaration, and def.underlying will be set to the type of e before
   140  // any components of e are type-checked. Path contains the path of named types
   141  // referring to this type; i.e. it is the path of named types directly containing
   142  // each other and leading to the current type e. Indirect containment (e.g. via
   143  // pointer indirection, function parameter, etc.) breaks the path (leads to a new
   144  // path, and usually via calling Checker.typ below) and those types are not found
   145  // in the path.
   146  //
   147  func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) {
   148  	if trace {
   149  		check.trace(e.Pos(), "%s", e)
   150  		check.indent++
   151  		defer func() {
   152  			check.indent--
   153  			check.trace(e.Pos(), "=> %s", T)
   154  		}()
   155  	}
   156  
   157  	T = check.typExprInternal(e, def, path)
   158  	assert(isTyped(T))
   159  	check.recordTypeAndValue(e, typexpr, T, nil)
   160  
   161  	return
   162  }
   163  
   164  // typ is like typExpr (with a nil argument for the def parameter),
   165  // but typ breaks type cycles. It should be called for components of
   166  // types that break cycles, such as pointer base types, slice or map
   167  // element types, etc. See the comment in typExpr for details.
   168  //
   169  func (check *Checker) typ(e ast.Expr) Type {
   170  	// typExpr is called with a nil path indicating an indirection:
   171  	// push indir sentinel on object path
   172  	if useCycleMarking {
   173  		check.push(indir)
   174  		defer check.pop()
   175  	}
   176  	return check.typExpr(e, nil, nil)
   177  }
   178  
   179  // funcType type-checks a function or method type.
   180  func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
   181  	scope := NewScope(check.scope, token.NoPos, token.NoPos, "function")
   182  	scope.isFunc = true
   183  	check.recordScope(ftyp, scope)
   184  
   185  	recvList, _ := check.collectParams(scope, recvPar, false)
   186  	params, variadic := check.collectParams(scope, ftyp.Params, true)
   187  	results, _ := check.collectParams(scope, ftyp.Results, false)
   188  
   189  	if recvPar != nil {
   190  		// recv parameter list present (may be empty)
   191  		// spec: "The receiver is specified via an extra parameter section preceding the
   192  		// method name. That parameter section must declare a single parameter, the receiver."
   193  		var recv *Var
   194  		switch len(recvList) {
   195  		case 0:
   196  			check.error(recvPar.Pos(), "method is missing receiver")
   197  			recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
   198  		default:
   199  			// more than one receiver
   200  			check.error(recvList[len(recvList)-1].Pos(), "method must have exactly one receiver")
   201  			fallthrough // continue with first receiver
   202  		case 1:
   203  			recv = recvList[0]
   204  		}
   205  		// spec: "The receiver type must be of the form T or *T where T is a type name."
   206  		// (ignore invalid types - error was reported before)
   207  		if t, _ := deref(recv.typ); t != Typ[Invalid] {
   208  			var err string
   209  			if T, _ := t.(*Named); T != nil {
   210  				// spec: "The type denoted by T is called the receiver base type; it must not
   211  				// be a pointer or interface type and it must be declared in the same package
   212  				// as the method."
   213  				if T.obj.pkg != check.pkg {
   214  					err = "type not defined in this package"
   215  				} else {
   216  					// TODO(gri) This is not correct if the underlying type is unknown yet.
   217  					switch u := T.underlying.(type) {
   218  					case *Basic:
   219  						// unsafe.Pointer is treated like a regular pointer
   220  						if u.kind == UnsafePointer {
   221  							err = "unsafe.Pointer"
   222  						}
   223  					case *Pointer, *Interface:
   224  						err = "pointer or interface type"
   225  					}
   226  				}
   227  			} else {
   228  				err = "basic or unnamed type"
   229  			}
   230  			if err != "" {
   231  				check.errorf(recv.pos, "invalid receiver %s (%s)", recv.typ, err)
   232  				// ok to continue
   233  			}
   234  		}
   235  		sig.recv = recv
   236  	}
   237  
   238  	sig.scope = scope
   239  	sig.params = NewTuple(params...)
   240  	sig.results = NewTuple(results...)
   241  	sig.variadic = variadic
   242  }
   243  
   244  // typExprInternal drives type checking of types.
   245  // Must only be called by typExpr.
   246  //
   247  func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName) Type {
   248  	switch e := e.(type) {
   249  	case *ast.BadExpr:
   250  		// ignore - error reported before
   251  
   252  	case *ast.Ident:
   253  		var x operand
   254  		check.ident(&x, e, def, path)
   255  
   256  		switch x.mode {
   257  		case typexpr:
   258  			typ := x.typ
   259  			def.setUnderlying(typ)
   260  			return typ
   261  		case invalid:
   262  			// ignore - error reported before
   263  		case novalue:
   264  			check.errorf(x.pos(), "%s used as type", &x)
   265  		default:
   266  			check.errorf(x.pos(), "%s is not a type", &x)
   267  		}
   268  
   269  	case *ast.SelectorExpr:
   270  		var x operand
   271  		check.selector(&x, e)
   272  
   273  		switch x.mode {
   274  		case typexpr:
   275  			typ := x.typ
   276  			def.setUnderlying(typ)
   277  			return typ
   278  		case invalid:
   279  			// ignore - error reported before
   280  		case novalue:
   281  			check.errorf(x.pos(), "%s used as type", &x)
   282  		default:
   283  			check.errorf(x.pos(), "%s is not a type", &x)
   284  		}
   285  
   286  	case *ast.ParenExpr:
   287  		return check.typExpr(e.X, def, path)
   288  
   289  	case *ast.ArrayType:
   290  		if e.Len != nil {
   291  			typ := new(Array)
   292  			def.setUnderlying(typ)
   293  			typ.len = check.arrayLength(e.Len)
   294  			typ.elem = check.typExpr(e.Elt, nil, path)
   295  			return typ
   296  
   297  		} else {
   298  			typ := new(Slice)
   299  			def.setUnderlying(typ)
   300  			typ.elem = check.typ(e.Elt)
   301  			return typ
   302  		}
   303  
   304  	case *ast.StructType:
   305  		typ := new(Struct)
   306  		def.setUnderlying(typ)
   307  		check.structType(typ, e, path)
   308  		return typ
   309  
   310  	case *ast.StarExpr:
   311  		typ := new(Pointer)
   312  		def.setUnderlying(typ)
   313  		typ.base = check.typ(e.X)
   314  		return typ
   315  
   316  	case *ast.FuncType:
   317  		typ := new(Signature)
   318  		def.setUnderlying(typ)
   319  		check.funcType(typ, nil, e)
   320  		return typ
   321  
   322  	case *ast.InterfaceType:
   323  		typ := new(Interface)
   324  		def.setUnderlying(typ)
   325  		check.interfaceType(typ, e, def, path)
   326  		return typ
   327  
   328  	case *ast.MapType:
   329  		typ := new(Map)
   330  		def.setUnderlying(typ)
   331  
   332  		typ.key = check.typ(e.Key)
   333  		typ.elem = check.typ(e.Value)
   334  
   335  		// spec: "The comparison operators == and != must be fully defined
   336  		// for operands of the key type; thus the key type must not be a
   337  		// function, map, or slice."
   338  		//
   339  		// Delay this check because it requires fully setup types;
   340  		// it is safe to continue in any case (was issue 6667).
   341  		check.later(func() {
   342  			if !Comparable(typ.key) {
   343  				check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key)
   344  			}
   345  		})
   346  
   347  		return typ
   348  
   349  	case *ast.ChanType:
   350  		typ := new(Chan)
   351  		def.setUnderlying(typ)
   352  
   353  		dir := SendRecv
   354  		switch e.Dir {
   355  		case ast.SEND | ast.RECV:
   356  			// nothing to do
   357  		case ast.SEND:
   358  			dir = SendOnly
   359  		case ast.RECV:
   360  			dir = RecvOnly
   361  		default:
   362  			check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir)
   363  			// ok to continue
   364  		}
   365  
   366  		typ.dir = dir
   367  		typ.elem = check.typ(e.Value)
   368  		return typ
   369  
   370  	default:
   371  		check.errorf(e.Pos(), "%s is not a type", e)
   372  	}
   373  
   374  	typ := Typ[Invalid]
   375  	def.setUnderlying(typ)
   376  	return typ
   377  }
   378  
   379  // typeOrNil type-checks the type expression (or nil value) e
   380  // and returns the typ of e, or nil.
   381  // If e is neither a type nor nil, typOrNil returns Typ[Invalid].
   382  //
   383  func (check *Checker) typOrNil(e ast.Expr) Type {
   384  	var x operand
   385  	check.rawExpr(&x, e, nil)
   386  	switch x.mode {
   387  	case invalid:
   388  		// ignore - error reported before
   389  	case novalue:
   390  		check.errorf(x.pos(), "%s used as type", &x)
   391  	case typexpr:
   392  		return x.typ
   393  	case value:
   394  		if x.isNil() {
   395  			return nil
   396  		}
   397  		fallthrough
   398  	default:
   399  		check.errorf(x.pos(), "%s is not a type", &x)
   400  	}
   401  	return Typ[Invalid]
   402  }
   403  
   404  // arrayLength type-checks the array length expression e
   405  // and returns the constant length >= 0, or a value < 0
   406  // to indicate an error (and thus an unknown length).
   407  func (check *Checker) arrayLength(e ast.Expr) int64 {
   408  	var x operand
   409  	check.expr(&x, e)
   410  	if x.mode != constant_ {
   411  		if x.mode != invalid {
   412  			check.errorf(x.pos(), "array length %s must be constant", &x)
   413  		}
   414  		return -1
   415  	}
   416  	if isUntyped(x.typ) || isInteger(x.typ) {
   417  		if val := constant.ToInt(x.val); val.Kind() == constant.Int {
   418  			if representableConst(val, check.conf, Typ[Int], nil) {
   419  				if n, ok := constant.Int64Val(val); ok && n >= 0 {
   420  					return n
   421  				}
   422  				check.errorf(x.pos(), "invalid array length %s", &x)
   423  				return -1
   424  			}
   425  		}
   426  	}
   427  	check.errorf(x.pos(), "array length %s must be integer", &x)
   428  	return -1
   429  }
   430  
   431  func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
   432  	if list == nil {
   433  		return
   434  	}
   435  
   436  	var named, anonymous bool
   437  	for i, field := range list.List {
   438  		ftype := field.Type
   439  		if t, _ := ftype.(*ast.Ellipsis); t != nil {
   440  			ftype = t.Elt
   441  			if variadicOk && i == len(list.List)-1 {
   442  				variadic = true
   443  			} else {
   444  				check.invalidAST(field.Pos(), "... not permitted")
   445  				// ignore ... and continue
   446  			}
   447  		}
   448  		typ := check.typ(ftype)
   449  		// The parser ensures that f.Tag is nil and we don't
   450  		// care if a constructed AST contains a non-nil tag.
   451  		if len(field.Names) > 0 {
   452  			// named parameter
   453  			for _, name := range field.Names {
   454  				if name.Name == "" {
   455  					check.invalidAST(name.Pos(), "anonymous parameter")
   456  					// ok to continue
   457  				}
   458  				par := NewParam(name.Pos(), check.pkg, name.Name, typ)
   459  				check.declare(scope, name, par, scope.pos)
   460  				params = append(params, par)
   461  			}
   462  			named = true
   463  		} else {
   464  			// anonymous parameter
   465  			par := NewParam(ftype.Pos(), check.pkg, "", typ)
   466  			check.recordImplicit(field, par)
   467  			params = append(params, par)
   468  			anonymous = true
   469  		}
   470  	}
   471  
   472  	if named && anonymous {
   473  		check.invalidAST(list.Pos(), "list contains both named and anonymous parameters")
   474  		// ok to continue
   475  	}
   476  
   477  	// For a variadic function, change the last parameter's type from T to []T.
   478  	if variadic && len(params) > 0 {
   479  		last := params[len(params)-1]
   480  		last.typ = &Slice{elem: last.typ}
   481  	}
   482  
   483  	return
   484  }
   485  
   486  func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool {
   487  	if alt := oset.insert(obj); alt != nil {
   488  		check.errorf(pos, "%s redeclared", obj.Name())
   489  		check.reportAltDecl(alt)
   490  		return false
   491  	}
   492  	return true
   493  }
   494  
   495  func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named, path []*TypeName) {
   496  	// fast-track empty interface
   497  	if iface.Methods.List == nil {
   498  		ityp.allMethods = markComplete
   499  		return
   500  	}
   501  
   502  	// collect embedded interfaces
   503  	// Only needed for printing and API. Delay collection
   504  	// to end of type-checking (for package-global interfaces)
   505  	// when all types are complete. Local interfaces are handled
   506  	// after each statement (as each statement processes delayed
   507  	// functions).
   508  	interfaceContext := check.context // capture for use in closure below
   509  	check.later(func() {
   510  		if trace {
   511  			check.trace(iface.Pos(), "-- delayed checking embedded interfaces of %v", iface)
   512  			check.indent++
   513  			defer func() {
   514  				check.indent--
   515  			}()
   516  		}
   517  
   518  		// The context must be restored since for local interfaces
   519  		// delayed functions are processed after each statement
   520  		// (was issue #24140).
   521  		defer func(ctxt context) {
   522  			check.context = ctxt
   523  		}(check.context)
   524  		check.context = interfaceContext
   525  
   526  		for _, f := range iface.Methods.List {
   527  			if len(f.Names) == 0 {
   528  				typ := check.typ(f.Type)
   529  				// typ should be a named type denoting an interface
   530  				// (the parser will make sure it's a named type but
   531  				// constructed ASTs may be wrong).
   532  				if typ == Typ[Invalid] {
   533  					continue // error reported before
   534  				}
   535  				embed, _ := typ.Underlying().(*Interface)
   536  				if embed == nil {
   537  					check.errorf(f.Type.Pos(), "%s is not an interface", typ)
   538  					continue
   539  				}
   540  				// Correct embedded interfaces must be complete -
   541  				// don't just assert, but report error since this
   542  				// used to be the underlying cause for issue #18395.
   543  				if embed.allMethods == nil {
   544  					check.dump("%v: incomplete embedded interface %s", f.Type.Pos(), typ)
   545  					unreachable()
   546  				}
   547  				// collect interface
   548  				ityp.embeddeds = append(ityp.embeddeds, typ)
   549  			}
   550  		}
   551  		// sort to match NewInterface/NewInterface2
   552  		// TODO(gri) we may be able to switch to source order
   553  		sort.Stable(byUniqueTypeName(ityp.embeddeds))
   554  	})
   555  
   556  	// compute method set
   557  	var tname *TypeName
   558  	if def != nil {
   559  		tname = def.obj
   560  	}
   561  	info := check.infoFromTypeLit(check.scope, iface, tname, path)
   562  	if info == nil || info == &emptyIfaceInfo {
   563  		// error or empty interface - exit early
   564  		ityp.allMethods = markComplete
   565  		return
   566  	}
   567  
   568  	// use named receiver type if available (for better error messages)
   569  	var recvTyp Type = ityp
   570  	if def != nil {
   571  		recvTyp = def
   572  	}
   573  
   574  	// Correct receiver type for all methods explicitly declared
   575  	// by this interface after we're done with type-checking at
   576  	// this level. See comment below for details.
   577  	check.later(func() {
   578  		for _, m := range ityp.methods {
   579  			m.typ.(*Signature).recv.typ = recvTyp
   580  		}
   581  	})
   582  
   583  	// collect methods
   584  	var sigfix []*methodInfo
   585  	for i, minfo := range info.methods {
   586  		fun := minfo.fun
   587  		if fun == nil {
   588  			name := minfo.src.Names[0]
   589  			pos := name.Pos()
   590  			// Don't type-check signature yet - use an
   591  			// empty signature now and update it later.
   592  			// But set up receiver since we know it and
   593  			// its position, and because interface method
   594  			// signatures don't get a receiver via regular
   595  			// type-checking (there isn't a receiver in the
   596  			// method's AST). Setting the receiver type is
   597  			// also important for ptrRecv() (see methodset.go).
   598  			//
   599  			// Note: For embedded methods, the receiver type
   600  			// should be the type of the interface that declared
   601  			// the methods in the first place. Since we get the
   602  			// methods here via methodInfo, which may be computed
   603  			// before we have all relevant interface types, we use
   604  			// the current interface's type (recvType). This may be
   605  			// the type of the interface embedding the interface that
   606  			// declared the methods. This doesn't matter for type-
   607  			// checking (we only care about the receiver type for
   608  			// the ptrRecv predicate, and it's never a pointer recv
   609  			// for interfaces), but it matters for go/types clients
   610  			// and for printing. We correct the receiver after type-
   611  			// checking.
   612  			//
   613  			// TODO(gri) Consider marking methods signatures
   614  			// as incomplete, for better error messages. See
   615  			// also the T4 and T5 tests in testdata/cycles2.src.
   616  			sig := new(Signature)
   617  			sig.recv = NewVar(pos, check.pkg, "", recvTyp)
   618  			fun = NewFunc(pos, check.pkg, name.Name, sig)
   619  			minfo.fun = fun
   620  			check.recordDef(name, fun)
   621  			sigfix = append(sigfix, minfo)
   622  		}
   623  		// fun != nil
   624  		if i < info.explicits {
   625  			ityp.methods = append(ityp.methods, fun)
   626  		}
   627  		ityp.allMethods = append(ityp.allMethods, fun)
   628  	}
   629  
   630  	// fix signatures now that we have collected all methods
   631  	savedContext := check.context
   632  	for _, minfo := range sigfix {
   633  		// (possibly embedded) methods must be type-checked within their scope and
   634  		// type-checking them must not affect the current context (was issue #23914)
   635  		check.context = context{scope: minfo.scope}
   636  		typ := check.typ(minfo.src.Type)
   637  		sig, _ := typ.(*Signature)
   638  		if sig == nil {
   639  			if typ != Typ[Invalid] {
   640  				check.invalidAST(minfo.src.Type.Pos(), "%s is not a method signature", typ)
   641  			}
   642  			continue // keep method with empty method signature
   643  		}
   644  		// update signature, but keep recv that was set up before
   645  		old := minfo.fun.typ.(*Signature)
   646  		sig.recv = old.recv
   647  		*old = *sig // update signature (don't replace pointer!)
   648  	}
   649  	check.context = savedContext
   650  
   651  	// sort to match NewInterface/NewInterface2
   652  	// TODO(gri) we may be able to switch to source order
   653  	sort.Sort(byUniqueMethodName(ityp.methods))
   654  
   655  	if ityp.allMethods == nil {
   656  		ityp.allMethods = markComplete
   657  	} else {
   658  		sort.Sort(byUniqueMethodName(ityp.allMethods))
   659  	}
   660  }
   661  
   662  // byUniqueTypeName named type lists can be sorted by their unique type names.
   663  type byUniqueTypeName []Type
   664  
   665  func (a byUniqueTypeName) Len() int           { return len(a) }
   666  func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) }
   667  func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   668  
   669  func sortName(t Type) string {
   670  	if named, _ := t.(*Named); named != nil {
   671  		return named.obj.Id()
   672  	}
   673  	return ""
   674  }
   675  
   676  // byUniqueMethodName method lists can be sorted by their unique method names.
   677  type byUniqueMethodName []*Func
   678  
   679  func (a byUniqueMethodName) Len() int           { return len(a) }
   680  func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() }
   681  func (a byUniqueMethodName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
   682  
   683  func (check *Checker) tag(t *ast.BasicLit) string {
   684  	if t != nil {
   685  		if t.Kind == token.STRING {
   686  			if val, err := strconv.Unquote(t.Value); err == nil {
   687  				return val
   688  			}
   689  		}
   690  		check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value)
   691  	}
   692  	return ""
   693  }
   694  
   695  func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeName) {
   696  	list := e.Fields
   697  	if list == nil {
   698  		return
   699  	}
   700  
   701  	// struct fields and tags
   702  	var fields []*Var
   703  	var tags []string
   704  
   705  	// for double-declaration checks
   706  	var fset objset
   707  
   708  	// current field typ and tag
   709  	var typ Type
   710  	var tag string
   711  	add := func(ident *ast.Ident, embedded bool, pos token.Pos) {
   712  		if tag != "" && tags == nil {
   713  			tags = make([]string, len(fields))
   714  		}
   715  		if tags != nil {
   716  			tags = append(tags, tag)
   717  		}
   718  
   719  		name := ident.Name
   720  		fld := NewField(pos, check.pkg, name, typ, embedded)
   721  		// spec: "Within a struct, non-blank field names must be unique."
   722  		if name == "_" || check.declareInSet(&fset, pos, fld) {
   723  			fields = append(fields, fld)
   724  			check.recordDef(ident, fld)
   725  		}
   726  	}
   727  
   728  	// addInvalid adds an embedded field of invalid type to the struct for
   729  	// fields with errors; this keeps the number of struct fields in sync
   730  	// with the source as long as the fields are _ or have different names
   731  	// (issue #25627).
   732  	addInvalid := func(ident *ast.Ident, pos token.Pos) {
   733  		typ = Typ[Invalid]
   734  		tag = ""
   735  		add(ident, true, pos)
   736  	}
   737  
   738  	for _, f := range list.List {
   739  		typ = check.typExpr(f.Type, nil, path)
   740  		tag = check.tag(f.Tag)
   741  		if len(f.Names) > 0 {
   742  			// named fields
   743  			for _, name := range f.Names {
   744  				add(name, false, name.Pos())
   745  			}
   746  		} else {
   747  			// embedded field
   748  			// spec: "An embedded type must be specified as a type name T or as a pointer
   749  			// to a non-interface type name *T, and T itself may not be a pointer type."
   750  			pos := f.Type.Pos()
   751  			name := embeddedFieldIdent(f.Type)
   752  			if name == nil {
   753  				check.invalidAST(pos, "embedded field type %s has no name", f.Type)
   754  				name = ast.NewIdent("_")
   755  				name.NamePos = pos
   756  				addInvalid(name, pos)
   757  				continue
   758  			}
   759  			t, isPtr := deref(typ)
   760  			// Because we have a name, typ must be of the form T or *T, where T is the name
   761  			// of a (named or alias) type, and t (= deref(typ)) must be the type of T.
   762  			switch t := t.Underlying().(type) {
   763  			case *Basic:
   764  				if t == Typ[Invalid] {
   765  					// error was reported before
   766  					addInvalid(name, pos)
   767  					continue
   768  				}
   769  
   770  				// unsafe.Pointer is treated like a regular pointer
   771  				if t.kind == UnsafePointer {
   772  					check.errorf(pos, "embedded field type cannot be unsafe.Pointer")
   773  					addInvalid(name, pos)
   774  					continue
   775  				}
   776  
   777  			case *Pointer:
   778  				check.errorf(pos, "embedded field type cannot be a pointer")
   779  				addInvalid(name, pos)
   780  				continue
   781  
   782  			case *Interface:
   783  				if isPtr {
   784  					check.errorf(pos, "embedded field type cannot be a pointer to an interface")
   785  					addInvalid(name, pos)
   786  					continue
   787  				}
   788  			}
   789  			add(name, true, pos)
   790  		}
   791  	}
   792  
   793  	styp.fields = fields
   794  	styp.tags = tags
   795  }
   796  
   797  func embeddedFieldIdent(e ast.Expr) *ast.Ident {
   798  	switch e := e.(type) {
   799  	case *ast.Ident:
   800  		return e
   801  	case *ast.StarExpr:
   802  		// *T is valid, but **T is not
   803  		if _, ok := e.X.(*ast.StarExpr); !ok {
   804  			return embeddedFieldIdent(e.X)
   805  		}
   806  	case *ast.SelectorExpr:
   807  		return e.Sel
   808  	}
   809  	return nil // invalid embedded field
   810  }
   811  

View as plain text