From: Robert Griesemer Date: Wed, 1 Mar 2023 21:53:48 +0000 (-0800) Subject: go/types, types2: combine missingMethodCause with missingMethod X-Git-Tag: go1.21rc1~1391 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2f9e38a1be0b2e09898dac261ae8894dcb2594a0;p=gostls13.git go/types, types2: combine missingMethodCause with missingMethod For now this is simply a mechanical combination without any relevant logic changes. This will make it easier to review subsequent changes. Change-Id: Ic2e2ae32b031d2dda0f69a08a5cc2349748bd25d Reviewed-on: https://go-review.googlesource.com/c/go/+/472675 Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot Auto-Submit: Robert Griesemer --- diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 7c20a28136..216bed9734 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -323,14 +323,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y return } - var alt *Func - if cause != nil { - defer func() { - if method != nil { - *cause = check.missingMethodCause(V, T, method, alt) - } - }() - } + var alt *Func // alternative method (pointer receiver or similar spelling) // V is an interface if u, _ := under(V).(*Interface); u != nil { @@ -342,16 +335,18 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y if !static { continue } - return m, false + method = m + goto Error } if !equivalent(f.typ, m.typ) { - alt = f - return m, true + method, alt = m, f + wrongType = true + goto Error } } - return + return nil, false } // V is not an interface @@ -372,7 +367,8 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y // we must have a method (not a struct field) f, _ := obj.(*Func) if f == nil { - return m, false + method = m + goto Error } // methods may not have a fully set up signature yet @@ -381,60 +377,63 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y } if !found || !equivalent(f.typ, m.typ) { - alt = f - return m, f.name == m.name + method, alt = m, f + wrongType = f.name == m.name + goto Error } } - return -} + return nil, false -// missingMethodCause returns a string giving the detailed cause for a missing method m, -// where m is missing from V, but required by T. It puts the cause in parentheses, -// and may include more have/want info after that. If non-nil, alt is a relevant -// method that matches in some way. It may have the correct name, but wrong type, or -// it may have a pointer receiver, or it may have the correct name except wrong case. -// check may be nil. -// missingMethodCause should only be called by missingMethod. -// TODO(gri) integrate this logic into missingMethod and get rid of this function. -func (check *Checker) missingMethodCause(V, T Type, m, alt *Func) string { - mname := "method " + m.Name() +Error: + if cause == nil { + return + } + + mname := "method " + method.Name() if alt != nil { - if m.Name() != alt.Name() { - return check.sprintf("(missing %s)\n\t\thave %s\n\t\twant %s", - mname, check.funcString(alt, false), check.funcString(m, false)) + if method.Name() != alt.Name() { + *cause = check.sprintf("(missing %s)\n\t\thave %s\n\t\twant %s", + mname, check.funcString(alt, false), check.funcString(method, false)) + return } - if Identical(m.typ, alt.typ) { - return check.sprintf("(%s has pointer receiver)", mname) + if Identical(method.typ, alt.typ) { + *cause = check.sprintf("(%s has pointer receiver)", mname) + return } - altS, mS := check.funcString(alt, false), check.funcString(m, false) - if altS == mS { + altS, methodS := check.funcString(alt, false), check.funcString(method, false) + if altS == methodS { // Would tell the user that Foo isn't a Foo, add package information to disambiguate. // See go.dev/issue/54258. - altS, mS = check.funcString(alt, true), check.funcString(m, true) + altS, methodS = check.funcString(alt, true), check.funcString(method, true) } - return check.sprintf("(wrong type for %s)\n\t\thave %s\n\t\twant %s", - mname, altS, mS) + *cause = check.sprintf("(wrong type for %s)\n\t\thave %s\n\t\twant %s", + mname, altS, methodS) + return } if isInterfacePtr(V) { - return "(" + check.interfacePtrError(V) + ")" + *cause = "(" + check.interfacePtrError(V) + ")" + return } if isInterfacePtr(T) { - return "(" + check.interfacePtrError(T) + ")" + *cause = "(" + check.interfacePtrError(T) + ")" + return } - obj, _, _ := lookupFieldOrMethod(V, true /* auto-deref */, m.pkg, m.name, false) + obj, _, _ := lookupFieldOrMethod(V, true /* auto-deref */, method.pkg, method.name, false) if fld, _ := obj.(*Var); fld != nil { - return check.sprintf("(%s.%s is a field, not a method)", V, fld.Name()) + *cause = check.sprintf("(%s.%s is a field, not a method)", V, fld.Name()) + return } - return check.sprintf("(missing %s)", mname) + *cause = check.sprintf("(missing %s)", mname) + return } func isInterfacePtr(T Type) bool { diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 0959788899..66e28ee6cb 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -325,14 +325,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y return } - var alt *Func - if cause != nil { - defer func() { - if method != nil { - *cause = check.missingMethodCause(V, T, method, alt) - } - }() - } + var alt *Func // alternative method (pointer receiver or similar spelling) // V is an interface if u, _ := under(V).(*Interface); u != nil { @@ -344,16 +337,18 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y if !static { continue } - return m, false + method = m + goto Error } if !equivalent(f.typ, m.typ) { - alt = f - return m, true + method, alt = m, f + wrongType = true + goto Error } } - return + return nil, false } // V is not an interface @@ -374,7 +369,8 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y // we must have a method (not a struct field) f, _ := obj.(*Func) if f == nil { - return m, false + method = m + goto Error } // methods may not have a fully set up signature yet @@ -383,60 +379,63 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y } if !found || !equivalent(f.typ, m.typ) { - alt = f - return m, f.name == m.name + method, alt = m, f + wrongType = f.name == m.name + goto Error } } - return -} + return nil, false -// missingMethodCause returns a string giving the detailed cause for a missing method m, -// where m is missing from V, but required by T. It puts the cause in parentheses, -// and may include more have/want info after that. If non-nil, alt is a relevant -// method that matches in some way. It may have the correct name, but wrong type, or -// it may have a pointer receiver, or it may have the correct name except wrong case. -// check may be nil. -// missingMethodCause should only be called by missingMethod. -// TODO(gri) integrate this logic into missingMethod and get rid of this function. -func (check *Checker) missingMethodCause(V, T Type, m, alt *Func) string { - mname := "method " + m.Name() +Error: + if cause == nil { + return + } + + mname := "method " + method.Name() if alt != nil { - if m.Name() != alt.Name() { - return check.sprintf("(missing %s)\n\t\thave %s\n\t\twant %s", - mname, check.funcString(alt, false), check.funcString(m, false)) + if method.Name() != alt.Name() { + *cause = check.sprintf("(missing %s)\n\t\thave %s\n\t\twant %s", + mname, check.funcString(alt, false), check.funcString(method, false)) + return } - if Identical(m.typ, alt.typ) { - return check.sprintf("(%s has pointer receiver)", mname) + if Identical(method.typ, alt.typ) { + *cause = check.sprintf("(%s has pointer receiver)", mname) + return } - altS, mS := check.funcString(alt, false), check.funcString(m, false) - if altS == mS { + altS, methodS := check.funcString(alt, false), check.funcString(method, false) + if altS == methodS { // Would tell the user that Foo isn't a Foo, add package information to disambiguate. // See go.dev/issue/54258. - altS, mS = check.funcString(alt, true), check.funcString(m, true) + altS, methodS = check.funcString(alt, true), check.funcString(method, true) } - return check.sprintf("(wrong type for %s)\n\t\thave %s\n\t\twant %s", - mname, altS, mS) + *cause = check.sprintf("(wrong type for %s)\n\t\thave %s\n\t\twant %s", + mname, altS, methodS) + return } if isInterfacePtr(V) { - return "(" + check.interfacePtrError(V) + ")" + *cause = "(" + check.interfacePtrError(V) + ")" + return } if isInterfacePtr(T) { - return "(" + check.interfacePtrError(T) + ")" + *cause = "(" + check.interfacePtrError(T) + ")" + return } - obj, _, _ := lookupFieldOrMethod(V, true /* auto-deref */, m.pkg, m.name, false) + obj, _, _ := lookupFieldOrMethod(V, true /* auto-deref */, method.pkg, method.name, false) if fld, _ := obj.(*Var); fld != nil { - return check.sprintf("(%s.%s is a field, not a method)", V, fld.Name()) + *cause = check.sprintf("(%s.%s is a field, not a method)", V, fld.Name()) + return } - return check.sprintf("(missing %s)", mname) + *cause = check.sprintf("(missing %s)", mname) + return } func isInterfacePtr(T Type) bool {