]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/go/types/typexpr.go
[dev.typeparams] all: merge master (37f9a8f) into dev.typeparams
[gostls13.git] / src / go / types / typexpr.go
index 1738d864a6573965f9bf5cf626b9b9a48fdb60ec..e6be7b72e462d698774b5e29134f23ca87e946a6 100644 (file)
@@ -12,8 +12,6 @@ import (
        "go/constant"
        "go/internal/typeparams"
        "go/token"
-       "sort"
-       "strconv"
        "strings"
 )
 
@@ -194,205 +192,6 @@ func (check *Checker) genericType(e ast.Expr, reportErr bool) Type {
        return typ
 }
 
-// isubst returns an x with identifiers substituted per the substitution map smap.
-// isubst only handles the case of (valid) method receiver type expressions correctly.
-func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr {
-       switch n := x.(type) {
-       case *ast.Ident:
-               if alt := smap[n]; alt != nil {
-                       return alt
-               }
-       case *ast.StarExpr:
-               X := isubst(n.X, smap)
-               if X != n.X {
-                       new := *n
-                       new.X = X
-                       return &new
-               }
-       case *ast.IndexExpr:
-               elems := typeparams.UnpackExpr(n.Index)
-               var newElems []ast.Expr
-               for i, elem := range elems {
-                       new := isubst(elem, smap)
-                       if new != elem {
-                               if newElems == nil {
-                                       newElems = make([]ast.Expr, len(elems))
-                                       copy(newElems, elems)
-                               }
-                               newElems[i] = new
-                       }
-               }
-               if newElems != nil {
-                       index := typeparams.PackExpr(newElems)
-                       new := *n
-                       new.Index = index
-                       return &new
-               }
-       case *ast.ParenExpr:
-               return isubst(n.X, smap) // no need to keep parentheses
-       default:
-               // Other receiver type expressions are invalid.
-               // It's fine to ignore those here as they will
-               // be checked elsewhere.
-       }
-       return x
-}
-
-// funcType type-checks a function or method type.
-func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast.FuncType) {
-       check.openScope(ftyp, "function")
-       check.scope.isFunc = true
-       check.recordScope(ftyp, check.scope)
-       sig.scope = check.scope
-       defer check.closeScope()
-
-       var recvTyp ast.Expr // rewritten receiver type; valid if != nil
-       if recvPar != nil && len(recvPar.List) > 0 {
-               // collect generic receiver type parameters, if any
-               // - a receiver type parameter is like any other type parameter, except that it is declared implicitly
-               // - the receiver specification acts as local declaration for its type parameters, which may be blank
-               _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
-               if len(rparams) > 0 {
-                       // Blank identifiers don't get declared and regular type-checking of the instantiated
-                       // parameterized receiver type expression fails in Checker.collectParams of receiver.
-                       // Identify blank type parameters and substitute each with a unique new identifier named
-                       // "n_" (where n is the parameter index) and which cannot conflict with any user-defined
-                       // name.
-                       var smap map[*ast.Ident]*ast.Ident // substitution map from "_" to "n_" identifiers
-                       for i, p := range rparams {
-                               if p.Name == "_" {
-                                       new := *p
-                                       new.Name = fmt.Sprintf("%d_", i)
-                                       rparams[i] = &new // use n_ identifier instead of _ so it can be looked up
-                                       if smap == nil {
-                                               smap = make(map[*ast.Ident]*ast.Ident)
-                                       }
-                                       smap[p] = &new
-                               }
-                       }
-                       if smap != nil {
-                               // blank identifiers were found => use rewritten receiver type
-                               recvTyp = isubst(recvPar.List[0].Type, smap)
-                       }
-                       sig.rparams = check.declareTypeParams(nil, rparams)
-                       // determine receiver type to get its type parameters
-                       // and the respective type parameter bounds
-                       var recvTParams []*TypeName
-                       if rname != nil {
-                               // recv should be a Named type (otherwise an error is reported elsewhere)
-                               // Also: Don't report an error via genericType since it will be reported
-                               //       again when we type-check the signature.
-                               // TODO(gri) maybe the receiver should be marked as invalid instead?
-                               if recv := asNamed(check.genericType(rname, false)); recv != nil {
-                                       recvTParams = recv.tparams
-                               }
-                       }
-                       // provide type parameter bounds
-                       // - only do this if we have the right number (otherwise an error is reported elsewhere)
-                       if len(sig.rparams) == len(recvTParams) {
-                               // We have a list of *TypeNames but we need a list of Types.
-                               list := make([]Type, len(sig.rparams))
-                               for i, t := range sig.rparams {
-                                       list[i] = t.typ
-                               }
-                               smap := makeSubstMap(recvTParams, list)
-                               for i, tname := range sig.rparams {
-                                       bound := recvTParams[i].typ.(*_TypeParam).bound
-                                       // bound is (possibly) parameterized in the context of the
-                                       // receiver type declaration. Substitute parameters for the
-                                       // current context.
-                                       // TODO(gri) should we assume now that bounds always exist?
-                                       //           (no bound == empty interface)
-                                       if bound != nil {
-                                               bound = check.subst(tname.pos, bound, smap)
-                                               tname.typ.(*_TypeParam).bound = bound
-                                       }
-                               }
-                       }
-               }
-       }
-
-       if tparams := typeparams.Get(ftyp); tparams != nil {
-               sig.tparams = check.collectTypeParams(tparams)
-               // Always type-check method type parameters but complain that they are not allowed.
-               // (A separate check is needed when type-checking interface method signatures because
-               // they don't have a receiver specification.)
-               if recvPar != nil {
-                       check.errorf(tparams, _Todo, "methods cannot have type parameters")
-               }
-       }
-
-       // Value (non-type) parameters' scope starts in the function body. Use a temporary scope for their
-       // declarations and then squash that scope into the parent scope (and report any redeclarations at
-       // that time).
-       scope := NewScope(check.scope, token.NoPos, token.NoPos, "function body (temp. scope)")
-       recvList, _ := check.collectParams(scope, recvPar, recvTyp, false) // use rewritten receiver type, if any
-       params, variadic := check.collectParams(scope, ftyp.Params, nil, true)
-       results, _ := check.collectParams(scope, ftyp.Results, nil, false)
-       scope.squash(func(obj, alt Object) {
-               check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name())
-               check.reportAltDecl(alt)
-       })
-
-       if recvPar != nil {
-               // recv parameter list present (may be empty)
-               // spec: "The receiver is specified via an extra parameter section preceding the
-               // method name. That parameter section must declare a single parameter, the receiver."
-               var recv *Var
-               switch len(recvList) {
-               case 0:
-                       // error reported by resolver
-                       recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
-               default:
-                       // more than one receiver
-                       check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver")
-                       fallthrough // continue with first receiver
-               case 1:
-                       recv = recvList[0]
-               }
-
-               // TODO(gri) We should delay rtyp expansion to when we actually need the
-               //           receiver; thus all checks here should be delayed to later.
-               rtyp, _ := deref(recv.typ)
-               rtyp = expand(rtyp)
-
-               // spec: "The receiver type must be of the form T or *T where T is a type name."
-               // (ignore invalid types - error was reported before)
-               if t := rtyp; t != Typ[Invalid] {
-                       var err string
-                       if T := asNamed(t); T != nil {
-                               // spec: "The type denoted by T is called the receiver base type; it must not
-                               // be a pointer or interface type and it must be declared in the same package
-                               // as the method."
-                               if T.obj.pkg != check.pkg {
-                                       err = "type not defined in this package"
-                               } else {
-                                       switch u := optype(T).(type) {
-                                       case *Basic:
-                                               // unsafe.Pointer is treated like a regular pointer
-                                               if u.kind == UnsafePointer {
-                                                       err = "unsafe.Pointer"
-                                               }
-                                       case *Pointer, *Interface:
-                                               err = "pointer or interface type"
-                                       }
-                               }
-                       } else {
-                               err = "basic or unnamed type"
-                       }
-                       if err != "" {
-                               check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err)
-                               // ok to continue
-                       }
-               }
-               sig.recv = recv
-       }
-
-       sig.params = NewTuple(params...)
-       sig.results = NewTuple(results...)
-       sig.variadic = variadic
-}
-
 // goTypeName returns the Go type name for typ and
 // removes any occurrences of "types." from that name.
 func goTypeName(typ Type) string {
@@ -689,518 +488,3 @@ func (check *Checker) typeList(list []ast.Expr) []Type {
        }
        return res
 }
