Commit de2e5459 authored by Matthew Dempsky's avatar Matthew Dempsky

[dev.typealias] cmd/compile: declare methods after resolving receiver type

For #18130.
Fixes #18655.

Change-Id: I58e2f076b9d8273f128cc033bba9edcd06c81567
Reviewed-on: https://go-review.googlesource.com/35575
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 9259f307
...@@ -466,14 +466,7 @@ func (p *importer) typ() *Type { ...@@ -466,14 +466,7 @@ func (p *importer) typ() *Type {
result := p.paramList() result := p.paramList()
nointerface := p.bool() nointerface := p.bool()
base := recv[0].Type n := newfuncname(methodname(sym, recv[0].Type))
star := false
if base.IsPtr() {
base = base.Elem()
star = true
}
n := methodname0(sym, star, base.Sym)
n.Type = functypefield(recv[0], params, result) n.Type = functypefield(recv[0], params, result)
checkwidth(n.Type) checkwidth(n.Type)
addmethod(sym, n.Type, false, nointerface) addmethod(sym, n.Type, false, nointerface)
......
...@@ -519,10 +519,6 @@ func funchdr(n *Node) { ...@@ -519,10 +519,6 @@ func funchdr(n *Node) {
Fatalf("funchdr: dclcontext = %d", dclcontext) Fatalf("funchdr: dclcontext = %d", dclcontext)
} }
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
makefuncsym(n.Func.Nname.Sym)
}
dclcontext = PAUTO dclcontext = PAUTO
funcstart(n) funcstart(n)
...@@ -1163,19 +1159,19 @@ bad: ...@@ -1163,19 +1159,19 @@ bad:
return nil return nil
} }
func methodname(s *Sym, recv *Node) *Node { // methodname is a misnomer because this now returns a Sym, rather
// than an ONAME.
// TODO(mdempsky): Reconcile with methodsym.
func methodname(s *Sym, recv *Type) *Sym {
star := false star := false
if recv.Op == OIND { if recv.IsPtr() {
star = true star = true
recv = recv.Left recv = recv.Elem()
} }
return methodname0(s, star, recv.Sym) tsym := recv.Sym
}
func methodname0(s *Sym, star bool, tsym *Sym) *Node {
if tsym == nil || isblanksym(s) { if tsym == nil || isblanksym(s) {
return newfuncname(s) return s
} }
var p string var p string
...@@ -1191,7 +1187,7 @@ func methodname0(s *Sym, star bool, tsym *Sym) *Node { ...@@ -1191,7 +1187,7 @@ func methodname0(s *Sym, star bool, tsym *Sym) *Node {
s = Pkglookup(p, tsym.Pkg) s = Pkglookup(p, tsym.Pkg)
} }
return newfuncname(s) return s
} }
// Add a method, declared as a function. // Add a method, declared as a function.
...@@ -1335,6 +1331,9 @@ func makefuncsym(s *Sym) { ...@@ -1335,6 +1331,9 @@ func makefuncsym(s *Sym) {
return return
} }
s1 := funcsym(s) s1 := funcsym(s)
if s1.Def != nil {
return
}
s1.Def = newfuncname(s1) s1.Def = newfuncname(s1)
s1.Def.Func.Shortname = s s1.Def.Func.Shortname = s
funcsyms = append(funcsyms, s1.Def) funcsyms = append(funcsyms, s1.Def)
......
...@@ -83,7 +83,7 @@ func autoexport(n *Node, ctxt Class) { ...@@ -83,7 +83,7 @@ func autoexport(n *Node, ctxt Class) {
if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN { if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
return return
} }
if n.Name.Param != nil && n.Name.Param.Ntype != nil && n.Name.Param.Ntype.Op == OTFUNC && n.Name.Param.Ntype.Left != nil { // method if n.Type != nil && n.Type.IsKind(TFUNC) && n.Type.Recv() != nil { // method
return return
} }
......
...@@ -247,19 +247,19 @@ func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node { ...@@ -247,19 +247,19 @@ func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node {
yyerror("func main must have no arguments and no return values") yyerror("func main must have no arguments and no return values")
} }
} }
f.Func.Nname = newfuncname(name)
} else { } else {
// Receiver MethodName Signature
f.Func.Shortname = name f.Func.Shortname = name
f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right) name = nblank.Sym // filled in by typecheckfunc
} }
f.Func.Nname = newfuncname(name)
f.Func.Nname.Name.Defn = f f.Func.Nname.Name.Defn = f
f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
declare(f.Func.Nname, PFUNC) if fun.Recv == nil {
declare(f.Func.Nname, PFUNC)
}
funchdr(f) funchdr(f)
return f return f
} }
......
...@@ -3436,8 +3436,15 @@ func typecheckfunc(n *Node) { ...@@ -3436,8 +3436,15 @@ func typecheckfunc(n *Node) {
t.SetNname(n.Func.Nname) t.SetNname(n.Func.Nname)
rcvr := t.Recv() rcvr := t.Recv()
if rcvr != nil && n.Func.Shortname != nil { if rcvr != nil && n.Func.Shortname != nil {
n.Func.Nname.Sym = methodname(n.Func.Shortname, rcvr.Type)
declare(n.Func.Nname, PFUNC)
addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0) addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0)
} }
if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
makefuncsym(n.Func.Nname.Sym)
}
} }
// The result of stringtoarraylit MUST be assigned back to n, e.g. // The result of stringtoarraylit MUST be assigned back to n, e.g.
......
...@@ -37,8 +37,8 @@ type ( ...@@ -37,8 +37,8 @@ type (
// Methods can be declared on the original named type and the alias. // Methods can be declared on the original named type and the alias.
func (T0) m1() {} // GCCGO_ERROR "previous" func (T0) m1() {} // GCCGO_ERROR "previous"
func (*T0) m1() {} // ERROR "method redeclared: T0\.m1|redefinition of .m1." func (*T0) m1() {} // ERROR "method redeclared: T0\.m1|redefinition of .m1."
func (A0) m1() {} // TODO(gri) this should be an error // GCCGO_ERROR "redefinition of .m1." func (A0) m1() {} // ERROR "T0\.m1 redeclared in this block|redefinition of .m1."
func (A0) m1() {} // ERROR "A0\.m1 redeclared in this block|redefinition of .m1." func (A0) m1() {} // ERROR "T0\.m1 redeclared in this block|redefinition of .m1."
func (A0) m2() {} func (A0) m2() {}
// Type aliases and the original type name can be used interchangeably. // Type aliases and the original type name can be used interchangeably.
...@@ -95,10 +95,10 @@ type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type|expected type" ...@@ -95,10 +95,10 @@ type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type|expected type"
func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type" func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type"
func (A2) m() {} // ERROR "invalid receiver type" func (A2) m() {} // ERROR "invalid receiver type"
func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type" func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
func (A4) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type" func (A4) m() {} // ERROR "reflect.Value.m redeclared in this block" "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
type B1 = struct{} type B1 = struct{}
func (B1) m() {} // ERROR "invalid receiver type" func (B1) m() {} // ERROR "m redeclared in this block" "invalid receiver type"
// TODO(gri) expand // TODO(gri) expand
// errorcheck
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
type T struct{}
type A = T
type B = T
func (T) m() {}
func (T) m() {} // ERROR "redeclared"
func (A) m() {} // ERROR "redeclared"
func (A) m() {} // ERROR "redeclared"
func (B) m() {} // ERROR "redeclared"
func (B) m() {} // ERROR "redeclared"
func (*T) m() {} // ERROR "redeclared"
func (*A) m() {} // ERROR "redeclared"
func (*B) m() {} // ERROR "redeclared"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment