mirror of
https://github.com/golang/go
synced 2024-11-11 23:40:22 -07:00
cmd/compile/internal/types2: review of pos.go and move into syntax package
This moves the two helper functions startPos and endPos into the syntax package where they belong. Export the functions and adjust dependent code. Change-Id: I8170faeadd7cfa8f53009f81fcffd50ec0fc6a98 Reviewed-on: https://go-review.googlesource.com/c/go/+/305578 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
d57189e92b
commit
93466cc1b6
@ -1,16 +1,13 @@
|
||||
// UNREVIEWED
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file implements helper functions for scope position computations.
|
||||
|
||||
package types2
|
||||
package syntax
|
||||
|
||||
import "cmd/compile/internal/syntax"
|
||||
|
||||
// startPos returns the start position of n.
|
||||
func startPos(n syntax.Node) syntax.Pos {
|
||||
// StartPos returns the start position of n.
|
||||
func StartPos(n Node) Pos {
|
||||
// Cases for nodes which don't need a correction are commented out.
|
||||
for m := n; ; {
|
||||
switch n := m.(type) {
|
||||
@ -18,95 +15,95 @@ func startPos(n syntax.Node) syntax.Pos {
|
||||
panic("internal error: nil")
|
||||
|
||||
// packages
|
||||
case *syntax.File:
|
||||
case *File:
|
||||
// file block starts at the beginning of the file
|
||||
return syntax.MakePos(n.Pos().Base(), 1, 1)
|
||||
return MakePos(n.Pos().Base(), 1, 1)
|
||||
|
||||
// declarations
|
||||
// case *syntax.ImportDecl:
|
||||
// case *syntax.ConstDecl:
|
||||
// case *syntax.TypeDecl:
|
||||
// case *syntax.VarDecl:
|
||||
// case *syntax.FuncDecl:
|
||||
// case *ImportDecl:
|
||||
// case *ConstDecl:
|
||||
// case *TypeDecl:
|
||||
// case *VarDecl:
|
||||
// case *FuncDecl:
|
||||
|
||||
// expressions
|
||||
// case *syntax.BadExpr:
|
||||
// case *syntax.Name:
|
||||
// case *syntax.BasicLit:
|
||||
case *syntax.CompositeLit:
|
||||
// case *BadExpr:
|
||||
// case *Name:
|
||||
// case *BasicLit:
|
||||
case *CompositeLit:
|
||||
if n.Type != nil {
|
||||
m = n.Type
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
// case *syntax.KeyValueExpr:
|
||||
// case *syntax.FuncLit:
|
||||
// case *syntax.ParenExpr:
|
||||
case *syntax.SelectorExpr:
|
||||
// case *KeyValueExpr:
|
||||
// case *FuncLit:
|
||||
// case *ParenExpr:
|
||||
case *SelectorExpr:
|
||||
m = n.X
|
||||
case *syntax.IndexExpr:
|
||||
case *IndexExpr:
|
||||
m = n.X
|
||||
// case *syntax.SliceExpr:
|
||||
case *syntax.AssertExpr:
|
||||
// case *SliceExpr:
|
||||
case *AssertExpr:
|
||||
m = n.X
|
||||
case *syntax.TypeSwitchGuard:
|
||||
case *TypeSwitchGuard:
|
||||
if n.Lhs != nil {
|
||||
m = n.Lhs
|
||||
continue
|
||||
}
|
||||
m = n.X
|
||||
case *syntax.Operation:
|
||||
case *Operation:
|
||||
if n.Y != nil {
|
||||
m = n.X
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.CallExpr:
|
||||
case *CallExpr:
|
||||
m = n.Fun
|
||||
case *syntax.ListExpr:
|
||||
case *ListExpr:
|
||||
if len(n.ElemList) > 0 {
|
||||
m = n.ElemList[0]
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
// types
|
||||
// case *syntax.ArrayType:
|
||||
// case *syntax.SliceType:
|
||||
// case *syntax.DotsType:
|
||||
// case *syntax.StructType:
|
||||
// case *syntax.Field:
|
||||
// case *syntax.InterfaceType:
|
||||
// case *syntax.FuncType:
|
||||
// case *syntax.MapType:
|
||||
// case *syntax.ChanType:
|
||||
// case *ArrayType:
|
||||
// case *SliceType:
|
||||
// case *DotsType:
|
||||
// case *StructType:
|
||||
// case *Field:
|
||||
// case *InterfaceType:
|
||||
// case *FuncType:
|
||||
// case *MapType:
|
||||
// case *ChanType:
|
||||
|
||||
// statements
|
||||
// case *syntax.EmptyStmt:
|
||||
// case *syntax.LabeledStmt:
|
||||
// case *syntax.BlockStmt:
|
||||
// case *syntax.ExprStmt:
|
||||
case *syntax.SendStmt:
|
||||
// case *EmptyStmt:
|
||||
// case *LabeledStmt:
|
||||
// case *BlockStmt:
|
||||
// case *ExprStmt:
|
||||
case *SendStmt:
|
||||
m = n.Chan
|
||||
// case *syntax.DeclStmt:
|
||||
case *syntax.AssignStmt:
|
||||
// case *DeclStmt:
|
||||
case *AssignStmt:
|
||||
m = n.Lhs
|
||||
// case *syntax.BranchStmt:
|
||||
// case *syntax.CallStmt:
|
||||
// case *syntax.ReturnStmt:
|
||||
// case *syntax.IfStmt:
|
||||
// case *syntax.ForStmt:
|
||||
// case *syntax.SwitchStmt:
|
||||
// case *syntax.SelectStmt:
|
||||
// case *BranchStmt:
|
||||
// case *CallStmt:
|
||||
// case *ReturnStmt:
|
||||
// case *IfStmt:
|
||||
// case *ForStmt:
|
||||
// case *SwitchStmt:
|
||||
// case *SelectStmt:
|
||||
|
||||
// helper nodes
|
||||
case *syntax.RangeClause:
|
||||
case *RangeClause:
|
||||
if n.Lhs != nil {
|
||||
m = n.Lhs
|
||||
continue
|
||||
}
|
||||
m = n.X
|
||||
// case *syntax.CaseClause:
|
||||
// case *syntax.CommClause:
|
||||
// case *CaseClause:
|
||||
// case *CommClause:
|
||||
|
||||
default:
|
||||
return n.Pos()
|
||||
@ -114,30 +111,29 @@ func startPos(n syntax.Node) syntax.Pos {
|
||||
}
|
||||
}
|
||||
|
||||
// endPos returns the approximate end position of n in the source.
|
||||
// For some nodes (*syntax.Name, *syntax.BasicLit) it returns
|
||||
// the position immediately following the node; for others
|
||||
// (*syntax.BlockStmt, *syntax.SwitchStmt, etc.) it returns
|
||||
// the position of the closing '}'; and for some (*syntax.ParenExpr)
|
||||
// EndPos returns the approximate end position of n in the source.
|
||||
// For some nodes (*Name, *BasicLit) it returns the position immediately
|
||||
// following the node; for others (*BlockStmt, *SwitchStmt, etc.) it
|
||||
// returns the position of the closing '}'; and for some (*ParenExpr)
|
||||
// the returned position is the end position of the last enclosed
|
||||
// expression.
|
||||
// Thus, endPos should not be used for exact demarcation of the
|
||||
// Thus, EndPos should not be used for exact demarcation of the
|
||||
// end of a node in the source; it is mostly useful to determine
|
||||
// scope ranges where there is some leeway.
|
||||
func endPos(n syntax.Node) syntax.Pos {
|
||||
func EndPos(n Node) Pos {
|
||||
for m := n; ; {
|
||||
switch n := m.(type) {
|
||||
case nil:
|
||||
panic("internal error: nil")
|
||||
|
||||
// packages
|
||||
case *syntax.File:
|
||||
case *File:
|
||||
return n.EOF
|
||||
|
||||
// declarations
|
||||
case *syntax.ImportDecl:
|
||||
case *ImportDecl:
|
||||
m = n.Path
|
||||
case *syntax.ConstDecl:
|
||||
case *ConstDecl:
|
||||
if n.Values != nil {
|
||||
m = n.Values
|
||||
continue
|
||||
@ -151,9 +147,9 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.TypeDecl:
|
||||
case *TypeDecl:
|
||||
m = n.Type
|
||||
case *syntax.VarDecl:
|
||||
case *VarDecl:
|
||||
if n.Values != nil {
|
||||
m = n.Values
|
||||
continue
|
||||
@ -167,7 +163,7 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.FuncDecl:
|
||||
case *FuncDecl:
|
||||
if n.Body != nil {
|
||||
m = n.Body
|
||||
continue
|
||||
@ -175,27 +171,27 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
m = n.Type
|
||||
|
||||
// expressions
|
||||
case *syntax.BadExpr:
|
||||
case *BadExpr:
|
||||
return n.Pos()
|
||||
case *syntax.Name:
|
||||
case *Name:
|
||||
p := n.Pos()
|
||||
return syntax.MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value)))
|
||||
case *syntax.BasicLit:
|
||||
return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value)))
|
||||
case *BasicLit:
|
||||
p := n.Pos()
|
||||
return syntax.MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value)))
|
||||
case *syntax.CompositeLit:
|
||||
return MakePos(p.Base(), p.Line(), p.Col()+uint(len(n.Value)))
|
||||
case *CompositeLit:
|
||||
return n.Rbrace
|
||||
case *syntax.KeyValueExpr:
|
||||
case *KeyValueExpr:
|
||||
m = n.Value
|
||||
case *syntax.FuncLit:
|
||||
case *FuncLit:
|
||||
m = n.Body
|
||||
case *syntax.ParenExpr:
|
||||
case *ParenExpr:
|
||||
m = n.X
|
||||
case *syntax.SelectorExpr:
|
||||
case *SelectorExpr:
|
||||
m = n.Sel
|
||||
case *syntax.IndexExpr:
|
||||
case *IndexExpr:
|
||||
m = n.Index
|
||||
case *syntax.SliceExpr:
|
||||
case *SliceExpr:
|
||||
for i := len(n.Index) - 1; i >= 0; i-- {
|
||||
if x := n.Index[i]; x != nil {
|
||||
m = x
|
||||
@ -203,23 +199,23 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
}
|
||||
}
|
||||
m = n.X
|
||||
case *syntax.AssertExpr:
|
||||
case *AssertExpr:
|
||||
m = n.Type
|
||||
case *syntax.TypeSwitchGuard:
|
||||
case *TypeSwitchGuard:
|
||||
m = n.X
|
||||
case *syntax.Operation:
|
||||
case *Operation:
|
||||
if n.Y != nil {
|
||||
m = n.Y
|
||||
continue
|
||||
}
|
||||
m = n.X
|
||||
case *syntax.CallExpr:
|
||||
case *CallExpr:
|
||||
if l := lastExpr(n.ArgList); l != nil {
|
||||
m = l
|
||||
continue
|
||||
}
|
||||
m = n.Fun
|
||||
case *syntax.ListExpr:
|
||||
case *ListExpr:
|
||||
if l := lastExpr(n.ElemList); l != nil {
|
||||
m = l
|
||||
continue
|
||||
@ -227,32 +223,32 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
return n.Pos()
|
||||
|
||||
// types
|
||||
case *syntax.ArrayType:
|
||||
case *ArrayType:
|
||||
m = n.Elem
|
||||
case *syntax.SliceType:
|
||||
case *SliceType:
|
||||
m = n.Elem
|
||||
case *syntax.DotsType:
|
||||
case *DotsType:
|
||||
m = n.Elem
|
||||
case *syntax.StructType:
|
||||
case *StructType:
|
||||
if l := lastField(n.FieldList); l != nil {
|
||||
m = l
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
// TODO(gri) need to take TagList into account
|
||||
case *syntax.Field:
|
||||
case *Field:
|
||||
if n.Type != nil {
|
||||
m = n.Type
|
||||
continue
|
||||
}
|
||||
m = n.Name
|
||||
case *syntax.InterfaceType:
|
||||
case *InterfaceType:
|
||||
if l := lastField(n.MethodList); l != nil {
|
||||
m = l
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.FuncType:
|
||||
case *FuncType:
|
||||
if l := lastField(n.ResultList); l != nil {
|
||||
m = l
|
||||
continue
|
||||
@ -262,71 +258,71 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.MapType:
|
||||
case *MapType:
|
||||
m = n.Value
|
||||
case *syntax.ChanType:
|
||||
case *ChanType:
|
||||
m = n.Elem
|
||||
|
||||
// statements
|
||||
case *syntax.EmptyStmt:
|
||||
case *EmptyStmt:
|
||||
return n.Pos()
|
||||
case *syntax.LabeledStmt:
|
||||
case *LabeledStmt:
|
||||
m = n.Stmt
|
||||
case *syntax.BlockStmt:
|
||||
case *BlockStmt:
|
||||
return n.Rbrace
|
||||
case *syntax.ExprStmt:
|
||||
case *ExprStmt:
|
||||
m = n.X
|
||||
case *syntax.SendStmt:
|
||||
case *SendStmt:
|
||||
m = n.Value
|
||||
case *syntax.DeclStmt:
|
||||
case *DeclStmt:
|
||||
if l := lastDecl(n.DeclList); l != nil {
|
||||
m = l
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.AssignStmt:
|
||||
case *AssignStmt:
|
||||
m = n.Rhs
|
||||
if m == nil {
|
||||
p := endPos(n.Lhs)
|
||||
return syntax.MakePos(p.Base(), p.Line(), p.Col()+2)
|
||||
p := EndPos(n.Lhs)
|
||||
return MakePos(p.Base(), p.Line(), p.Col()+2)
|
||||
}
|
||||
case *syntax.BranchStmt:
|
||||
case *BranchStmt:
|
||||
if n.Label != nil {
|
||||
m = n.Label
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.CallStmt:
|
||||
case *CallStmt:
|
||||
m = n.Call
|
||||
case *syntax.ReturnStmt:
|
||||
case *ReturnStmt:
|
||||
if n.Results != nil {
|
||||
m = n.Results
|
||||
continue
|
||||
}
|
||||
return n.Pos()
|
||||
case *syntax.IfStmt:
|
||||
case *IfStmt:
|
||||
if n.Else != nil {
|
||||
m = n.Else
|
||||
continue
|
||||
}
|
||||
m = n.Then
|
||||
case *syntax.ForStmt:
|
||||
case *ForStmt:
|
||||
m = n.Body
|
||||
case *syntax.SwitchStmt:
|
||||
case *SwitchStmt:
|
||||
return n.Rbrace
|
||||
case *syntax.SelectStmt:
|
||||
case *SelectStmt:
|
||||
return n.Rbrace
|
||||
|
||||
// helper nodes
|
||||
case *syntax.RangeClause:
|
||||
case *RangeClause:
|
||||
m = n.X
|
||||
case *syntax.CaseClause:
|
||||
case *CaseClause:
|
||||
if l := lastStmt(n.Body); l != nil {
|
||||
m = l
|
||||
continue
|
||||
}
|
||||
return n.Colon
|
||||
case *syntax.CommClause:
|
||||
case *CommClause:
|
||||
if l := lastStmt(n.Body); l != nil {
|
||||
m = l
|
||||
continue
|
||||
@ -339,28 +335,28 @@ func endPos(n syntax.Node) syntax.Pos {
|
||||
}
|
||||
}
|
||||
|
||||
func lastDecl(list []syntax.Decl) syntax.Decl {
|
||||
func lastDecl(list []Decl) Decl {
|
||||
if l := len(list); l > 0 {
|
||||
return list[l-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lastExpr(list []syntax.Expr) syntax.Expr {
|
||||
func lastExpr(list []Expr) Expr {
|
||||
if l := len(list); l > 0 {
|
||||
return list[l-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lastStmt(list []syntax.Stmt) syntax.Stmt {
|
||||
func lastStmt(list []Stmt) Stmt {
|
||||
if l := len(list); l > 0 {
|
||||
return list[l-1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func lastField(list []*syntax.Field) *syntax.Field {
|
||||
func lastField(list []*Field) *Field {
|
||||
if l := len(list); l > 0 {
|
||||
return list[l-1]
|
||||
}
|
@ -377,7 +377,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
||||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
// for short variable declarations) and ends at the end of the innermost
|
||||
// containing block."
|
||||
scopePos := endPos(rhs[len(rhs)-1])
|
||||
scopePos := syntax.EndPos(rhs[len(rhs)-1])
|
||||
for _, obj := range newVars {
|
||||
check.declare(scope, nil, obj, scopePos) // recordObject already called
|
||||
}
|
||||
|
@ -901,7 +901,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
|
||||
// inside a function begins at the end of the ConstSpec or VarSpec
|
||||
// (ShortVarDecl for short variable declarations) and ends at the
|
||||
// end of the innermost containing block."
|
||||
scopePos := endPos(s)
|
||||
scopePos := syntax.EndPos(s)
|
||||
for i, name := range s.NameList {
|
||||
check.declare(check.scope, name, lhs[i], scopePos)
|
||||
}
|
||||
@ -958,7 +958,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
|
||||
|
||||
// declare all variables
|
||||
// (only at this point are the variable scopes (parents) set)
|
||||
scopePos := endPos(s) // see constant declarations
|
||||
scopePos := syntax.EndPos(s) // see constant declarations
|
||||
for i, name := range s.NameList {
|
||||
// see constant declarations
|
||||
check.declare(check.scope, name, lhs0[i], scopePos)
|
||||
|
@ -207,10 +207,10 @@ func posFor(at poser) syntax.Pos {
|
||||
switch x := at.(type) {
|
||||
case *operand:
|
||||
if x.expr != nil {
|
||||
return startPos(x.expr)
|
||||
return syntax.StartPos(x.expr)
|
||||
}
|
||||
case syntax.Node:
|
||||
return startPos(x)
|
||||
return syntax.StartPos(x)
|
||||
}
|
||||
return at.Pos()
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func (check *Checker) overflow(x *operand) {
|
||||
// If the corresponding expression is an operation, use the
|
||||
// operator position rather than the start of the expression
|
||||
// as error position.
|
||||
pos := startPos(x.expr)
|
||||
pos := syntax.StartPos(x.expr)
|
||||
what := "" // operator description, if any
|
||||
if op, _ := x.expr.(*syntax.Operation); op != nil {
|
||||
pos = op.Pos()
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
// labels checks correct label use in body.
|
||||
func (check *Checker) labels(body *syntax.BlockStmt) {
|
||||
// set of all labels in this body
|
||||
all := NewScope(nil, body.Pos(), endPos(body), "label")
|
||||
all := NewScope(nil, body.Pos(), syntax.EndPos(body), "label")
|
||||
|
||||
fwdJumps := check.blockBranches(all, nil, nil, body.List)
|
||||
|
||||
|
@ -216,7 +216,7 @@ func (check *Checker) collectObjects() {
|
||||
// but there is no corresponding package object.
|
||||
check.recordDef(file.PkgName, nil)
|
||||
|
||||
fileScope := NewScope(check.pkg.scope, startPos(file), endPos(file), check.filename(fileNo))
|
||||
fileScope := NewScope(check.pkg.scope, syntax.StartPos(file), syntax.EndPos(file), check.filename(fileNo))
|
||||
fileScopes = append(fileScopes, fileScope)
|
||||
check.recordScope(file, fileScope)
|
||||
|
||||
|
@ -16,13 +16,13 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
|
||||
if check.conf.Trace {
|
||||
check.trace(body.Pos(), "--- %s: %s", name, sig)
|
||||
defer func() {
|
||||
check.trace(endPos(body), "--- <end>")
|
||||
check.trace(syntax.EndPos(body), "--- <end>")
|
||||
}()
|
||||
}
|
||||
|
||||
// set function scope extent
|
||||
sig.scope.pos = body.Pos()
|
||||
sig.scope.end = endPos(body)
|
||||
sig.scope.end = syntax.EndPos(body)
|
||||
|
||||
// save/restore current context and setup function context
|
||||
// (and use 0 indentation at function start)
|
||||
@ -154,7 +154,7 @@ func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
|
||||
}
|
||||
|
||||
func (check *Checker) openScope(node syntax.Node, comment string) {
|
||||
check.openScopeUntil(node, endPos(node), comment)
|
||||
check.openScopeUntil(node, syntax.EndPos(node), comment)
|
||||
}
|
||||
|
||||
func (check *Checker) openScopeUntil(node syntax.Node, end syntax.Pos, comment string) {
|
||||
@ -723,7 +723,7 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
|
||||
// "at the end of the TypeSwitchCase" in #16794 instead?
|
||||
scopePos := clause.Pos() // for default clause (len(List) == 0)
|
||||
if n := len(cases); n > 0 {
|
||||
scopePos = endPos(cases[n-1])
|
||||
scopePos = syntax.EndPos(cases[n-1])
|
||||
}
|
||||
check.declare(check.scope, nil, obj, scopePos)
|
||||
check.recordImplicit(clause, obj)
|
||||
@ -840,7 +840,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
|
||||
|
||||
// declare variables
|
||||
if len(vars) > 0 {
|
||||
scopePos := endPos(rclause.X) // TODO(gri) should this just be s.Body.Pos (spec clarification)?
|
||||
scopePos := syntax.EndPos(rclause.X) // TODO(gri) should this just be s.Body.Pos (spec clarification)?
|
||||
for _, obj := range vars {
|
||||
// spec: "The scope of a constant or variable identifier declared inside
|
||||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
|
@ -131,7 +131,7 @@ func (check *Checker) typ(e syntax.Expr) Type {
|
||||
// (see ordinaryType).
|
||||
func (check *Checker) varType(e syntax.Expr) Type {
|
||||
typ := check.definedType(e, nil)
|
||||
check.ordinaryType(startPos(e), typ)
|
||||
check.ordinaryType(syntax.StartPos(e), typ)
|
||||
return typ
|
||||
}
|
||||
|
||||
@ -1154,7 +1154,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
|
||||
// spec: "An embedded type must be specified as a type name T or as a
|
||||
// pointer to a non-interface type name *T, and T itself may not be a
|
||||
// pointer type."
|
||||
pos := startPos(f.Type)
|
||||
pos := syntax.StartPos(f.Type)
|
||||
name := embeddedFieldIdent(f.Type)
|
||||
if name == nil {
|
||||
check.errorf(pos, "invalid embedded field type %s", f.Type)
|
||||
|
Loading…
Reference in New Issue
Block a user