]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/reflectdata/reflect.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / src / cmd / compile / internal / reflectdata / reflect.go
index 0d3070fd39c6d3e576afa74dcc3d6270d61cdd5c..e76f9c5f3c1b19e405e8a6880290e9cfd2771604 100644 (file)
@@ -846,14 +846,19 @@ func TypePtr(t *types.Type) *ir.AddrExpr {
        return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr)
 }
 
-// ITabLsym returns the LSym representing the itab for concreate type typ
-// implementing interface iface.
+// ITabLsym returns the LSym representing the itab for concrete type typ implementing
+// interface iface. A dummy tab will be created in the unusual case where typ doesn't
+// implement iface. Normally, this wouldn't happen, because the typechecker would
+// have reported a compile-time error. This situation can only happen when the
+// destination type of a type assert or a type in a type switch is parameterized, so
+// it may sometimes, but not always, be a type that can't implement the specified
+// interface.
 func ITabLsym(typ, iface *types.Type) *obj.LSym {
        s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
        lsym := s.Linksym()
 
        if !existed {
-               writeITab(lsym, typ, iface)
+               writeITab(lsym, typ, iface, true)
        }
        return lsym
 }
@@ -865,7 +870,7 @@ func ITabAddr(typ, iface *types.Type) *ir.AddrExpr {
        lsym := s.Linksym()
 
        if !existed {
-               writeITab(lsym, typ, iface)
+               writeITab(lsym, typ, iface, false)
        }
 
        n := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8])
@@ -924,11 +929,12 @@ func hashMightPanic(t *types.Type) bool {
        }
 }
 
-// formalType replaces byte and rune aliases with real types.
+// formalType replaces predeclared aliases with real types.
 // They've been separate internally to make error messages
 // better, but we have to merge them in the reflect tables.
 func formalType(t *types.Type) *types.Type {
-       if t == types.ByteType || t == types.RuneType {
+       switch t {
+       case types.AnyType, types.ByteType, types.RuneType:
                return types.Types[t.Kind()]
        }
        return t
@@ -1303,9 +1309,10 @@ func WriteRuntimeTypes() {
        }
 }
 
-// writeITab writes the itab for concrete type typ implementing
-// interface iface.
-func writeITab(lsym *obj.LSym, typ, iface *types.Type) {
+// writeITab writes the itab for concrete type typ implementing interface iface. If
+// allowNonImplement is true, allow the case where typ does not implement iface, and just
+// create a dummy itab with zeroed-out method entries.
+func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
        // TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe
        // others) to stop clobbering these.
        oldpos, oldfn := base.Pos, ir.CurFunc
@@ -1331,14 +1338,9 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) {
                                break
                        }
                }
-               if sigs[0].Sym.Name == "==" {
-                       sigs = sigs[1:]
-                       if len(sigs) == 0 {
-                               break
-                       }
-               }
        }
-       if len(sigs) != 0 {
+       completeItab := len(sigs) == 0
+       if !allowNonImplement && !completeItab {
                base.Fatalf("incomplete itab")
        }
 
@@ -1355,7 +1357,12 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type) {
        o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash
        o += 4                                        // skip unused field
        for _, fn := range entries {
-               o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
+               if !completeItab {
+                       // If typ doesn't implement iface, make method entries be zero.
+                       o = objw.Uintptr(lsym, o, 0)
+               } else {
+                       o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
+               }
        }
        // Nothing writes static itabs, so they are read only.
        objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
@@ -1417,6 +1424,9 @@ func WriteBasicTypes() {
                }
                writeType(types.NewPtr(types.Types[types.TSTRING]))
                writeType(types.NewPtr(types.Types[types.TUNSAFEPTR]))
+               if base.Flag.G > 0 {
+                       writeType(types.AnyType)
+               }
 
                // emit type structs for error and func(error) string.
                // The latter is the type of an auto-generated wrapper.
@@ -1938,18 +1948,25 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
 
                        // Target method uses shaped names.
                        targs2 := make([]*types.Type, len(targs))
+                       origRParams := deref(orig).OrigSym().Def.(*ir.Name).Type().RParams()
                        for i, t := range targs {
-                               targs2[i] = typecheck.Shapify(t, i)
+                               targs2[i] = typecheck.Shapify(t, i, origRParams[i])
                        }
                        targs = targs2
 
                        sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true)
                        if sym.Def == nil {
-                               // Currently we make sure that we have all the instantiations
-                               // we need by generating them all in ../noder/stencil.go:instantiateMethods
-                               // TODO: maybe there's a better, more incremental way to generate
-                               // only the instantiations we need?
-                               base.Fatalf("instantiation %s not found", sym.Name)
+                               // Currently we make sure that we have all the
+                               // instantiations we need by generating them all in
+                               // ../noder/stencil.go:instantiateMethods
+                               // Extra instantiations because of an inlined function
+                               // should have been exported, and so available via
+                               // Resolve.
+                               in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
+                               if in.Op() == ir.ONONAME {
+                                       base.Fatalf("instantiation %s not found", sym.Name)
+                               }
+                               sym = in.Sym()
                        }
                        target := ir.AsNode(sym.Def)
                        call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args)
@@ -2075,8 +2092,14 @@ func getDictionary(gf *types.Sym, targs []*types.Type) ir.Node {
        sym := typecheck.MakeDictSym(gf, targs, true)
 
        // Dictionary should already have been generated by instantiateMethods().
+       // Extra dictionaries needed because of an inlined function should have been
+       // exported, and so available via Resolve.
        if lsym := sym.Linksym(); len(lsym.P) == 0 {
-               base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
+               in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
+               if in.Op() == ir.ONONAME {
+                       base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
+               }
+               sym = in.Sym()
        }
 
        // Make (or reuse) a node referencing the dictionary symbol.