mirror of
https://github.com/golang/go
synced 2024-11-19 03:44:40 -07:00
cmd/compile: stop generating garbage when checking map key types
Change-Id: Ib500ee92ae1a3d15f7c9f3f46d238b75184b4304 Reviewed-on: https://go-review.googlesource.com/21382 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
00289c296c
commit
7c4d53c2c8
@ -3018,7 +3018,7 @@ func (p *parser) hidden_type_misc() *Type {
|
|||||||
p.want(']')
|
p.want(']')
|
||||||
s5 := p.hidden_type()
|
s5 := p.hidden_type()
|
||||||
|
|
||||||
return maptype(s3, s5)
|
return typMap(s3, s5)
|
||||||
|
|
||||||
case LSTRUCT:
|
case LSTRUCT:
|
||||||
// LSTRUCT '{' ohidden_structdcl_list '}'
|
// LSTRUCT '{' ohidden_structdcl_list '}'
|
||||||
|
@ -372,40 +372,37 @@ func saveorignode(n *Node) {
|
|||||||
n.Orig = norig
|
n.Orig = norig
|
||||||
}
|
}
|
||||||
|
|
||||||
func maptype(key *Type, val *Type) *Type {
|
// checkMapKeyType checks that Type key is valid for use as a map key.
|
||||||
if key != nil {
|
func checkMapKeyType(key *Type) {
|
||||||
var bad *Type
|
var bad *Type
|
||||||
atype := algtype1(key, &bad)
|
atype := algtype1(key, &bad)
|
||||||
var mtype EType
|
var mtype EType
|
||||||
if bad == nil {
|
if bad == nil {
|
||||||
mtype = key.Etype
|
mtype = key.Etype
|
||||||
} else {
|
} else {
|
||||||
mtype = bad.Etype
|
mtype = bad.Etype
|
||||||
|
}
|
||||||
|
switch mtype {
|
||||||
|
default:
|
||||||
|
if atype == ANOEQ {
|
||||||
|
Yyerror("invalid map key type %v", key)
|
||||||
}
|
}
|
||||||
switch mtype {
|
|
||||||
default:
|
|
||||||
if atype == ANOEQ {
|
|
||||||
Yyerror("invalid map key type %v", key)
|
|
||||||
}
|
|
||||||
|
|
||||||
case TANY:
|
case TANY:
|
||||||
// will be resolved later.
|
// will be resolved later.
|
||||||
break
|
break
|
||||||
|
|
||||||
case TFORW:
|
case TFORW:
|
||||||
// map[key] used during definition of key.
|
// map[key] used during definition of key.
|
||||||
// postpone check until key is fully defined.
|
// postpone check until key is fully defined.
|
||||||
// if there are multiple uses of map[key]
|
// if there are multiple uses of map[key]
|
||||||
// before key is fully defined, the error
|
// before key is fully defined, the error
|
||||||
// will only be printed for the first one.
|
// will only be printed for the first one.
|
||||||
// good enough.
|
// good enough.
|
||||||
if key.Maplineno == 0 {
|
if key.Maplineno == 0 {
|
||||||
key.Maplineno = lineno
|
key.Maplineno = lineno
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return typMap(key, val)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// methcmp sorts by symbol, then by package path for unexported symbols.
|
// methcmp sorts by symbol, then by package path for unexported symbols.
|
||||||
|
@ -275,6 +275,10 @@ func typChan(elem *Type, dir uint8) *Type {
|
|||||||
|
|
||||||
// typMap returns a new map Type with key type k and element (aka value) type v.
|
// typMap returns a new map Type with key type k and element (aka value) type v.
|
||||||
func typMap(k, v *Type) *Type {
|
func typMap(k, v *Type) *Type {
|
||||||
|
if k != nil {
|
||||||
|
checkMapKeyType(k)
|
||||||
|
}
|
||||||
|
|
||||||
t := typ(TMAP)
|
t := typ(TMAP)
|
||||||
t.Down = k
|
t.Down = k
|
||||||
t.Type = v
|
t.Type = v
|
||||||
|
@ -402,7 +402,7 @@ OpSwitch:
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
n.Op = OTYPE
|
n.Op = OTYPE
|
||||||
n.Type = maptype(l.Type, r.Type)
|
n.Type = typMap(l.Type, r.Type)
|
||||||
n.Left = nil
|
n.Left = nil
|
||||||
n.Right = nil
|
n.Right = nil
|
||||||
|
|
||||||
@ -3595,7 +3595,7 @@ ret:
|
|||||||
|
|
||||||
for _, n := range mapqueue {
|
for _, n := range mapqueue {
|
||||||
lineno = n.Type.Maplineno
|
lineno = n.Type.Maplineno
|
||||||
maptype(n.Type, Types[TBOOL])
|
checkMapKeyType(n.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
lineno = lno
|
lineno = lno
|
||||||
|
Loading…
Reference in New Issue
Block a user