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:
parent
8ed026e783
commit
a29f3136b4
24
api/go1.txt
24
api/go1.txt
@ -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
|
||||||
|
@ -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))
|
||||||
|
7
src/cmd/api/testdata/src/pkg/p1/golden.txt
vendored
7
src/cmd/api/testdata/src/pkg/p1/golden.txt
vendored
@ -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
|
||||||
|
10
src/cmd/api/testdata/src/pkg/p1/p1.go
vendored
10
src/cmd/api/testdata/src/pkg/p1/p1.go
vendored
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user