Skip to content

Commit ed647b1

Browse files
committed
[dev.typeparams] cmd/compile: use Type.LinkString for map keys
This CL changes typecheck and order to use Type.LinkString for computing map keys instead of Type.NameString. As mentioned in the LinkString docs (added by the previous CL), LinkString reliably maps type identity to string equality as long as the LinkString calls all happen within the same compilation unit (which they do here). This eliminates the need for subsequent types.Identical checks. Change-Id: I32ff591e69d6f23f2dc6ebd5af343618ebe89013 Reviewed-on: https://go-review.googlesource.com/c/go/+/330911 Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Go Bot <[email protected]> Trust: Matthew Dempsky <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 942edc7 commit ed647b1

File tree

3 files changed

+23
-35
lines changed

3 files changed

+23
-35
lines changed

src/cmd/compile/internal/reflectdata/reflect.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ func WriteBasicTypes() {
13881388

13891389
type typeAndStr struct {
13901390
t *types.Type
1391-
short string
1391+
short string // "short" here means NameString
13921392
regular string
13931393
}
13941394

@@ -1401,8 +1401,13 @@ func (a typesByString) Less(i, j int) bool {
14011401
}
14021402
// When the only difference between the types is whether
14031403
// they refer to byte or uint8, such as **byte vs **uint8,
1404-
// the types' ShortStrings can be identical.
1404+
// the types' NameStrings can be identical.
14051405
// To preserve deterministic sort ordering, sort these by String().
1406+
//
1407+
// TODO(mdempsky): This all seems suspect. Using LinkString would
1408+
// avoid naming collisions, and there shouldn't be a reason to care
1409+
// about "byte" vs "uint8": they share the same runtime type
1410+
// descriptor anyway.
14061411
if a[i].regular != a[j].regular {
14071412
return a[i].regular < a[j].regular
14081413
}

src/cmd/compile/internal/typecheck/stmt.go

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -662,29 +662,18 @@ func tcSwitchType(n *ir.SwitchStmt) {
662662
}
663663

664664
type typeSet struct {
665-
m map[string][]typeSetEntry
666-
}
667-
668-
type typeSetEntry struct {
669-
pos src.XPos
670-
typ *types.Type
665+
m map[string]src.XPos
671666
}
672667

673668
func (s *typeSet) add(pos src.XPos, typ *types.Type) {
674669
if s.m == nil {
675-
s.m = make(map[string][]typeSetEntry)
670+
s.m = make(map[string]src.XPos)
676671
}
677672

678-
// LongString does not uniquely identify types, so we need to
679-
// disambiguate collisions with types.Identical.
680-
// TODO(mdempsky): Add a method that *is* unique.
681-
ls := typ.NameString()
682-
prevs := s.m[ls]
683-
for _, prev := range prevs {
684-
if types.Identical(typ, prev.typ) {
685-
base.ErrorfAt(pos, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev.pos))
686-
return
687-
}
673+
ls := typ.LinkString()
674+
if prev, ok := s.m[ls]; ok {
675+
base.ErrorfAt(pos, "duplicate case %v in type switch\n\tprevious case at %s", typ, base.FmtPos(prev))
676+
return
688677
}
689-
s.m[ls] = append(prevs, typeSetEntry{pos, typ})
678+
s.m[ls] = pos
690679
}

src/cmd/compile/internal/walk/order.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import (
5151
type orderState struct {
5252
out []ir.Node // list of generated statements
5353
temp []*ir.Name // stack of temporary variables
54-
free map[string][]*ir.Name // free list of unused temporaries, by type.LongString().
54+
free map[string][]*ir.Name // free list of unused temporaries, by type.LinkString().
5555
edit func(ir.Node) ir.Node // cached closure of o.exprNoLHS
5656
}
5757

@@ -76,20 +76,14 @@ func (o *orderState) append(stmt ir.Node) {
7676
// If clear is true, newTemp emits code to zero the temporary.
7777
func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name {
7878
var v *ir.Name
79-
// Note: LongString is close to the type equality we want,
80-
// but not exactly. We still need to double-check with types.Identical.
81-
key := t.NameString()
82-
a := o.free[key]
83-
for i, n := range a {
84-
if types.Identical(t, n.Type()) {
85-
v = a[i]
86-
a[i] = a[len(a)-1]
87-
a = a[:len(a)-1]
88-
o.free[key] = a
89-
break
79+
key := t.LinkString()
80+
if a := o.free[key]; len(a) > 0 {
81+
v = a[len(a)-1]
82+
if !types.Identical(t, v.Type()) {
83+
base.Fatalf("expected %L to have type %v", v, t)
9084
}
91-
}
92-
if v == nil {
85+
o.free[key] = a[:len(a)-1]
86+
} else {
9387
v = typecheck.Temp(t)
9488
}
9589
if clear {
@@ -370,7 +364,7 @@ func (o *orderState) markTemp() ordermarker {
370364
// which must have been returned by markTemp.
371365
func (o *orderState) popTemp(mark ordermarker) {
372366
for _, n := range o.temp[mark:] {
373-
key := n.Type().NameString()
367+
key := n.Type().LinkString()
374368
o.free[key] = append(o.free[key], n)
375369
}
376370
o.temp = o.temp[:mark]

0 commit comments

Comments
 (0)