yyerror("%v undefined (cannot refer to unexported field or method %v)", n, n.Sym)
default:
- if mt := lookdot(n, t, 2); mt != nil { // Case-insensitive lookup.
+ if mt := lookdot(n, t, 2); mt != nil && visible(mt.Sym) { // Case-insensitive lookup.
yyerror("%v undefined (type %v has no field or method %v, but does have %v)", n, n.Left.Type, n.Sym, mt.Sym)
} else {
yyerror("%v undefined (type %v has no field or method %v)", n, n.Left.Type, n.Sym)
f := lookdot1(nil, l.Sym, t, t.Fields(), 0)
if f == nil {
if ci := lookdot1(nil, l.Sym, t, t.Fields(), 2); ci != nil { // Case-insensitive lookup.
- yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym)
+ if visible(ci.Sym) {
+ yyerror("unknown field '%v' in struct literal of type %v (but does have %v)", l.Sym, t, ci.Sym)
+ } else {
+ yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t)
+ }
continue
}
p, _ := dotpath(l.Sym, t, nil, true)
return n
}
+// visible reports whether sym is exported or locally defined.
+func visible(sym *types.Sym) bool {
+ return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == localpkg)
+}
+
// lvalue etc
func islvalue(n *Node) bool {
switch n.Op {
--- /dev/null
+// errorcheck
+
+// Copyright 2018 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 main
+
+import "net/http"
+
+var s = http.Server{}
+var _ = s.doneChan // ERROR "s.doneChan undefined .cannot refer to unexported field or method doneChan.$"
+var _ = s.DoneChan // ERROR "s.DoneChan undefined .type http.Server has no field or method DoneChan.$"
+var _ = http.Server{tlsConfig: nil} // ERROR "unknown field 'tlsConfig' in struct literal.+ .but does have TLSConfig.$"
+var _ = http.Server{DoneChan: nil} // ERROR "unknown field 'DoneChan' in struct literal of type http.Server$"
+
+type foo struct {
+ bar int
+}
+
+var _ = &foo{bAr: 10} // ERROR "unknown field 'bAr' in struct literal.+ .but does have bar.$"