]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: move struct checking into separate...
authorRobert Griesemer <gri@golang.org>
Thu, 20 May 2021 21:47:40 +0000 (14:47 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 21 May 2021 15:26:25 +0000 (15:26 +0000)
This only moves functionality from one file into another.
Except for import adjustments there are no changes to the
code.

Change-Id: I8dff41fe82693c96b09a152975c3fd1e3b439e8d
Reviewed-on: https://go-review.googlesource.com/c/go/+/321589
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/struct.go [new file with mode: 0644]
src/cmd/compile/internal/types2/typexpr.go

diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go
new file mode 100644 (file)
index 0000000..302b988
--- /dev/null
@@ -0,0 +1,165 @@
+// Copyright 2021 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.
+
+package types2
+
+import (
+       "cmd/compile/internal/syntax"
+       "strconv"
+)
+
+func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
+       if e.FieldList == nil {
+               return
+       }
+
+       // struct fields and tags
+       var fields []*Var
+       var tags []string
+
+       // for double-declaration checks
+       var fset objset
+
+       // current field typ and tag
+       var typ Type
+       var tag string
+       add := func(ident *syntax.Name, embedded bool, pos syntax.Pos) {
+               if tag != "" && tags == nil {
+                       tags = make([]string, len(fields))
+               }
+               if tags != nil {
+                       tags = append(tags, tag)
+               }
+
+               name := ident.Value
+               fld := NewField(pos, check.pkg, name, typ, embedded)
+               // spec: "Within a struct, non-blank field names must be unique."
+               if name == "_" || check.declareInSet(&fset, pos, fld) {
+                       fields = append(fields, fld)
+                       check.recordDef(ident, fld)
+               }
+       }
+
+       // addInvalid adds an embedded field of invalid type to the struct for
+       // fields with errors; this keeps the number of struct fields in sync
+       // with the source as long as the fields are _ or have different names
+       // (issue #25627).
+       addInvalid := func(ident *syntax.Name, pos syntax.Pos) {
+               typ = Typ[Invalid]
+               tag = ""
+               add(ident, true, pos)
+       }
+
+       var prev syntax.Expr
+       for i, f := range e.FieldList {
+               // Fields declared syntactically with the same type (e.g.: a, b, c T)
+               // share the same type expression. Only check type if it's a new type.
+               if i == 0 || f.Type != prev {
+                       typ = check.varType(f.Type)
+                       prev = f.Type
+               }
+               tag = ""
+               if i < len(e.TagList) {
+                       tag = check.tag(e.TagList[i])
+               }
+               if f.Name != nil {
+                       // named field
+                       add(f.Name, false, f.Name.Pos())
+               } else {
+                       // embedded field
+                       // 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 := syntax.StartPos(f.Type)
+                       name := embeddedFieldIdent(f.Type)
+                       if name == nil {
+                               check.errorf(pos, "invalid embedded field type %s", f.Type)
+                               name = &syntax.Name{Value: "_"} // TODO(gri) need to set position to pos
+                               addInvalid(name, pos)
+                               continue
+                       }
+                       add(name, true, pos)
+
+                       // Because we have a name, typ must be of the form T or *T, where T is the name
+                       // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
+                       // We must delay this check to the end because we don't want to instantiate
+                       // (via under(t)) a possibly incomplete type.
+                       embeddedTyp := typ // for closure below
+                       embeddedPos := pos
+                       check.later(func() {
+                               t, isPtr := deref(embeddedTyp)
+                               switch t := optype(t).(type) {
+                               case *Basic:
+                                       if t == Typ[Invalid] {
+                                               // error was reported before
+                                               return
+                                       }
+                                       // unsafe.Pointer is treated like a regular pointer
+                                       if t.kind == UnsafePointer {
+                                               check.error(embeddedPos, "embedded field type cannot be unsafe.Pointer")
+                                       }
+                               case *Pointer:
+                                       check.error(embeddedPos, "embedded field type cannot be a pointer")
+                               case *Interface:
+                                       if isPtr {
+                                               check.error(embeddedPos, "embedded field type cannot be a pointer to an interface")
+                                       }
+                               }
+                       })
+               }
+       }
+
+       styp.fields = fields
+       styp.tags = tags
+}
+
+func embeddedFieldIdent(e syntax.Expr) *syntax.Name {
+       switch e := e.(type) {
+       case *syntax.Name:
+               return e
+       case *syntax.Operation:
+               if base := ptrBase(e); base != nil {
+                       // *T is valid, but **T is not
+                       if op, _ := base.(*syntax.Operation); op == nil || ptrBase(op) == nil {
+                               return embeddedFieldIdent(e.X)
+                       }
+               }
+       case *syntax.SelectorExpr:
+               return e.Sel
+       case *syntax.IndexExpr:
+               return embeddedFieldIdent(e.X)
+       }
+       return nil // invalid embedded field
+}
+
+func (check *Checker) declareInSet(oset *objset, pos syntax.Pos, obj Object) bool {
+       if alt := oset.insert(obj); alt != nil {
+               var err error_
+               err.errorf(pos, "%s redeclared", obj.Name())
+               err.recordAltDecl(alt)
+               check.report(&err)
+               return false
+       }
+       return true
+}
+
+func (check *Checker) tag(t *syntax.BasicLit) string {
+       // If t.Bad, an error was reported during parsing.
+       if t != nil && !t.Bad {
+               if t.Kind == syntax.StringLit {
+                       if val, err := strconv.Unquote(t.Value); err == nil {
+                               return val
+                       }
+               }
+               check.errorf(t, invalidAST+"incorrect tag syntax: %q", t.Value)
+       }
+       return ""
+}
+
+func ptrBase(x *syntax.Operation) syntax.Expr {
+       if x.Op == syntax.Mul && x.Y == nil {
+               return x.X
+       }
+       return nil
+}
index bae4d3e4b53acfcc124b7e55b2a10919ad56fc44..2352030b9b12d955308e10bff84266ce7752562e 100644 (file)
@@ -10,7 +10,6 @@ import (
        "cmd/compile/internal/syntax"
        "fmt"
        "go/constant"
-       "strconv"
        "strings"
 )
 
