]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/go/types/typexpr.go
[dev.typeparams] merge master (2f0da6d) into dev.typeparams
[gostls13.git] / src / go / types / typexpr.go
index b9249494fa16d0159d65f7e1c8213d8c3e5ae8a7..503f9c71aca63501fc2798e5219aa4d2a6b78eec 100644 (file)
@@ -7,11 +7,13 @@
 package types
 
 import (
+       "fmt"
        "go/ast"
        "go/constant"
        "go/token"
        "sort"
        "strconv"
+       "strings"
 )
 
 // ident type-checks identifier e and initializes x with the value or type of e.
@@ -116,41 +118,218 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
 }
 
 // typ type-checks the type expression e and returns its type, or Typ[Invalid].
+// The type must not be an (uninstantiated) generic type.
 func (check *Checker) typ(e ast.Expr) Type {
        return check.definedType(e, nil)
 }
 
+// varType type-checks the type expression e and returns its type, or Typ[Invalid].
+// The type must not be an (uninstantiated) generic type and it must be ordinary
+// (see ordinaryType).
+func (check *Checker) varType(e ast.Expr) Type {
+       typ := check.definedType(e, nil)
+       check.ordinaryType(e, typ)
+       return typ
+}
+
+// ordinaryType reports an error if typ is an interface type containing
+// type lists or is (or embeds) the predeclared type comparable.
+func (check *Checker) ordinaryType(pos positioner, typ Type) {
+       // We don't want to call under() (via asInterface) or complete interfaces
+       // while we are in the middle of type-checking parameter declarations that
+       // might belong to interface methods. Delay this check to the end of
+       // type-checking.
+       check.atEnd(func() {
+               if t := asInterface(typ); t != nil {
+                       check.completeInterface(pos.Pos(), t) // TODO(gri) is this the correct position?
+                       if t.allTypes != nil {
+                               check.softErrorf(pos, _Todo, "interface contains type constraints (%s)", t.allTypes)
+                               return
+                       }
+                       if t.IsComparable() {
+                               check.softErrorf(pos, _Todo, "interface is (or embeds) comparable")
+                       }
+               }
+       })
+}
+
+// anyType type-checks the type expression e and returns its type, or Typ[Invalid].
+// The type may be generic or instantiated.
+func (check *Checker) anyType(e ast.Expr) Type {
+       typ := check.typInternal(e, nil)
+       assert(isTyped(typ))
+       check.recordTypeAndValue(e, typexpr, typ, nil)
+       return typ
+}
+
 // definedType is like typ but also accepts a type name def.
 // If def != nil, e is the type specification for the defined type def, declared
 // in a type declaration, and def.underlying will be set to the type of e before
 // any components of e are type-checked.
 //
