</pre>
<p>
-A field declared with a type but no explicit field name is an <i>anonymous field</i>.
+A field declared with a type but no explicit field name is an <i>anonymous field</i>
+(colloquially called an embedded field).
Such a field type must be specified as
-a type name <code>T</code> or as a pointer to a type name <code>*T</code>,
+a type name <code>T</code> or as a pointer to a non-interface type name <code>*T</code>,
and <code>T</code> itself may not be
a pointer type. The unqualified type name acts as the field name.
</p>
<p>
denotes the field or method <code>f</code> of the value denoted by <code>x</code>
-(or of <code>*x</code> if
-<code>x</code> is of pointer type). The identifier <code>f</code>
+(or sometimes <code>*x</code>; see below). The identifier <code>f</code>
is called the (field or method)
<i>selector</i>; it must not be the <a href="#Blank_identifier">blank identifier</a>.
The type of the expression is the type of <code>f</code>.
</li>
</ol>
<p>
-Selectors automatically dereference pointers.
-If <code>x</code> is of pointer type, <code>x.y</code>
-is shorthand for <code>(*x).y</code>; if <code>y</code>
-is also of pointer type, <code>x.y.z</code> is shorthand
+Selectors automatically dereference pointers to structs.
+If <code>x</code> is a pointer to a struct, <code>x.y</code>
+is shorthand for <code>(*x).y</code>; if the field <code>y</code>
+is also a pointer to a struct, <code>x.y.z</code> is shorthand
for <code>(*(*x).y).z</code>, and so on.
-If <code>*x</code> is of pointer type, dereferencing
-must be explicit;
-only one level of automatic dereferencing is provided.
-For an <code>x</code> of type <code>T</code> containing an
-anonymous field declared as <code>*A</code>,
+If <code>x</code> contains an anonymous field of type <code>*A</code>,
+where <code>A</code> is also a struct type,
<code>x.f</code> is a shortcut for <code>(*x.A).f</code>.
</p>
<p>
n->right = N;
if(n->embedded && n->type != T) {
t1 = n->type;
- if(t1->sym == S && isptr[t1->etype])
+ if(t1->sym == S && isptr[t1->etype]) {
t1 = t1->type;
+ if(t1->etype == TINTER)
+ yyerror("embedded type cannot be a pointer to interface");
+ }
if(isptr[t1->etype])
yyerror("embedded type cannot be a pointer");
else if(t1->etype == TFORW && t1->embedlineno == 0)
oldlist = pc;
genwrapper(t, f, isym, 0);
}
-
- // Generate wrapper for pointer to interface type.
- isym = methodsym(method, ptrto(t), 0);
- if(!(isym->flags & SymSiggen)) {
- isym->flags |= SymSiggen;
- if(oldlist == nil)
- oldlist = pc;
- genwrapper(ptrto(t), f, isym, 0);
- }
}
if(oldlist) {
ok = Erv;
goto ret;
}
- if(isptr[t->etype]) {
+ if(isptr[t->etype] && t->type->etype != TINTER) {
t = t->type;
if(t == T)
goto error;
type KeyType interface {
Hash() uint32
- Match(other *KeyType) bool
+ Match(other KeyType) bool
}
type Entry struct {
- key *KeyType
- value *ValueType
+ key KeyType
+ value ValueType
}
}
-func (m *HashMap) Probe (key *KeyType) *Entry {
+func (m *HashMap) Probe (key KeyType) *Entry {
ASSERT(key != nil)
var i uint32 = key.Hash() % m.capacity()
}
-func (m *HashMap) Lookup (key *KeyType, insert bool) *Entry {
+func (m *HashMap) Lookup (key KeyType, insert bool) *Entry {
// Find a matching entry.
var p *Entry = m.Probe(key)
if p.key != nil {
}
-func (n *Number) Match(other *KeyType) bool {
+func (n *Number) Match(other KeyType) bool {
// var y *Number = other
// return n.x == y.x
return false
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Check methods derived from embedded interface and *interface values.
+// Check methods derived from embedded interface values.
package main
var t = T(Value)
var pt = &t
var ti Inter = t
-var pti = &ti
type S struct { Inter }
var s = S{ ti }
var ps = &s
-type SP struct { *Inter }
-var sp = SP{ &ti }
-var psp = &sp
-
var i Inter
-var pi = &i
var ok = true
check("t.M()", t.M())
check("pt.M()", pt.M())
check("ti.M()", ti.M())
- check("pti.M()", pti.M())
check("s.M()", s.M())
check("ps.M()", ps.M())
- check("sp.M()", sp.M())
- check("psp.M()", psp.M())
i = t
check("i = t; i.M()", i.M())
- check("i = t; pi.M()", pi.M())
i = pt
check("i = pt; i.M()", i.M())
- check("i = pt; pi.M()", pi.M())
i = s
check("i = s; i.M()", i.M())
- check("i = s; pi.M()", pi.M())
i = ps
check("i = ps; i.M()", i.M())
- check("i = ps; pi.M()", pi.M())
-
- i = sp
- check("i = sp; i.M()", i.M())
- check("i = sp; pi.M()", pi.M())
-
- i = psp
- check("i = psp; i.M()", i.M())
- check("i = psp; pi.M()", pi.M())
if !ok {
println("BUG: interface10")
--- /dev/null
+// errchk $G -e $D/$F.go
+
+// Copyright 2009 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.
+
+// Check methods derived from embedded interface and *interface values.
+
+package main
+
+import "os"
+
+const Value = 1e12
+
+type Inter interface { M() int64 }
+
+type T int64
+func (t T) M() int64 { return int64(t) }
+var t = T(Value)
+var pt = &t
+var ti Inter = t
+var pti = &ti
+
+type S struct { Inter }
+var s = S{ ti }
+var ps = &s
+
+type SP struct { *Inter } // ERROR "interface"
+
+var i Inter
+var pi = &i
+
+var ok = true
+
+func check(s string, v int64) {
+ if v != Value {
+ println(s, v)
+ ok = false
+ }
+}
+
+func main() {
+ check("t.M()", t.M())
+ check("pt.M()", pt.M())
+ check("ti.M()", ti.M())
+ check("pti.M()", pti.M()) // ERROR "method"
+ check("s.M()", s.M())
+ check("ps.M()", ps.M())
+
+ i = t
+ check("i = t; i.M()", i.M())
+ check("i = t; pi.M()", pi.M()) // ERROR "method"
+
+ i = pt
+ check("i = pt; i.M()", i.M())
+ check("i = pt; pi.M()", pi.M()) // ERROR "method"
+
+ i = s
+ check("i = s; i.M()", i.M())
+ check("i = s; pi.M()", pi.M()) // ERROR "method"
+
+ i = ps
+ check("i = ps; i.M()", i.M())
+ check("i = ps; pi.M()", pi.M()) // ERROR "method"
+
+ if !ok {
+ println("BUG: interface10")
+ os.Exit(1)
+ }
+}
println("Val.val(v):", Val.val(v))
panic("fail")
}
- pv := &v
- if pv.val() != 3 {
- println("pv.val():", pv.val())
- panic("fail")
- }
}
}
var _ = (*Val).val // ERROR "method"
+
+var v Val
+var pv = &v
+
+var _ = pv.val() // ERROR "method"