diff options
author | Robert Griesemer <gri@golang.org> | 2021-05-20 14:47:40 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2021-05-21 15:26:25 +0000 |
commit | cfe0250497aa2eaa7d3a9a56d815bfa1f4b9b8b5 (patch) | |
tree | 28161ac86e10ceadb8ab664411d8f9a1f1fbabe7 /src/cmd/compile/internal/types2/typexpr.go | |
parent | 211244e1720942af2f2b77b8c96ff7f3a019df31 (diff) | |
download | go-cfe0250497aa2eaa7d3a9a56d815bfa1f4b9b8b5.tar.gz go-cfe0250497aa2eaa7d3a9a56d815bfa1f4b9b8b5.zip |
[dev.typeparams] cmd/compile/internal/types2: move struct checking into separate file
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>
Diffstat (limited to 'src/cmd/compile/internal/types2/typexpr.go')
-rw-r--r-- | src/cmd/compile/internal/types2/typexpr.go | 156 |
1 files changed, 0 insertions, 156 deletions
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index bae4d3e4b5..2352030b9b 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -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 -} |