-func (check *Checker) definedType(e ast.Expr, def *Named) (T Type) {
-       if trace {
-               check.trace(e.Pos(), "%s", e)
-               check.indent++
-               defer func() {
-                       check.indent--
-                       check.trace(e.Pos(), "=> %s", T)
-               }()
+func (check *Checker) definedType(e ast.Expr, def *Named) Type {
+       typ := check.typInternal(e, def)
+       assert(isTyped(typ))
+       if isGeneric(typ) {
+               check.errorf(e, _Todo, "cannot use generic type %s without instantiation", typ)
+               typ = Typ[Invalid]
        }
+       check.recordTypeAndValue(e, typexpr, typ, nil)
+       return typ
+}
 
-       T = check.typInternal(e, def)
-       assert(isTyped(T))
-       check.recordTypeAndValue(e, typexpr, T, nil)
+// genericType is like typ but the type must be an (uninstantiated) generic type.
+func (check *Checker) genericType(e ast.Expr, reportErr bool) Type {
+       typ := check.typInternal(e, nil)
+       assert(isTyped(typ))
+       if typ != Typ[Invalid] && !isGeneric(typ) {
+               if reportErr {
+                       check.errorf(e, _Todo, "%s is not a generic type", typ)
+               }
+               typ = Typ[Invalid]
+       }
+       // TODO(gri) what is the correct call below?
+       check.recordTypeAndValue(e, typexpr, typ, nil)
+       return typ
+}
 
-       return
+// 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.CallExpr:
+               var args []ast.Expr
+               for i, arg := range n.Args {
+                       new := isubst(arg, smap)
+                       if new != arg {
+                               if args == nil {
+                                       args = make([]ast.Expr, len(n.Args))
+                                       copy(args, n.Args)
+                               }
+                               args[i] = new
+                       }
+               }
+               if args != nil {
+                       new := *n
+                       new.Args = args
+                       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) {
-       scope := NewScope(check.scope, token.NoPos, token.NoPos, "function")
-       scope.isFunc = true
-       check.recordScope(ftyp, scope)
+       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 ftyp.TParams != nil {
+               sig.tparams = check.collectTypeParams(ftyp.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(ftyp.TParams, _Todo, "methods cannot have type parameters")
+               }
+       }
 
-       recvList, _ := check.collectParams(scope, recvPar, false)
-       params, variadic := check.collectParams(scope, ftyp.Params, true)
-       results, _ := check.collectParams(scope, ftyp.Results, false)
+       // 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)
@@ -159,7 +338,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                var recv *Var
                switch len(recvList) {
                case 0:
-                       check.error(recvPar, _BadRecv, "method is missing receiver")
+                       // error reported by resolver
                        recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
                default:
                        // more than one receiver
@@ -168,19 +347,24 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                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, _ := deref(recv.typ); t != Typ[Invalid] {
+               if t := rtyp; t != Typ[Invalid] {
                        var err string
-                       if T, _ := t.(*Named); T != nil {
+                       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 {
-                                       // TODO(gri) This is not correct if the underlying type is unknown yet.
-                                       switch u := T.underlying.(type) {
+                                       switch u := optype(T).(type) {
                                        case *Basic:
                                                // unsafe.Pointer is treated like a regular pointer
                                                if u.kind == UnsafePointer {
@@ -201,17 +385,43 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast
                sig.recv = recv
        }
 
-       sig.scope = scope
        sig.params = NewTuple(params...)
        sig.results = NewTuple(results...)
        sig.variadic = variadic
 }
 
+// goTypeName returns the Go type name for typ and
+// removes any occurences of "types." from that name.
+func goTypeName(typ Type) string {
+       return strings.ReplaceAll(fmt.Sprintf("%T", typ), "types.", "")
+}
+
 // typInternal drives type checking of types.
-// Must only be called by definedType.
+// Must only be called by definedType or genericType.
 //
-func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
-       switch e := e.(type) {
+func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
+       if trace {
+               check.trace(e0.Pos(), "type %s", e0)
+               check.indent++
+               defer func() {
+                       check.indent--
+                       var under Type
+                       if T != nil {
+                               // Calling under() here may lead to endless instantiations.
+                               // Test case: type T[P any] *T[P]
+                               // TODO(gri) investigate if that's a bug or to be expected
+                               // (see also analogous comment in Checker.instantiate).
+                               under = T.Underlying()
+                       }
+                       if T == under {
+                               check.trace(e0.Pos(), "=> %s // %s", T, goTypeName(T))
+                       } else {
+                               check.trace(e0.Pos(), "=> %s (under = %s) // %s", T, under, goTypeName(T))
+                       }
+               }()
+       }
+
+       switch e := e0.(type) {
        case *ast.BadExpr:
                // ignore - error reported before
 
@@ -249,7 +459,19 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                        check.errorf(&x, _NotAType, "%s is not a type", &x)
                }
 
+       case *ast.IndexExpr:
+               return check.instantiatedType(e.X, []ast.Expr{e.Index}, def)
+
+       case *ast.CallExpr:
+               if e.Brackets {
+                       return check.instantiatedType(e.Fun, e.Args, def)
+               } else {
+                       check.errorf(e0, _NotAType, "%s is not a type", e0)
+               }
+
        case *ast.ParenExpr:
+               // Generic types must be instantiated before they can be used in any form.
+               // Consequently, generic types cannot be parenthesized.
                return check.definedType(e.X, def)
 
        case *ast.ArrayType:
@@ -257,16 +479,21 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                        typ := new(Array)
                        def.setUnderlying(typ)
                        typ.len = check.arrayLength(e.Len)
-                       typ.elem = check.typ(e.Elt)
-                       return typ
-
-               } else {
-                       typ := new(Slice)
-                       def.setUnderlying(typ)
-                       typ.elem = check.typ(e.Elt)
+                       typ.elem = check.varType(e.Elt)
                        return typ
                }
 
+               typ := new(Slice)
+               def.setUnderlying(typ)
+               typ.elem = check.varType(e.Elt)
+               return typ
+
+       case *ast.Ellipsis:
+               // dots are handled explicitly where they are legal
+               // (array composite literals and parameter lists)
+               check.error(e, _InvalidDotDotDot, "invalid use of '...'")
+               check.use(e.Elt)
+
        case *ast.StructType:
                typ := new(Struct)
                def.setUnderlying(typ)
@@ -276,7 +503,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
        case *ast.StarExpr:
                typ := new(Pointer)
                def.setUnderlying(typ)
-               typ.base = check.typ(e.X)
+               typ.base = check.varType(e.X)
                return typ
 
        case *ast.FuncType:
@@ -288,6 +515,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
        case *ast.InterfaceType:
                typ := new(Interface)
                def.setUnderlying(typ)
+               if def != nil {
+                       typ.obj = def.obj
+               }
                check.interfaceType(typ, e, def)
                return typ
 
@@ -295,8 +525,8 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                typ := new(Map)
                def.setUnderlying(typ)
 
-               typ.key = check.typ(e.Key)
-               typ.elem = check.typ(e.Value)
+               typ.key = check.varType(e.Key)
+               typ.elem = check.varType(e.Value)
 
                // spec: "The comparison operators == and != must be fully defined
                // for operands of the key type; thus the key type must not be a
@@ -306,7 +536,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                // it is safe to continue in any case (was issue 6667).
                check.atEnd(func() {
                        if !Comparable(typ.key) {
-                               check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s", typ.key)
+                               var why string
+                               if asTypeParam(typ.key) != nil {
+                                       why = " (missing comparable constraint)"
+                               }
+                               check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s%s", typ.key, why)
                        }
                })
 
@@ -330,11 +564,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
                }
 
                typ.dir = dir
-               typ.elem = check.typ(e.Value)
+               typ.elem = check.varType(e.Value)
                return typ
 
        default:
-               check.errorf(e, _NotAType, "%s is not a type", e)
+               check.errorf(e0, _NotAType, "%s is not a type", e0)
        }
 
        typ := Typ[Invalid]
@@ -343,10 +577,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
 }
 
 // typeOrNil type-checks the type expression (or nil value) e
-// and returns the typ of e, or nil.
-// If e is neither a type nor nil, typOrNil returns Typ[Invalid].
-//
-func (check *Checker) typOrNil(e ast.Expr) Type {
+// and returns the type of e, or nil. If e is a type, it must
+// not be an (uninstantiated) generic type.
+// If e is neither a type nor nil, typeOrNil returns Typ[Invalid].
+// TODO(gri) should we also disallow non-var types?
+func (check *Checker) typeOrNil(e ast.Expr) Type {
        var x operand
        check.rawExpr(&x, e, nil)
        switch x.mode {
@@ -355,6 +590,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
        case novalue:
                check.errorf(&x, _NotAType, "%s used as type", &x)
        case typexpr:
+               check.instantiatedOperand(&x)
                return x.typ
        case value:
                if x.isNil() {
@@ -367,6 +603,49 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
        return Typ[Invalid]
 }
 
+func (check *Checker) instantiatedType(x ast.Expr, targs []ast.Expr, def *Named) Type {
+       b := check.genericType(x, true) // TODO(gri) what about cycles?
+       if b == Typ[Invalid] {
+               return b // error already reported
+       }
+       base := asNamed(b)
+       if base == nil {
+               unreachable() // should have been caught by genericType
+       }
+
+       // create a new type instance rather than instantiate the type
+       // TODO(gri) should do argument number check here rather than
+       //           when instantiating the type?
+       typ := new(instance)
+       def.setUnderlying(typ)
+
+       typ.check = check
+       typ.pos = x.Pos()
+       typ.base = base
+
+       // evaluate arguments (always)
+       typ.targs = check.typeList(targs)
+       if typ.targs == nil {
+               def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
+               return Typ[Invalid]
+       }
+
+       // determine argument positions (for error reporting)
+       typ.poslist = make([]token.Pos, len(targs))
+       for i, arg := range targs {
+               typ.poslist[i] = arg.Pos()
+       }
+
+       // make sure we check instantiation works at least once
+       // and that the resulting type is valid
+       check.atEnd(func() {
+               t := typ.expand()
+               check.validType(t, nil)
+       })
+
+       return typ
+}
+
 // arrayLength type-checks the array length expression e
 // and returns the constant length >= 0, or a value < 0
 // to indicate an error (and thus an unknown length).
@@ -394,7 +673,25 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
        return -1
 }
 
-func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
+// typeList provides the list of types corresponding to the incoming expression list.
+// If an error occured, the result is nil, but all list elements were type-checked.
+func (check *Checker) typeList(list []ast.Expr) []Type {
+       res := make([]Type, len(list)) // res != nil even if len(list) == 0
+       for i, x := range list {
+               t := check.varType(x)
+               if t == Typ[Invalid] {
+                       res = nil
+               }
+               if res != nil {
+                       res[i] = t
+               }
+       }
+       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 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
        }
@@ -402,6 +699,9 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
        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 {
@@ -411,7 +711,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
                                // ignore ... and continue
                        }
                }
-               typ := check.typ(ftype)
+               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 {
@@ -462,9 +762,12 @@ func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool
 }
 
 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].
+                       // 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]
@@ -473,6 +776,18 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                                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 {
@@ -482,6 +797,13 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                                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 {
+                               check.errorf(f.Type.(*ast.FuncType).TParams, _Todo, "methods cannot have type parameters")
+                       }
+
                        // use named receiver type if available (for better error messages)
                        var recvTyp Type = ityp
                        if def != nil {
@@ -493,25 +815,17 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
                        check.recordDef(name, m)
                        ityp.methods = append(ityp.methods, m)
                } else {
-                       // We have an embedded interface and f.Type is its
-                       // (possibly qualified) embedded type name. Collect
-                       // it if it's a valid interface.
-                       typ := check.typ(f.Type)
-
-                       utyp := check.underlying(typ)
-                       if _, ok := utyp.(*Interface); !ok {
-                               if utyp != Typ[Invalid] {
-                                       check.errorf(f.Type, _InvalidIfaceEmbed, "%s is not an interface", typ)
-                               }
-                               continue
-                       }
-
-                       ityp.embeddeds = append(ityp.embeddeds, typ)
+                       // 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())
                }
        }
 
-       if len(ityp.methods) == 0 && len(ityp.embeddeds) == 0 {
+       // 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
@@ -521,10 +835,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
        sortMethods(ityp.methods)
        sortTypes(ityp.embeddeds)
 
-       check.later(func() { check.completeInterface(ityp) })
+       check.later(func() { check.completeInterface(iface.Pos(), ityp) })
 }
 
-func (check *Checker) completeInterface(ityp *Interface) {
+func (check *Checker) completeInterface(pos token.Pos, ityp *Interface) {
        if ityp.allMethods != nil {
                return
        }
@@ -538,11 +852,18 @@ func (check *Checker) completeInterface(ityp *Interface) {
        }
 
        if trace {
-               check.trace(token.NoPos, "complete %s", ityp)
+               // 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(token.NoPos, "=> %s", ityp)
+                       check.trace(pos, "=> %s (methods = %v, types = %v)", ityp, ityp.allMethods, ityp.allTypes)
                }()
        }
 
@@ -596,25 +917,77 @@ func (check *Checker) completeInterface(ityp *Interface) {
                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
-               typ, ok := check.underlying(typ).(*Interface)
-               if !ok {
-                       // An error was reported when collecting the embedded types.
-                       // Ignore it.
+               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(typ)
-               for _, m := range typ.allMethods {
+               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) {
@@ -629,7 +1002,7 @@ func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName
 func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 
 func sortName(t Type) string {
-       if named, _ := t.(*Named); named != nil {
+       if named := asNamed(t); named != nil {
                return named.obj.Id()
        }
        return ""
@@ -711,7 +1084,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
        }
 
        for _, f := range list.List {
-               typ = check.typ(f.Type)
+               typ = check.varType(f.Type)
                tag = check.tag(f.Tag)
                if len(f.Names) > 0 {
                        // named fields
@@ -720,48 +1093,51 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
                        }
                } 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."
+                       // 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 {
-                               check.invalidAST(f.Type, "embedded field type %s has no name", f.Type)
+                               // 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
                        }
-                       t, isPtr := deref(typ)
+                       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.
-                       switch t := t.Underlying().(type) {
-                       case *Basic:
-                               if t == Typ[Invalid] {
-                                       // error was reported before
-                                       addInvalid(name, pos)
-                                       continue
-                               }
-
-                               // unsafe.Pointer is treated like a regular pointer
-                               if t.kind == UnsafePointer {
-                                       check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer")
-                                       addInvalid(name, pos)
-                                       continue
-                               }
+                       // We must delay this check to the end because we don't want to instantiate
+                       // (via under(t)) a possibly incomplete type.
 
-                       case *Pointer:
-                               check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer")
-                               addInvalid(name, pos)
-                               continue
+                       // for use in the closure below
+                       embeddedTyp := typ
+                       embeddedPos := f.Type
 
-                       case *Interface:
-                               if isPtr {
-                                       check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface")
-                                       addInvalid(name, pos)
-                                       continue
+                       check.atEnd(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")
+                                       }
                                }
-                       }
-                       add(name, true, pos)
+                       })
                }
        }
 
@@ -780,6 +1156,50 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident {
                }
        case *ast.SelectorExpr:
                return e.Sel
+       case *ast.IndexExpr:
+               return embeddedFieldIdent(e.X)
+       case *ast.CallExpr:
+               if e.Brackets {
+                       return embeddedFieldIdent(e.Fun)
+               }
        }
        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.atEnd(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
+}