mirror of
https://github.com/golang/go
synced 2024-11-21 18:44:45 -07:00
gc, spec, tests: no auto-indirect of pointer to interface value
Implies no embedding of pointer to interface value either. R=gri, iant, ken2, r, r2 CC=golang-dev https://golang.org/cl/2289041
This commit is contained in:
parent
6117652d8d
commit
bee2d5b0ad
@ -879,9 +879,10 @@ struct {
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<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
|
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
|
and <code>T</code> itself may not be
|
||||||
a pointer type. The unqualified type name acts as the field name.
|
a pointer type. The unqualified type name acts as the field name.
|
||||||
</p>
|
</p>
|
||||||
@ -2214,8 +2215,7 @@ x.f
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
denotes the field or method <code>f</code> of the value denoted by <code>x</code>
|
denotes the field or method <code>f</code> of the value denoted by <code>x</code>
|
||||||
(or of <code>*x</code> if
|
(or sometimes <code>*x</code>; see below). The identifier <code>f</code>
|
||||||
<code>x</code> is of pointer type). The identifier <code>f</code>
|
|
||||||
is called the (field or method)
|
is called the (field or method)
|
||||||
<i>selector</i>; it must not be the <a href="#Blank_identifier">blank identifier</a>.
|
<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>.
|
The type of the expression is the type of <code>f</code>.
|
||||||
@ -2258,16 +2258,13 @@ In all other cases, <code>x.f</code> is illegal.
|
|||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
<p>
|
<p>
|
||||||
Selectors automatically dereference pointers.
|
Selectors automatically dereference pointers to structs.
|
||||||
If <code>x</code> is of pointer type, <code>x.y</code>
|
If <code>x</code> is a pointer to a struct, <code>x.y</code>
|
||||||
is shorthand for <code>(*x).y</code>; if <code>y</code>
|
is shorthand for <code>(*x).y</code>; if the field <code>y</code>
|
||||||
is also of pointer type, <code>x.y.z</code> is shorthand
|
is also a pointer to a struct, <code>x.y.z</code> is shorthand
|
||||||
for <code>(*(*x).y).z</code>, and so on.
|
for <code>(*(*x).y).z</code>, and so on.
|
||||||
If <code>*x</code> is of pointer type, dereferencing
|
If <code>x</code> contains an anonymous field of type <code>*A</code>,
|
||||||
must be explicit;
|
where <code>A</code> is also a struct type,
|
||||||
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>,
|
|
||||||
<code>x.f</code> is a shortcut for <code>(*x.A).f</code>.
|
<code>x.f</code> is a shortcut for <code>(*x.A).f</code>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -729,8 +729,11 @@ stotype(NodeList *l, int et, Type **t)
|
|||||||
n->right = N;
|
n->right = N;
|
||||||
if(n->embedded && n->type != T) {
|
if(n->embedded && n->type != T) {
|
||||||
t1 = n->type;
|
t1 = n->type;
|
||||||
if(t1->sym == S && isptr[t1->etype])
|
if(t1->sym == S && isptr[t1->etype]) {
|
||||||
t1 = t1->type;
|
t1 = t1->type;
|
||||||
|
if(t1->etype == TINTER)
|
||||||
|
yyerror("embedded type cannot be a pointer to interface");
|
||||||
|
}
|
||||||
if(isptr[t1->etype])
|
if(isptr[t1->etype])
|
||||||
yyerror("embedded type cannot be a pointer");
|
yyerror("embedded type cannot be a pointer");
|
||||||
else if(t1->etype == TFORW && t1->embedlineno == 0)
|
else if(t1->etype == TFORW && t1->embedlineno == 0)
|
||||||
|
@ -286,15 +286,6 @@ imethods(Type *t)
|
|||||||
oldlist = pc;
|
oldlist = pc;
|
||||||
genwrapper(t, f, isym, 0);
|
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) {
|
if(oldlist) {
|
||||||
|
@ -520,7 +520,7 @@ reswitch:
|
|||||||
ok = Erv;
|
ok = Erv;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
if(isptr[t->etype]) {
|
if(isptr[t->etype] && t->type->etype != TINTER) {
|
||||||
t = t->type;
|
t = t->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -21,7 +21,7 @@ func ASSERT(p bool) {
|
|||||||
|
|
||||||
type KeyType interface {
|
type KeyType interface {
|
||||||
Hash() uint32
|
Hash() uint32
|
||||||
Match(other *KeyType) bool
|
Match(other KeyType) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -31,8 +31,8 @@ type ValueType interface {
|
|||||||
|
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
key *KeyType
|
key KeyType
|
||||||
value *ValueType
|
value ValueType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ func (m *HashMap) Initialize (initial_log2_capacity uint32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m *HashMap) Probe (key *KeyType) *Entry {
|
func (m *HashMap) Probe (key KeyType) *Entry {
|
||||||
ASSERT(key != nil)
|
ASSERT(key != nil)
|
||||||
|
|
||||||
var i uint32 = key.Hash() % m.capacity()
|
var i uint32 = key.Hash() % m.capacity()
|
||||||
@ -86,7 +86,7 @@ func (m *HashMap) Probe (key *KeyType) *Entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (m *HashMap) Lookup (key *KeyType, insert bool) *Entry {
|
func (m *HashMap) Lookup (key KeyType, insert bool) *Entry {
|
||||||
// Find a matching entry.
|
// Find a matching entry.
|
||||||
var p *Entry = m.Probe(key)
|
var p *Entry = m.Probe(key)
|
||||||
if p.key != nil {
|
if p.key != nil {
|
||||||
@ -145,7 +145,7 @@ func (n *Number) Hash() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (n *Number) Match(other *KeyType) bool {
|
func (n *Number) Match(other KeyType) bool {
|
||||||
// var y *Number = other
|
// var y *Number = other
|
||||||
// return n.x == y.x
|
// return n.x == y.x
|
||||||
return false
|
return false
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
package main
|
||||||
|
|
||||||
@ -19,18 +19,12 @@ func (t T) M() int64 { return int64(t) }
|
|||||||
var t = T(Value)
|
var t = T(Value)
|
||||||
var pt = &t
|
var pt = &t
|
||||||
var ti Inter = t
|
var ti Inter = t
|
||||||
var pti = &ti
|
|
||||||
|
|
||||||
type S struct { Inter }
|
type S struct { Inter }
|
||||||
var s = S{ ti }
|
var s = S{ ti }
|
||||||
var ps = &s
|
var ps = &s
|
||||||
|
|
||||||
type SP struct { *Inter }
|
|
||||||
var sp = SP{ &ti }
|
|
||||||
var psp = &sp
|
|
||||||
|
|
||||||
var i Inter
|
var i Inter
|
||||||
var pi = &i
|
|
||||||
|
|
||||||
var ok = true
|
var ok = true
|
||||||
|
|
||||||
@ -45,35 +39,20 @@ func main() {
|
|||||||
check("t.M()", t.M())
|
check("t.M()", t.M())
|
||||||
check("pt.M()", pt.M())
|
check("pt.M()", pt.M())
|
||||||
check("ti.M()", ti.M())
|
check("ti.M()", ti.M())
|
||||||
check("pti.M()", pti.M())
|
|
||||||
check("s.M()", s.M())
|
check("s.M()", s.M())
|
||||||
check("ps.M()", ps.M())
|
check("ps.M()", ps.M())
|
||||||
check("sp.M()", sp.M())
|
|
||||||
check("psp.M()", psp.M())
|
|
||||||
|
|
||||||
i = t
|
i = t
|
||||||
check("i = t; i.M()", i.M())
|
check("i = t; i.M()", i.M())
|
||||||
check("i = t; pi.M()", pi.M())
|
|
||||||
|
|
||||||
i = pt
|
i = pt
|
||||||
check("i = pt; i.M()", i.M())
|
check("i = pt; i.M()", i.M())
|
||||||
check("i = pt; pi.M()", pi.M())
|
|
||||||
|
|
||||||
i = s
|
i = s
|
||||||
check("i = s; i.M()", i.M())
|
check("i = s; i.M()", i.M())
|
||||||
check("i = s; pi.M()", pi.M())
|
|
||||||
|
|
||||||
i = ps
|
i = ps
|
||||||
check("i = ps; i.M()", i.M())
|
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 {
|
if !ok {
|
||||||
println("BUG: interface10")
|
println("BUG: interface10")
|
||||||
|
70
test/interface/embed2.go
Normal file
70
test/interface/embed2.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
@ -124,9 +124,4 @@ func main() {
|
|||||||
println("Val.val(v):", Val.val(v))
|
println("Val.val(v):", Val.val(v))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
pv := &v
|
|
||||||
if pv.val() != 3 {
|
|
||||||
println("pv.val():", pv.val())
|
|
||||||
panic("fail")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,3 +20,8 @@ type Val interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _ = (*Val).val // ERROR "method"
|
var _ = (*Val).val // ERROR "method"
|
||||||
|
|
||||||
|
var v Val
|
||||||
|
var pv = &v
|
||||||
|
|
||||||
|
var _ = pv.val() // ERROR "method"
|
||||||
|
Loading…
Reference in New Issue
Block a user