1
0
mirror of https://github.com/golang/go synced 2024-11-25 03:07:56 -07:00

cmd/api: allow extension of interfaces with unexported methods

Fixes #4061.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/6525047
This commit is contained in:
Russ Cox 2012-09-18 15:57:03 -04:00
parent 8ed026e783
commit a29f3136b4
4 changed files with 57 additions and 19 deletions

View File

@ -2811,7 +2811,7 @@ pkg go/ast, type CompositeLit struct, Elts []Expr
pkg go/ast, type CompositeLit struct, Lbrace token.Pos pkg go/ast, type CompositeLit struct, Lbrace token.Pos
pkg go/ast, type CompositeLit struct, Rbrace token.Pos pkg go/ast, type CompositeLit struct, Rbrace token.Pos
pkg go/ast, type CompositeLit struct, Type Expr pkg go/ast, type CompositeLit struct, Type Expr
pkg go/ast, type Decl interface { End, Pos } pkg go/ast, type Decl interface, unexported methods
pkg go/ast, type Decl interface, End() token.Pos pkg go/ast, type Decl interface, End() token.Pos
pkg go/ast, type Decl interface, Pos() token.Pos pkg go/ast, type Decl interface, Pos() token.Pos
pkg go/ast, type DeclStmt struct pkg go/ast, type DeclStmt struct
@ -2824,7 +2824,7 @@ pkg go/ast, type Ellipsis struct, Ellipsis token.Pos
pkg go/ast, type Ellipsis struct, Elt Expr pkg go/ast, type Ellipsis struct, Elt Expr
pkg go/ast, type EmptyStmt struct pkg go/ast, type EmptyStmt struct
pkg go/ast, type EmptyStmt struct, Semicolon token.Pos pkg go/ast, type EmptyStmt struct, Semicolon token.Pos
pkg go/ast, type Expr interface { End, Pos } pkg go/ast, type Expr interface, unexported methods
pkg go/ast, type Expr interface, End() token.Pos pkg go/ast, type Expr interface, End() token.Pos
pkg go/ast, type Expr interface, Pos() token.Pos pkg go/ast, type Expr interface, Pos() token.Pos
pkg go/ast, type ExprStmt struct pkg go/ast, type ExprStmt struct
@ -2971,13 +2971,13 @@ pkg go/ast, type SliceExpr struct, Lbrack token.Pos
pkg go/ast, type SliceExpr struct, Low Expr pkg go/ast, type SliceExpr struct, Low Expr
pkg go/ast, type SliceExpr struct, Rbrack token.Pos pkg go/ast, type SliceExpr struct, Rbrack token.Pos
pkg go/ast, type SliceExpr struct, X Expr pkg go/ast, type SliceExpr struct, X Expr
pkg go/ast, type Spec interface { End, Pos } pkg go/ast, type Spec interface, unexported methods
pkg go/ast, type Spec interface, End() token.Pos pkg go/ast, type Spec interface, End() token.Pos
pkg go/ast, type Spec interface, Pos() token.Pos pkg go/ast, type Spec interface, Pos() token.Pos
pkg go/ast, type StarExpr struct pkg go/ast, type StarExpr struct
pkg go/ast, type StarExpr struct, Star token.Pos pkg go/ast, type StarExpr struct, Star token.Pos
pkg go/ast, type StarExpr struct, X Expr pkg go/ast, type StarExpr struct, X Expr
pkg go/ast, type Stmt interface { End, Pos } pkg go/ast, type Stmt interface, unexported methods
pkg go/ast, type Stmt interface, End() token.Pos pkg go/ast, type Stmt interface, End() token.Pos
pkg go/ast, type Stmt interface, Pos() token.Pos pkg go/ast, type Stmt interface, Pos() token.Pos
pkg go/ast, type StructType struct pkg go/ast, type StructType struct
@ -5458,7 +5458,7 @@ pkg reflect, type StructField struct, PkgPath string
pkg reflect, type StructField struct, Tag StructTag pkg reflect, type StructField struct, Tag StructTag
pkg reflect, type StructField struct, Type Type pkg reflect, type StructField struct, Type Type
pkg reflect, type StructTag string pkg reflect, type StructTag string
pkg reflect, type Type interface { Align, AssignableTo, Bits, ChanDir, Elem, Field, FieldAlign, FieldByIndex, FieldByName, FieldByNameFunc, Implements, In, IsVariadic, Key, Kind, Len, Method, MethodByName, Name, NumField, NumIn, NumMethod, NumOut, Out, PkgPath, Size, String } pkg reflect, type Type interface, unexported methods
pkg reflect, type Type interface, Align() int pkg reflect, type Type interface, Align() int
pkg reflect, type Type interface, AssignableTo(Type) bool pkg reflect, type Type interface, AssignableTo(Type) bool
pkg reflect, type Type interface, Bits() int pkg reflect, type Type interface, Bits() int
@ -7608,7 +7608,7 @@ pkg syscall (darwin-386), type Rlimit struct, Max uint64
pkg syscall (darwin-386), type RouteMessage struct pkg syscall (darwin-386), type RouteMessage struct
pkg syscall (darwin-386), type RouteMessage struct, Data []byte pkg syscall (darwin-386), type RouteMessage struct, Data []byte
pkg syscall (darwin-386), type RouteMessage struct, Header RtMsghdr pkg syscall (darwin-386), type RouteMessage struct, Header RtMsghdr
pkg syscall (darwin-386), type RoutingMessage interface {} pkg syscall (darwin-386), type RoutingMessage interface, unexported methods
pkg syscall (darwin-386), type RtMetrics struct pkg syscall (darwin-386), type RtMetrics struct
pkg syscall (darwin-386), type RtMetrics struct, Expire int32 pkg syscall (darwin-386), type RtMetrics struct, Expire int32
pkg syscall (darwin-386), type RtMetrics struct, Filler [4]uint32 pkg syscall (darwin-386), type RtMetrics struct, Filler [4]uint32
@ -9427,7 +9427,7 @@ pkg syscall (darwin-386-cgo), type Rlimit struct, Max uint64
pkg syscall (darwin-386-cgo), type RouteMessage struct pkg syscall (darwin-386-cgo), type RouteMessage struct
pkg syscall (darwin-386-cgo), type RouteMessage struct, Data []byte pkg syscall (darwin-386-cgo), type RouteMessage struct, Data []byte
pkg syscall (darwin-386-cgo), type RouteMessage struct, Header RtMsghdr pkg syscall (darwin-386-cgo), type RouteMessage struct, Header RtMsghdr
pkg syscall (darwin-386-cgo), type RoutingMessage interface {} pkg syscall (darwin-386-cgo), type RoutingMessage interface, unexported methods
pkg syscall (darwin-386-cgo), type RtMetrics struct pkg syscall (darwin-386-cgo), type RtMetrics struct
pkg syscall (darwin-386-cgo), type RtMetrics struct, Expire int32 pkg syscall (darwin-386-cgo), type RtMetrics struct, Expire int32
pkg syscall (darwin-386-cgo), type RtMetrics struct, Filler [4]uint32 pkg syscall (darwin-386-cgo), type RtMetrics struct, Filler [4]uint32
@ -11249,7 +11249,7 @@ pkg syscall (darwin-amd64), type Rlimit struct, Max uint64
pkg syscall (darwin-amd64), type RouteMessage struct pkg syscall (darwin-amd64), type RouteMessage struct
pkg syscall (darwin-amd64), type RouteMessage struct, Data []byte pkg syscall (darwin-amd64), type RouteMessage struct, Data []byte
pkg syscall (darwin-amd64), type RouteMessage struct, Header RtMsghdr pkg syscall (darwin-amd64), type RouteMessage struct, Header RtMsghdr
pkg syscall (darwin-amd64), type RoutingMessage interface {} pkg syscall (darwin-amd64), type RoutingMessage interface, unexported methods
pkg syscall (darwin-amd64), type RtMetrics struct pkg syscall (darwin-amd64), type RtMetrics struct
pkg syscall (darwin-amd64), type RtMetrics struct, Expire int32 pkg syscall (darwin-amd64), type RtMetrics struct, Expire int32
pkg syscall (darwin-amd64), type RtMetrics struct, Filler [4]uint32 pkg syscall (darwin-amd64), type RtMetrics struct, Filler [4]uint32
@ -13075,7 +13075,7 @@ pkg syscall (darwin-amd64-cgo), type Rlimit struct, Max uint64
pkg syscall (darwin-amd64-cgo), type RouteMessage struct pkg syscall (darwin-amd64-cgo), type RouteMessage struct
pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Data []byte pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Data []byte
pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Header RtMsghdr pkg syscall (darwin-amd64-cgo), type RouteMessage struct, Header RtMsghdr
pkg syscall (darwin-amd64-cgo), type RoutingMessage interface {} pkg syscall (darwin-amd64-cgo), type RoutingMessage interface, unexported methods
pkg syscall (darwin-amd64-cgo), type RtMetrics struct pkg syscall (darwin-amd64-cgo), type RtMetrics struct
pkg syscall (darwin-amd64-cgo), type RtMetrics struct, Expire int32 pkg syscall (darwin-amd64-cgo), type RtMetrics struct, Expire int32
pkg syscall (darwin-amd64-cgo), type RtMetrics struct, Filler [4]uint32 pkg syscall (darwin-amd64-cgo), type RtMetrics struct, Filler [4]uint32
@ -15046,7 +15046,7 @@ pkg syscall (freebsd-386), type Rlimit struct, Max int64
pkg syscall (freebsd-386), type RouteMessage struct pkg syscall (freebsd-386), type RouteMessage struct
pkg syscall (freebsd-386), type RouteMessage struct, Data []byte pkg syscall (freebsd-386), type RouteMessage struct, Data []byte
pkg syscall (freebsd-386), type RouteMessage struct, Header RtMsghdr pkg syscall (freebsd-386), type RouteMessage struct, Header RtMsghdr
pkg syscall (freebsd-386), type RoutingMessage interface {} pkg syscall (freebsd-386), type RoutingMessage interface, unexported methods
pkg syscall (freebsd-386), type RtMetrics struct pkg syscall (freebsd-386), type RtMetrics struct
pkg syscall (freebsd-386), type RtMetrics struct, Expire uint32 pkg syscall (freebsd-386), type RtMetrics struct, Expire uint32
pkg syscall (freebsd-386), type RtMetrics struct, Filler [3]uint32 pkg syscall (freebsd-386), type RtMetrics struct, Filler [3]uint32
@ -17022,7 +17022,7 @@ pkg syscall (freebsd-amd64), type Rlimit struct, Max int64
pkg syscall (freebsd-amd64), type RouteMessage struct pkg syscall (freebsd-amd64), type RouteMessage struct
pkg syscall (freebsd-amd64), type RouteMessage struct, Data []byte pkg syscall (freebsd-amd64), type RouteMessage struct, Data []byte
pkg syscall (freebsd-amd64), type RouteMessage struct, Header RtMsghdr pkg syscall (freebsd-amd64), type RouteMessage struct, Header RtMsghdr
pkg syscall (freebsd-amd64), type RoutingMessage interface {} pkg syscall (freebsd-amd64), type RoutingMessage interface, unexported methods
pkg syscall (freebsd-amd64), type RtMetrics struct pkg syscall (freebsd-amd64), type RtMetrics struct
pkg syscall (freebsd-amd64), type RtMetrics struct, Expire uint64 pkg syscall (freebsd-amd64), type RtMetrics struct, Expire uint64
pkg syscall (freebsd-amd64), type RtMetrics struct, Filler [3]uint64 pkg syscall (freebsd-amd64), type RtMetrics struct, Filler [3]uint64
@ -30123,7 +30123,7 @@ pkg syscall, type RawSockaddrInet4 struct, Addr [4]byte
pkg syscall, type RawSockaddrInet4 struct, Port uint16 pkg syscall, type RawSockaddrInet4 struct, Port uint16
pkg syscall, type Rusage struct pkg syscall, type Rusage struct
pkg syscall, type Signal int pkg syscall, type Signal int
pkg syscall, type Sockaddr interface {} pkg syscall, type Sockaddr interface, unexported methods
pkg syscall, type SockaddrInet4 struct pkg syscall, type SockaddrInet4 struct
pkg syscall, type SockaddrInet4 struct, Addr [4]byte pkg syscall, type SockaddrInet4 struct, Addr [4]byte
pkg syscall, type SockaddrInet4 struct, Port int pkg syscall, type SockaddrInet4 struct, Port int