@@ -800,158 +799,3 @@ func (check *Checker) collectParams(scope *Scope, list []*syntax.Field, type0 sy
 
        return
 }
-
-func (check *Checker) declareInSet(oset *objset, pos syntax.Pos, obj Object) bool {
-       if alt := oset.insert(obj); alt != nil {
-               var err error_
-               err.errorf(pos, "%s redeclared", obj.Name())
-               err.recordAltDecl(alt)
-               check.report(&err)
-               return false
-       }
-       return true
-}
-
-func (check *Checker) tag(t *syntax.BasicLit) string {
-       // If t.Bad, an error was reported during parsing.
-       if t != nil && !t.Bad {
-               if t.Kind == syntax.StringLit {
-                       if val, err := strconv.Unquote(t.Value); err == nil {
-                               return val
-                       }
-               }
-               check.errorf(t, invalidAST+"incorrect tag syntax: %q", t.Value)
-       }
-       return ""
-}
-
-func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
-       if e.FieldList == nil {
-               return
-       }
-
-       // struct fields and tags
-       var fields []*Var
-       var tags []string
-
-       // for double-declaration checks
-       var fset objset
-
-       // current field typ and tag
-       var typ Type
-       var tag string
-       add := func(ident *syntax.Name, embedded bool, pos syntax.Pos) {
-               if tag != "" && tags == nil {
-                       tags = make([]string, len(fields))
-               }
-               if tags != nil {
-                       tags = append(tags, tag)
-               }
-
-               name := ident.Value
-               fld := NewField(pos, check.pkg, name, typ, embedded)
-               // spec: "Within a struct, non-blank field names must be unique."
-               if name == "_" || check.declareInSet(&fset, pos, fld) {
-                       fields = append(fields, fld)
-                       check.recordDef(ident, fld)
-               }
-       }
-
-       // addInvalid adds an embedded field of invalid type to the struct for
-       // fields with errors; this keeps the number of struct fields in sync
-       // with the source as long as the fields are _ or have different names
-       // (issue #25627).
-       addInvalid := func(ident *syntax.Name, pos syntax.Pos) {
-               typ = Typ[Invalid]
-               tag = ""
-               add(ident, true, pos)
-       }
-
-       var prev syntax.Expr
-       for i, f := range e.FieldList {
-               // Fields declared syntactically with the same type (e.g.: a, b, c T)
-               // share the same type expression. Only check type if it's a new type.
-               if i == 0 || f.Type != prev {
-                       typ = check.varType(f.Type)
-                       prev = f.Type
-               }
-               tag = ""
-               if i < len(e.TagList) {
-                       tag = check.tag(e.TagList[i])
-               }
-               if f.Name != nil {
-                       // named field
-                       add(f.Name, false, f.Name.Pos())
-               } else {
-                       // embedded field
-                       // 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 := syntax.StartPos(f.Type)
-                       name := embeddedFieldIdent(f.Type)
-                       if name == nil {
-                               check.errorf(pos, "invalid embedded field type %s", f.Type)
-                               name = &syntax.Name{Value: "_"} // TODO(gri) need to set position to pos
-                               addInvalid(name, pos)
-                               continue
-                       }
-                       add(name, true, pos)
-
-                       // Because we have a name, typ must be of the form T or *T, where T is the name
-                       // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
-                       // We must delay this check to the end because we don't want to instantiate
-                       // (via under(t)) a possibly incomplete type.
-                       embeddedTyp := typ // for closure below
-                       embeddedPos := pos
-                       check.later(func() {
-                               t, isPtr := deref(embeddedTyp)
-                               switch t := optype(t).(type) {
-                               case *Basic:
-                                       if t == Typ[Invalid] {
-                                               // error was reported before
-                                               return
-                                       }
-                                       // unsafe.Pointer is treated like a regular pointer
-                                       if t.kind == UnsafePointer {
-                                               check.error(embeddedPos, "embedded field type cannot be unsafe.Pointer")
-                                       }
-                               case *Pointer:
-                                       check.error(embeddedPos, "embedded field type cannot be a pointer")
-                               case *Interface:
-                                       if isPtr {
-                                               check.error(embeddedPos, "embedded field type cannot be a pointer to an interface")
-                                       }
-                               }
-                       })
-               }
-       }
-
-       styp.fields = fields
-       styp.tags = tags
-}
-
-func embeddedFieldIdent(e syntax.Expr) *syntax.Name {
-       switch e := e.(type) {
-       case *syntax.Name:
-               return e
-       case *syntax.Operation:
-               if base := ptrBase(e); base != nil {
-                       // *T is valid, but **T is not
-                       if op, _ := base.(*syntax.Operation); op == nil || ptrBase(op) == nil {
-                               return embeddedFieldIdent(e.X)
-                       }
-               }
-       case *syntax.SelectorExpr:
-               return e.Sel
-       case *syntax.IndexExpr:
-               return embeddedFieldIdent(e.X)
-       }
-       return nil // invalid embedded field
-}
-
-func ptrBase(x *syntax.Operation) syntax.Expr {
-       if x.Op == syntax.Mul && x.Y == nil {
-               return x.X
-       }
-       return nil
-}