-
-// collectParams declares the parameters of list in scope and returns the corresponding
-// variable list. If type0 != nil, it is used instead of the first type in list.
-func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, type0 ast.Expr, variadicOk bool) (params []*Var, variadic bool) {
-       if list == nil {
-               return
-       }
-
-       var named, anonymous bool
-       for i, field := range list.List {
-               ftype := field.Type
-               if i == 0 && type0 != nil {
-                       ftype = type0
-               }
-               if t, _ := ftype.(*ast.Ellipsis); t != nil {
-                       ftype = t.Elt
-                       if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 {
-                               variadic = true
-                       } else {
-                               check.softErrorf(t, _MisplacedDotDotDot, "can only use ... with final parameter in list")
-                               // ignore ... and continue
-                       }
-               }
-               typ := check.varType(ftype)
-               // The parser ensures that f.Tag is nil and we don't
-               // care if a constructed AST contains a non-nil tag.
-               if len(field.Names) > 0 {
-                       // named parameter
-                       for _, name := range field.Names {
-                               if name.Name == "" {
-                                       check.invalidAST(name, "anonymous parameter")
-                                       // ok to continue
-                               }
-                               par := NewParam(name.Pos(), check.pkg, name.Name, typ)
-                               check.declare(scope, name, par, scope.pos)
-                               params = append(params, par)
-                       }
-                       named = true
-               } else {
-                       // anonymous parameter
-                       par := NewParam(ftype.Pos(), check.pkg, "", typ)
-                       check.recordImplicit(field, par)
-                       params = append(params, par)
-                       anonymous = true
-               }
-       }
-
-       if named && anonymous {
-               check.invalidAST(list, "list contains both named and anonymous parameters")
-               // ok to continue
-       }
-
-       // For a variadic function, change the last parameter's type from T to []T.
-       // Since we type-checked T rather than ...T, we also need to retro-actively
-       // record the type for ...T.
-       if variadic {
-               last := params[len(params)-1]
-               last.typ = &Slice{elem: last.typ}
-               check.recordTypeAndValue(list.List[len(list.List)-1].Type, typexpr, last.typ, nil)
-       }
-
-       return
-}
-
-func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool {
-       if alt := oset.insert(obj); alt != nil {
-               check.errorf(atPos(pos), _DuplicateDecl, "%s redeclared", obj.Name())
-               check.reportAltDecl(alt)
-               return false
-       }
-       return true
-}
-
-func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
-       var tlist *ast.Ident // "type" name of first entry in a type list declaration
-       var types []ast.Expr
-       for _, f := range iface.Methods.List {
-               if len(f.Names) > 0 {
-                       // We have a method with name f.Names[0], or a type
-                       // of a type list (name.Name == "type").
-                       // (The parser ensures that there's only one method
-                       // and we don't care if a constructed AST has more.)
-                       name := f.Names[0]
-                       if name.Name == "_" {
-                               check.errorf(name, _BlankIfaceMethod, "invalid method name _")
-                               continue // ignore
-                       }
-
-                       if name.Name == "type" {
-                               // Always collect all type list entries, even from
-                               // different type lists, under the assumption that
-                               // the author intended to include all types.
-                               types = append(types, f.Type)
-                               if tlist != nil && tlist != name {
-                                       check.errorf(name, _Todo, "cannot have multiple type lists in an interface")
-                               }
-                               tlist = name
-                               continue
-                       }
-
-                       typ := check.typ(f.Type)
-                       sig, _ := typ.(*Signature)
-                       if sig == nil {
-                               if typ != Typ[Invalid] {
-                                       check.invalidAST(f.Type, "%s is not a method signature", typ)
-                               }
-                               continue // ignore
-                       }
-
-                       // Always type-check method type parameters but complain if they are not enabled.
-                       // (This extra check is needed here because interface method signatures don't have
-                       // a receiver specification.)
-                       if sig.tparams != nil {
-                               var at positioner = f.Type
-                               if tparams := typeparams.Get(f.Type); tparams != nil {
-                                       at = tparams
-                               }
-                               check.errorf(at, _Todo, "methods cannot have type parameters")
-                       }
-
-                       // use named receiver type if available (for better error messages)
-                       var recvTyp Type = ityp
-                       if def != nil {
-                               recvTyp = def
-                       }
-                       sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp)
-
-                       m := NewFunc(name.Pos(), check.pkg, name.Name, sig)
-                       check.recordDef(name, m)
-                       ityp.methods = append(ityp.methods, m)
-               } else {
-                       // We have an embedded type. completeInterface will
-                       // eventually verify that we have an interface.
-                       ityp.embeddeds = append(ityp.embeddeds, check.typ(f.Type))
-                       check.posMap[ityp] = append(check.posMap[ityp], f.Type.Pos())
-               }
-       }
-
-       // type constraints
-       ityp.types = _NewSum(check.collectTypeConstraints(iface.Pos(), types))
-
-       if len(ityp.methods) == 0 && ityp.types == nil && len(ityp.embeddeds) == 0 {
-               // empty interface
-               ityp.allMethods = markComplete
-               return
-       }
-
-       // sort for API stability
-       sortMethods(ityp.methods)
-       sortTypes(ityp.embeddeds)
-
-       check.later(func() { check.completeInterface(iface.Pos(), ityp) })
-}
-
-func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) {
-       if ityp.allMethods != nil {
-               return
-       }
-
-       // completeInterface may be called via the LookupFieldOrMethod,
-       // MissingMethod, Identical, or IdenticalIgnoreTags external API
-       // in which case check will be nil. In this case, type-checking
-       // must be finished and all interfaces should have been completed.
-       if check == nil {
-               panic("internal error: incomplete interface")
-       }
-
-       if trace {
-               // Types don't generally have position information.
-               // If we don't have a valid pos provided, try to use
-               // one close enough.
-               if !pos.IsValid() && len(ityp.methods) > 0 {
-                       pos = ityp.methods[0].pos
-               }
-
-               check.trace(pos, "complete %s", ityp)
-               check.indent++
-               defer func() {
-                       check.indent--
-                       check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes)
-               }()
-       }
-
-       // An infinitely expanding interface (due to a cycle) is detected
-       // elsewhere (Checker.validType), so here we simply assume we only
-       // have valid interfaces. Mark the interface as complete to avoid
-       // infinite recursion if the validType check occurs later for some
-       // reason.
-       ityp.allMethods = markComplete
-
-       // Methods of embedded interfaces are collected unchanged; i.e., the identity
-       // of a method I.m's Func Object of an interface I is the same as that of
-       // the method m in an interface that embeds interface I. On the other hand,
-       // if a method is embedded via multiple overlapping embedded interfaces, we
-       // don't provide a guarantee which "original m" got chosen for the embedding
-       // interface. See also issue #34421.
-       //
-       // If we don't care to provide this identity guarantee anymore, instead of
-       // reusing the original method in embeddings, we can clone the method's Func
-       // Object and give it the position of a corresponding embedded interface. Then
-       // we can get rid of the mpos map below and simply use the cloned method's
-       // position.
-
-       var seen objset
-       var methods []*Func
-       mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages
-       addMethod := func(pos token.Pos, m *Func, explicit bool) {
-               switch other := seen.insert(m); {
-               case other == nil:
-                       methods = append(methods, m)
-                       mpos[m] = pos
-               case explicit:
-                       check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name)
-                       check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
-               default:
-                       // We have a duplicate method name in an embedded (not explicitly declared) method.
-                       // Check method signatures after all types are computed (issue #33656).
-                       // If we're pre-go1.14 (overlapping embeddings are not permitted), report that
-                       // error here as well (even though we could do it eagerly) because it's the same
-                       // error message.
-                       check.later(func() {
-                               if !check.allowVersion(m.pkg, 1, 14) || !check.identical(m.typ, other.Type()) {
-                                       check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name)
-                                       check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
-                               }
-                       })
-               }
-       }
-
-       for _, m := range ityp.methods {
-               addMethod(m.pos, m, true)
-       }
-
-       // collect types
-       allTypes := ityp.types
-
-       posList := check.posMap[ityp]
-       for i, typ := range ityp.embeddeds {
-               pos := posList[i] // embedding position
-               utyp := under(typ)
-               etyp := asInterface(utyp)
-               if etyp == nil {
-                       if utyp != Typ[Invalid] {
-                               var format string
-                               if _, ok := utyp.(*_TypeParam); ok {
-                                       format = "%s is a type parameter, not an interface"
-                               } else {
-                                       format = "%s is not an interface"
-                               }
-                               // TODO: correct error code.
-                               check.errorf(atPos(pos), _InvalidIfaceEmbed, format, typ)
-                       }
-                       continue
-               }
-               check.completeInterface(pos, etyp)
-               for _, m := range etyp.allMethods {
-                       addMethod(pos, m, false) // use embedding position pos rather than m.pos
-               }
-               allTypes = intersect(allTypes, etyp.allTypes)
-       }
-
-       if methods != nil {
-               sort.Sort(byUniqueMethodName(methods))
-               ityp.allMethods = methods
-       }
-       ityp.allTypes = allTypes
-}
-
-// intersect computes the intersection of the types x and y.
-// Note: A incomming nil type stands for the top type. A top
-// type result is returned as nil.
-func intersect(x, y Type) (r Type) {
-       defer func() {
-               if r == theTop {
-                       r = nil
-               }
-       }()
-
-       switch {
-       case x == theBottom || y == theBottom:
-               return theBottom
-       case x == nil || x == theTop:
-               return y
-       case y == nil || x == theTop:
-               return x
-       }
-
-       xtypes := unpackType(x)
-       ytypes := unpackType(y)
-       // Compute the list rtypes which includes only
-       // types that are in both xtypes and ytypes.
-       // Quadratic algorithm, but good enough for now.
-       // TODO(gri) fix this
-       var rtypes []Type
-       for _, x := range xtypes {
-               if includes(ytypes, x) {
-                       rtypes = append(rtypes, x)
-               }
-       }
-
-       if rtypes == nil {
-               return theBottom
-       }
-       return _NewSum(rtypes)
-}
-
-func sortTypes(list []Type) {
-       sort.Stable(byUniqueTypeName(list))
-}
-
-// byUniqueTypeName named type lists can be sorted by their unique type names.
-type byUniqueTypeName []Type
-
-func (a byUniqueTypeName) Len() int           { return len(a) }
-func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) }
-func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-
-func sortName(t Type) string {
-       if named := asNamed(t); named != nil {
-               return named.obj.Id()
-       }
-       return ""
-}
-
-func sortMethods(list []*Func) {
-       sort.Sort(byUniqueMethodName(list))
-}
-
-func assertSortedMethods(list []*Func) {
-       if !debug {
-               panic("internal error: assertSortedMethods called outside debug mode")
-       }
-       if !sort.IsSorted(byUniqueMethodName(list)) {
-               panic("internal error: methods not sorted")
-       }
-}
-
-// byUniqueMethodName method lists can be sorted by their unique method names.
-type byUniqueMethodName []*Func
-
-func (a byUniqueMethodName) Len() int           { return len(a) }
-func (a byUniqueMethodName) Less(i, j int) bool { return a[i].Id() < a[j].Id() }
-func (a byUniqueMethodName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-
-func (check *Checker) tag(t *ast.BasicLit) string {
-       if t != nil {
-               if t.Kind == token.STRING {
-                       if val, err := strconv.Unquote(t.Value); err == nil {
-                               return val
-                       }
-               }
-               check.invalidAST(t, "incorrect tag syntax: %q", t.Value)
-       }
-       return ""
-}
-
-func (check *Checker) structType(styp *Struct, e *ast.StructType) {
-       list := e.Fields
-       if list == 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 *ast.Ident, embedded bool, pos token.Pos) {
-               if tag != "" && tags == nil {
-                       tags = make([]string, len(fields))
-               }
-               if tags != nil {
-                       tags = append(tags, tag)
-               }
-
-               name := ident.Name
-               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 *ast.Ident, pos token.Pos) {
-               typ = Typ[Invalid]
-               tag = ""
-               add(ident, true, pos)
-       }
-
-       for _, f := range list.List {
-               typ = check.varType(f.Type)
-               tag = check.tag(f.Tag)
-               if len(f.Names) > 0 {
-                       // named fields
-                       for _, name := range f.Names {
-                               add(name, false, 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 := f.Type.Pos()
-                       name := embeddedFieldIdent(f.Type)
-                       if name == nil {
-                               // TODO(rFindley): using invalidAST here causes test failures (all
-                               //                 errors should have codes). Clean this up.
-                               check.errorf(f.Type, _Todo, "invalid AST: embedded field type %s has no name", f.Type)
-                               name = ast.NewIdent("_")
-                               name.NamePos = 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.
-
-                       // for use in the closure below
-                       embeddedTyp := typ
-                       embeddedPos := f.Type
-
-                       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.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer")
-                                       }
-                               case *Pointer:
-                                       check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
-                               case *Interface:
-                                       if isPtr {
-                                               check.errorf(embeddedPos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")
-                                       }
-                               }
-                       })
-               }
-       }
-
-       styp.fields = fields
-       styp.tags = tags
-}
-
-func embeddedFieldIdent(e ast.Expr) *ast.Ident {
-       switch e := e.(type) {
-       case *ast.Ident:
-               return e
-       case *ast.StarExpr:
-               // *T is valid, but **T is not
-               if _, ok := e.X.(*ast.StarExpr); !ok {
-                       return embeddedFieldIdent(e.X)
-               }
-       case *ast.SelectorExpr:
-               return e.Sel
-       case *ast.IndexExpr:
-               return embeddedFieldIdent(e.X)
-       }
-       return nil // invalid embedded field
-}
-
-func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []Type {
-       list := make([]Type, 0, len(types)) // assume all types are correct
-       for _, texpr := range types {
-               if texpr == nil {
-                       check.invalidAST(atPos(pos), "missing type constraint")
-                       continue
-               }
-               list = append(list, check.varType(texpr))
-       }
-
-       // Ensure that each type is only present once in the type list.  Types may be
-       // interfaces, which may not be complete yet. It's ok to do this check at the
-       // end because it's not a requirement for correctness of the code.
-       // Note: This is a quadratic algorithm, but type lists tend to be short.
-       check.later(func() {
-               for i, t := range list {
-                       if t := asInterface(t); t != nil {
-                               check.completeInterface(types[i].Pos(), t)
-                       }
-                       if includes(list[:i], t) {
-                               check.softErrorf(types[i], _Todo, "duplicate type %s in type list", t)
-                       }
-               }
-       })
-
-       return list
-}
-
-// includes reports whether typ is in list.
-func includes(list []Type, typ Type) bool {
-       for _, e := range list {
-               if Identical(typ, e) {
-                       return true
-               }
-       }
-       return false
-}