Skip to content

Commit f011e0c

Browse files
committed
[dev.typealias] cmd/compile, go/types, go/importer: various alias related fixes
cmd/compile: - remove crud from prior alias implementation - better comments in places go/types: - fix TypeName.IsAlias predicate - more tests go/importer (go/internal/gcimporter15): - handle "@" format for anonymous fields using aliases (currently tested indirectly via x/tools/gcimporter15 tests) For #18130. Change-Id: I23a6d4e3a4c2a5c1ae589513da73fde7cad5f386 Reviewed-on: https://go-review.googlesource.com/35101 Reviewed-by: Alan Donovan <[email protected]>
1 parent 49de5f0 commit f011e0c

File tree

5 files changed

+53
-72
lines changed

5 files changed

+53
-72
lines changed

src/cmd/compile/internal/gc/bexport.go

+6-31
Original file line numberDiff line numberDiff line change
@@ -447,30 +447,6 @@ func unidealType(typ *Type, val Val) *Type {
447447
}
448448

449449
func (p *exporter) obj(sym *Sym) {
450-
if sym.Flags&SymAlias != 0 {
451-
p.tag(aliasTag)
452-
p.pos(nil) // TODO(gri) fix position information
453-
// Aliases can only be exported from the package that
454-
// declares them (aliases to aliases are resolved to the
455-
// original object, and so are uses of aliases in inlined
456-
// exported function bodies). Thus, we only need the alias
457-
// name without package qualification.
458-
if sym.Pkg != localpkg {
459-
Fatalf("exporter: export of non-local alias: %v", sym)
460-
}
461-
p.string(sym.Name)
462-
orig := sym.Def.Sym
463-
if orig.Flags&SymAlias != 0 {
464-
Fatalf("exporter: original object %v marked as alias", sym)
465-
}
466-
p.qualifiedName(orig)
467-
return
468-
}
469-
470-
if sym != sym.Def.Sym {
471-
Fatalf("exporter: exported object %v is not original %v", sym, sym.Def.Sym)
472-
}
473-
474450
// Exported objects may be from different packages because they
475451
// may be re-exported via an exported alias or as dependencies in
476452
// exported inlined function bodies. Thus, exported object names
@@ -885,15 +861,15 @@ func (p *exporter) fieldName(t *Field) {
885861
name := t.Sym.Name
886862
if t.Embedded != 0 {
887863
// anonymous field - we distinguish between 3 cases:
888-
// 1) field name matches base type name and name is exported
889-
// 2) field name matches base type name and name is not exported
890-
// 3) field name doesn't match base type name (type name is alias)
864+
// 1) field name matches base type name and is exported
865+
// 2) field name matches base type name and is not exported
866+
// 3) field name doesn't match base type name (alias name)
891867
bname := basetypeName(t.Type)
892868
if name == bname {
893869
if exportname(name) {
894-
name = "" // 1) we don't need to know the name
870+
name = "" // 1) we don't need to know the field name or package
895871
} else {
896-
name = "?" // 2) use unexported name to force package export
872+
name = "?" // 2) use unexported name "?" to force package export
897873
}
898874
} else {
899875
// 3) indicate alias and export name as is
@@ -920,11 +896,10 @@ func basetypeName(t *Type) string {
920896
if s == nil && t.IsPtr() {
921897
s = t.Elem().Sym // deref
922898
}
923-
// s should exist, but be conservative
924899
if s != nil {
925900
return s.Name
926901
}
927-
return ""
902+
return "" // unnamed type
928903
}
929904

930905
func (p *exporter) paramList(params *Type, numbered bool) {

src/cmd/compile/internal/gc/bimport.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -582,14 +582,15 @@ func (p *importer) field() *Field {
582582

583583
f := newField()
584584
if sym.Name == "" {
585-
// anonymous field - typ must be T or *T and T must be a type name
585+
// anonymous field: typ must be T or *T and T must be a type name
586586
s := typ.Sym
587587
if s == nil && typ.IsPtr() {
588588
s = typ.Elem().Sym // deref
589589
}
590590
sym = sym.Pkg.Lookup(s.Name)
591591
f.Embedded = 1
592592
} else if sym.Flags&SymAlias != 0 {
593+
// anonymous field: we have an explicit name because it's an alias
593594
f.Embedded = 1
594595
}
595596

@@ -635,13 +636,13 @@ func (p *importer) fieldName() *Sym {
635636
var flag SymFlags
636637
switch name {
637638
case "":
638-
// field name is exported - nothing to do
639+
// 1) field name matches base type name and is exported: nothing to do
639640
case "?":
640-
// field name is not exported - need package
641+
// 2) field name matches base type name and is not exported: need package
641642
name = ""
642643
pkg = p.pkg()
643644
case "@":
644-
// field name doesn't match type name (alias)
645+
// 3) field name doesn't match base type name (alias name): need name and possibly package
645646
name = p.string()
646647
flag = SymAlias
647648
fallthrough

src/go/internal/gcimporter/bimport.go

+16-14
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,7 @@ var (
341341

342342
func (p *importer) qualifiedName() (pkg *types.Package, name string) {
343343
name = p.string()
344-
if name != "" {
345-
pkg = p.pkg()
346-
}
344+
pkg = p.pkg()
347345
return
348346
}
349347

@@ -556,7 +554,7 @@ func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags [
556554

557555
func (p *importer) field(parent *types.Package) (*types.Var, string) {
558556
pos := p.pos()
559-
pkg, name := p.fieldName(parent)
557+
pkg, name, alias := p.fieldName(parent)
560558
typ := p.typ(parent)
561559
tag := p.string()
562560

@@ -570,9 +568,12 @@ func (p *importer) field(parent *types.Package) (*types.Var, string) {
570568
case *types.Named:
571569
name = typ.Obj().Name()
572570
default:
573-
errorf("anonymous field expected")
571+
errorf("named base type expected")
574572
}
575573
anonymous = true
574+
} else if alias {
575+
// anonymous field: we have an explicit name because it's an alias
576+
anonymous = true
576577
}
577578

578579
return types.NewField(pos, pkg, name, typ, anonymous), tag
@@ -590,41 +591,42 @@ func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
590591

591592
func (p *importer) method(parent *types.Package) *types.Func {
592593
pos := p.pos()
593-
pkg, name := p.fieldName(parent)
594+
pkg, name, _ := p.fieldName(parent)
594595
params, isddd := p.paramList()
595596
result, _ := p.paramList()
596597
sig := types.NewSignature(nil, params, result, isddd)
597598
return types.NewFunc(pos, pkg, name, sig)
598599
}
599600

600-
func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
601-
name := p.string()
602-
pkg := parent
601+
func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
602+
name = p.string()
603+
pkg = parent
603604
if pkg == nil {
604605
// use the imported package instead
605606
pkg = p.pkgList[0]
606607
}
607608
if p.version == 0 && name == "_" {
608609
// version 0 didn't export a package for _ fields
609-
return pkg, name
610+
return
610611
}
611612
switch name {
612613
case "":
613-
// field name is exported - nothing to do
614+
// 1) field name matches base type name and is exported: nothing to do
614615
case "?":
615-
// field name is not exported - need package
616+
// 2) field name matches base type name and is not exported: need package
616617
name = ""
617618
pkg = p.pkg()
618619
case "@":
619-
// field name doesn't match type name (alias)
620+
// 3) field name doesn't match type name (alias)
620621
name = p.string()
622+
alias = true
621623
fallthrough
622624
default:
623625
if !exported(name) {
624626
pkg = p.pkg()
625627
}
626628
}
627-
return pkg, name
629+
return
628630
}
629631

630632
func (p *importer) paramList() (*types.Tuple, bool) {

src/go/types/object.go

+8-12
Original file line numberDiff line numberDiff line change
@@ -163,23 +163,19 @@ func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
163163
return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
164164
}
165165

166+
// IsAlias reports whether obj is an alias name for a type.
166167
func (obj *TypeName) IsAlias() bool {
167168
switch t := obj.typ.(type) {
168169
case nil:
169170
return false
170171
case *Basic:
171-
// It would seem that we should be able to look for different names here;
172-
// but the names of universeByte/Rune are "byte" and "rune", respectively.
173-
// We do this so that we get better error messages. However, general alias
174-
// types don't have that name information and thus behave differently when
175-
// reporting errors (we won't see the alias name, only the original name).
176-
// Maybe we should remove the special handling for the predeclared types
177-
// as well to be consistent (at the cost of slightly less clear error
178-
// messages when byte/rune are involved).
179-
// This also plays out in the implementation of the Identical(Type, Type)
180-
// predicate.
181-
// TODO(gri) consider possible clean up
182-
return t == universeByte || t == universeRune
172+
// Any user-defined type name for a basic type is an alias for a
173+
// basic type (because basic types are pre-declared in the Universe
174+
// scope, outside any package scope), and so is any type name with
175+
// a different name than the name of the basic type it refers to.
176+
// Additionaly, we need to look for "byte" and "rune" because they
177+
// are aliases but have the same names (for better error messages).
178+
return obj.pkg != nil || t.name != obj.name || t == universeByte || t == universeRune
183179
case *Named:
184180
return obj != t.obj
185181
default:

src/go/types/object_test.go

+18-11
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,23 @@ func TestIsAlias(t *testing.T) {
2121
}
2222

2323
// various other types
24-
t0 := NewTypeName(0, nil, "t0", nil)
25-
check(t0, false) // no type yet
26-
27-
t1 := NewTypeName(0, nil, "t1", nil)
24+
pkg := NewPackage("p", "p")
25+
t1 := NewTypeName(0, pkg, "t1", nil)
2826
n1 := NewNamed(t1, new(Struct), nil)
29-
check(t1, false) // type name refers to named type and vice versa
30-
31-
t2 := NewTypeName(0, nil, "t2", new(Interface))
32-
check(t2, true) // type name refers to unnamed type
33-
34-
t3 := NewTypeName(0, nil, "t3", n1)
35-
check(t3, true) // type name refers to named type with different type name (true alias)
27+
for _, test := range []struct {
28+
name *TypeName
29+
alias bool
30+
}{
31+
{NewTypeName(0, nil, "t0", nil), false}, // no type yet
32+
{NewTypeName(0, pkg, "t0", nil), false}, // no type yet
33+
{t1, false}, // type name refers to named type and vice versa
34+
{NewTypeName(0, nil, "t2", new(Interface)), true}, // type name refers to unnamed type
35+
{NewTypeName(0, pkg, "t3", n1), true}, // type name refers to named type with different type name
36+
{NewTypeName(0, nil, "t4", Typ[Int32]), true}, // type name refers to basic type with different name
37+
{NewTypeName(0, nil, "int32", Typ[Int32]), false}, // type name refers to basic type with same name
38+
{NewTypeName(0, pkg, "int32", Typ[Int32]), true}, // type name is declared in user-defined package (outside Universe)
39+
{NewTypeName(0, nil, "rune", Typ[Rune]), true}, // type name refers to basic type rune which is an alias already
40+
} {
41+
check(test.name, test.alias)
42+
}
3643
}

0 commit comments

Comments
 (0)