View File

@ -892,15 +892,18 @@ type method struct {
sig string // "([]byte) (int, error)", from funcSigString sig string // "([]byte) (int, error)", from funcSigString
} }
// interfaceMethods returns the expanded list of methods for an interface. // interfaceMethods returns the expanded list of exported methods for an interface.
// The boolean complete reports whether the list contains all methods (that is, the
// interface has no unexported methods).
// pkg is the complete package name ("net/http") // pkg is the complete package name ("net/http")
// iname is the interface name. // iname is the interface name.
func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) { func (w *Walker) interfaceMethods(pkg, iname string) (methods []method, complete bool) {
t, ok := w.interfaces[pkgSymbol{pkg, iname}] t, ok := w.interfaces[pkgSymbol{pkg, iname}]
if !ok { if !ok {
log.Fatalf("failed to find interface %s.%s", pkg, iname) log.Fatalf("failed to find interface %s.%s", pkg, iname)
} }
complete = true
for _, f := range t.Methods.List { for _, f := range t.Methods.List {
typ := f.Type typ := f.Type
switch tv := typ.(type) { switch tv := typ.(type) {
@ -912,6 +915,8 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
name: mname.Name, name: mname.Name,
sig: w.funcSigString(ft), sig: w.funcSigString(ft),
}) })
} else {
complete = false
} }
} }
case *ast.Ident: case *ast.Ident:
@ -927,7 +932,9 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
log.Fatalf("unexported embedded interface %q in exported interface %s.%s; confused", log.Fatalf("unexported embedded interface %q in exported interface %s.%s; confused",
embedded, pkg, iname) embedded, pkg, iname)
} }
methods = append(methods, w.interfaceMethods(pkg, embedded)...) m, c := w.interfaceMethods(pkg, embedded)
methods = append(methods, m...)
complete = complete && c
case *ast.SelectorExpr: case *ast.SelectorExpr:
lhs := w.nodeString(tv.X) lhs := w.nodeString(tv.X)
rhs := w.nodeString(tv.Sel) rhs := w.nodeString(tv.Sel)
@ -935,7 +942,9 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
if !ok { if !ok {
log.Fatalf("can't resolve selector %q in interface %s.%s", lhs, pkg, iname) log.Fatalf("can't resolve selector %q in interface %s.%s", lhs, pkg, iname)
} }
methods = append(methods, w.interfaceMethods(fpkg, rhs)...) m, c := w.interfaceMethods(fpkg, rhs)
methods = append(methods, m...)
complete = complete && c
default: default:
log.Fatalf("unknown type %T in interface field", typ) log.Fatalf("unknown type %T in interface field", typ)
} }
@ -945,14 +954,28 @@ func (w *Walker) interfaceMethods(pkg, iname string) (methods []method) {
func (w *Walker) walkInterfaceType(name string, t *ast.InterfaceType) { func (w *Walker) walkInterfaceType(name string, t *ast.InterfaceType) {
methNames := []string{} methNames := []string{}
pop := w.pushScope("type " + name + " interface") pop := w.pushScope("type " + name + " interface")
for _, m := range w.interfaceMethods(w.curPackageName, name) { methods, complete := w.interfaceMethods(w.curPackageName, name)
for _, m := range methods {
methNames = append(methNames, m.name) methNames = append(methNames, m.name)
w.emitFeature(fmt.Sprintf("%s%s", m.name, m.sig)) w.emitFeature(fmt.Sprintf("%s%s", m.name, m.sig))
} }
if !complete {
// The method set has unexported methods, so all the
// implementations are provided by the same package,
// so the method set can be extended. Instead of recording
// the full set of names (below), record only that there were
// unexported methods. (If the interface shrinks, we will notice
// because a method signature emitted during the last loop,
// will disappear.)
w.emitFeature("unexported methods")
}
pop() pop()
if !complete {
return
}
sort.Strings(methNames) sort.Strings(methNames)
if len(methNames) == 0 { if len(methNames) == 0 {
w.emitFeature(fmt.Sprintf("type %s interface {}", name)) w.emitFeature(fmt.Sprintf("type %s interface {}", name))

View File

@ -37,7 +37,7 @@ pkg p1, type Embedded struct
pkg p1, type Error interface { Error, Temporary } pkg p1, type Error interface { Error, Temporary }
pkg p1, type Error interface, Error() string pkg p1, type Error interface, Error() string
pkg p1, type Error interface, Temporary() bool pkg p1, type Error interface, Temporary() bool
pkg p1, type I interface { Get, GetNamed, Name, PackageTwoMeth, Set } pkg p1, type I interface, unexported methods
pkg p1, type I interface, Get(string) int64 pkg p1, type I interface, Get(string) int64
pkg p1, type I interface, GetNamed(string) int64 pkg p1, type I interface, GetNamed(string) int64
pkg p1, type I interface, Name() string pkg p1, type I interface, Name() string
@ -46,6 +46,11 @@ pkg p1, type I interface, Set(string, int64)
pkg p1, type MyInt int pkg p1, type MyInt int
pkg p1, type Namer interface { Name } pkg p1, type Namer interface { Name }
pkg p1, type Namer interface, Name() string pkg p1, type Namer interface, Name() string
pkg p1, type Public interface { X, Y }
pkg p1, type Public interface, X()
pkg p1, type Public interface, Y()
pkg p1, type Private interface, unexported methods
pkg p1, type Private interface, X()
pkg p1, type S struct pkg p1, type S struct
pkg p1, type S struct, Public *int pkg p1, type S struct, Public *int
pkg p1, type S struct, PublicTime time.Time pkg p1, type S struct, PublicTime time.Time

View File

@ -78,6 +78,16 @@ type I interface {
private() private()
} }
type Public interface {
X()
Y()
}
type Private interface {
X()
y()
}
type Error interface { type Error interface {
error error
Temporary() bool Temporary() bool