mirror of
https://github.com/golang/go.git
synced 2025-05-06 08:03:03 +00:00
cmd/compile: import/export of alias declarations
This CL completes support for alias declarations in the compiler. Also: - increased export format version - updated various comments For #16339. Fixes #17487. Change-Id: Ic6945fc44c0041771eaf9dcfe973f601d14de069 Reviewed-on: https://go-review.googlesource.com/32090 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
81038d2e2b
commit
03d81b5ed9
@ -9,10 +9,12 @@
|
|||||||
1) Export data encoding principles:
|
1) Export data encoding principles:
|
||||||
|
|
||||||
The export data is a serialized description of the graph of exported
|
The export data is a serialized description of the graph of exported
|
||||||
"objects": constants, types, variables, and functions. In general,
|
"objects": constants, types, variables, and functions. Aliases may be
|
||||||
types - but also objects referred to from inlined function bodies -
|
directly reexported, and unaliased types may be indirectly reexported
|
||||||
can be reexported and so we need to know which package they are coming
|
(as part of the type of a directly exorted object). More generally,
|
||||||
from. Therefore, packages are also part of the export graph.
|
objects referred to from inlined function bodies can be reexported.
|
||||||
|
We need to know which package declares these reexported objects, and
|
||||||
|
therefore packages are also part of the export graph.
|
||||||
|
|
||||||
The roots of the graph are two lists of objects. The 1st list (phase 1,
|
The roots of the graph are two lists of objects. The 1st list (phase 1,
|
||||||
see Export) contains all objects that are exported at the package level.
|
see Export) contains all objects that are exported at the package level.
|
||||||
@ -30,9 +32,9 @@ function bodies. The format of this representation is compiler specific.
|
|||||||
|
|
||||||
The graph is serialized in in-order fashion, starting with the roots.
|
The graph is serialized in in-order fashion, starting with the roots.
|
||||||
Each object in the graph is serialized by writing its fields sequentially.
|
Each object in the graph is serialized by writing its fields sequentially.
|
||||||
If the field is a pointer to another object, that object is serialized,
|
If the field is a pointer to another object, that object is serialized in
|
||||||
recursively. Otherwise the field is written. Non-pointer fields are all
|
place, recursively. Otherwise the field is written in place. Non-pointer
|
||||||
encoded as integer or string values.
|
fields are all encoded as integer or string values.
|
||||||
|
|
||||||
Some objects (packages, types) may be referred to more than once. When
|
Some objects (packages, types) may be referred to more than once. When
|
||||||
reaching an object that was not serialized before, an integer _index_
|
reaching an object that was not serialized before, an integer _index_
|
||||||
@ -43,7 +45,7 @@ If the object was already serialized, the encoding is simply the object
|
|||||||
index >= 0. An importer can trivially determine if an object needs to
|
index >= 0. An importer can trivially determine if an object needs to
|
||||||
be read in for the first time (tag < 0) and entered into the respective
|
be read in for the first time (tag < 0) and entered into the respective
|
||||||
object table, or if the object was seen already (index >= 0), in which
|
object table, or if the object was seen already (index >= 0), in which
|
||||||
case the index is used to look up the object in a table.
|
case the index is used to look up the object in the respective table.
|
||||||
|
|
||||||
Before exporting or importing, the type tables are populated with the
|
Before exporting or importing, the type tables are populated with the
|
||||||
predeclared types (int, string, error, unsafe.Pointer, etc.). This way
|
predeclared types (int, string, error, unsafe.Pointer, etc.). This way
|
||||||
@ -59,7 +61,7 @@ format. These strings are followed by version-specific encoding options.
|
|||||||
That format encoding is no longer used but is supported to avoid spurious
|
That format encoding is no longer used but is supported to avoid spurious
|
||||||
errors when importing old installed package files.)
|
errors when importing old installed package files.)
|
||||||
|
|
||||||
The header is followed by the package object for the exported package,
|
This header is followed by the package object for the exported package,
|
||||||
two lists of objects, and the list of inlined function bodies.
|
two lists of objects, and the list of inlined function bodies.
|
||||||
|
|
||||||
The encoding of objects is straight-forward: Constants, variables, and
|
The encoding of objects is straight-forward: Constants, variables, and
|
||||||
@ -69,6 +71,8 @@ same type was imported before via another import, the importer must use
|
|||||||
the previously imported type pointer so that we have exactly one version
|
the previously imported type pointer so that we have exactly one version
|
||||||
(i.e., one pointer) for each named type (and read but discard the current
|
(i.e., one pointer) for each named type (and read but discard the current
|
||||||
type encoding). Unnamed types simply encode their respective fields.
|
type encoding). Unnamed types simply encode their respective fields.
|
||||||
|
Aliases are encoded starting with their name followed by the original
|
||||||
|
(aliased) object.
|
||||||
|
|
||||||
In the encoding, some lists start with the list length. Some lists are
|
In the encoding, some lists start with the list length. Some lists are
|
||||||
terminated with an end marker (usually for lists where we may not know
|
terminated with an end marker (usually for lists where we may not know
|
||||||
@ -101,30 +105,8 @@ compatibility with both the last release of the compiler, and with the
|
|||||||
corresponding compiler at tip. That change is necessarily more involved,
|
corresponding compiler at tip. That change is necessarily more involved,
|
||||||
as it must switch based on the version number in the export data file.
|
as it must switch based on the version number in the export data file.
|
||||||
|
|
||||||
It is recommended to turn on debugFormat when working on format changes
|
It is recommended to turn on debugFormat temporarily when working on format
|
||||||
as it will help finding encoding/decoding inconsistencies quickly.
|
changes as it will help finding encoding/decoding inconsistencies quickly.
|
||||||
|
|
||||||
Special care must be taken to update builtin.go when the export format
|
|
||||||
changes: builtin.go contains the export data obtained by compiling the
|
|
||||||
builtin/runtime.go and builtin/unsafe.go files; those compilations in
|
|
||||||
turn depend on importing the data in builtin.go. Thus, when the export
|
|
||||||
data format changes, the compiler must be able to import the data in
|
|
||||||
builtin.go even if its format has not yet changed. Proceed in several
|
|
||||||
steps as follows:
|
|
||||||
|
|
||||||
- Change the exporter to use the new format, and use a different version
|
|
||||||
string as well.
|
|
||||||
- Update the importer accordingly, but accept both the old and the new
|
|
||||||
format depending on the version string.
|
|
||||||
- all.bash should pass at this point.
|
|
||||||
- Run mkbuiltin.go: this will create a new builtin.go using the new
|
|
||||||
export format.
|
|
||||||
- go test -run Builtin should pass at this point.
|
|
||||||
- Remove importer support for the old export format and (maybe) revert
|
|
||||||
the version string again (it's only needed to mark the transition).
|
|
||||||
- all.bash should still pass.
|
|
||||||
|
|
||||||
Don't forget to set debugFormat to false.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package gc
|
package gc
|
||||||
@ -158,7 +140,11 @@ const debugFormat = false // default: false
|
|||||||
const forceObjFileStability = true
|
const forceObjFileStability = true
|
||||||
|
|
||||||
// Current export format version. Increase with each format change.
|
// Current export format version. Increase with each format change.
|
||||||
const exportVersion = 2
|
// 3: added aliasTag and export of aliases
|
||||||
|
// 2: removed unused bool in ODCL export
|
||||||
|
// 1: header format change (more regular), export package for _ struct fields
|
||||||
|
// 0: Go1.7 encoding
|
||||||
|
const exportVersion = 3
|
||||||
|
|
||||||
// exportInlined enables the export of inlined function bodies and related
|
// exportInlined enables the export of inlined function bodies and related
|
||||||
// dependencies. The compiler should work w/o any loss of functionality with
|
// dependencies. The compiler should work w/o any loss of functionality with
|
||||||
@ -364,6 +350,11 @@ func export(out *bufio.Writer, trace bool) int {
|
|||||||
if p.trace {
|
if p.trace {
|
||||||
p.tracef("\n")
|
p.tracef("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sym.Flags&SymAlias != 0 {
|
||||||
|
Fatalf("exporter: unexpected alias %v in inlined function body", sym)
|
||||||
|
}
|
||||||
|
|
||||||
p.obj(sym)
|
p.obj(sym)
|
||||||
objcount++
|
objcount++
|
||||||
}
|
}
|
||||||
@ -455,16 +446,44 @@ func unidealType(typ *Type, val Val) *Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *exporter) obj(sym *Sym) {
|
func (p *exporter) obj(sym *Sym) {
|
||||||
|
if sym.Flags&SymAlias != 0 {
|
||||||
|
p.tag(aliasTag)
|
||||||
|
p.pos(nil) // TODO(gri) fix position information
|
||||||
|
// Aliases can only be exported from the package that
|
||||||
|
// declares them (aliases to aliases are resolved to the
|
||||||
|
// original object, and so are uses of aliases in inlined
|
||||||
|
// exported function bodies). Thus, we only need the alias
|
||||||
|
// name without package qualification.
|
||||||
|
if sym.Pkg != localpkg {
|
||||||
|
Fatalf("exporter: export of non-local alias: %v", sym)
|
||||||
|
}
|
||||||
|
p.string(sym.Name)
|
||||||
|
sym = sym.Def.Sym // original object
|
||||||
|
// fall through to export original
|
||||||
|
// Multiple aliases to the same original will cause that
|
||||||
|
// original to be exported multiple times (issue #17636).
|
||||||
|
// TODO(gri) fix this
|
||||||
|
}
|
||||||
|
|
||||||
|
if sym != sym.Def.Sym {
|
||||||
|
Fatalf("exporter: exported object %v is not original %v", sym, sym.Def.Sym)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sym.Flags&SymAlias != 0 {
|
||||||
|
Fatalf("exporter: original object %v marked as alias", sym)
|
||||||
|
}
|
||||||
|
|
||||||
// Exported objects may be from different packages because they
|
// Exported objects may be from different packages because they
|
||||||
// may be re-exported as depencies when exporting inlined function
|
// may be re-exported via an exported alias or as dependencies in
|
||||||
// bodies. Thus, exported object names must be fully qualified.
|
// exported inlined function bodies. Thus, exported object names
|
||||||
|
// must be fully qualified.
|
||||||
//
|
//
|
||||||
// TODO(gri) This can only happen if exportInlined is enabled
|
// (This can only happen for aliased objects or during phase 2
|
||||||
// (default), and during phase 2 of object export. Objects exported
|
// (exportInlined enabled) of object export. Unaliased Objects
|
||||||
// in phase 1 (compiler-indendepent objects) are by definition only
|
// exported in phase 1 (compiler-indendepent objects) are by
|
||||||
// the objects from the current package and not pulled in via inlined
|
// definition only the objects from the current package and not
|
||||||
// function bodies. In that case the package qualifier is not needed.
|
// pulled in via inlined function bodies. In that case the package
|
||||||
// Possible space optimization.
|
// qualifier is not needed. Possible space optimization.)
|
||||||
|
|
||||||
n := sym.Def
|
n := sym.Def
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
@ -1780,6 +1799,9 @@ const (
|
|||||||
stringTag
|
stringTag
|
||||||
nilTag
|
nilTag
|
||||||
unknownTag // not used by gc (only appears in packages with errors)
|
unknownTag // not used by gc (only appears in packages with errors)
|
||||||
|
|
||||||
|
// Aliases
|
||||||
|
aliasTag
|
||||||
)
|
)
|
||||||
|
|
||||||
// Debugging support.
|
// Debugging support.
|
||||||
@ -1815,6 +1837,9 @@ var tagString = [...]string{
|
|||||||
-stringTag: "string",
|
-stringTag: "string",
|
||||||
-nilTag: "nil",
|
-nilTag: "nil",
|
||||||
-unknownTag: "unknown",
|
-unknownTag: "unknown",
|
||||||
|
|
||||||
|
// Aliases
|
||||||
|
-aliasTag: "alias",
|
||||||
}
|
}
|
||||||
|
|
||||||
// untype returns the "pseudo" untyped type for a Ctype (import/export use only).
|
// untype returns the "pseudo" untyped type for a Ctype (import/export use only).
|
||||||
|
@ -86,10 +86,10 @@ func Import(in *bufio.Reader) {
|
|||||||
|
|
||||||
// read version specific flags - extend as necessary
|
// read version specific flags - extend as necessary
|
||||||
switch p.version {
|
switch p.version {
|
||||||
// case 3:
|
// case 4:
|
||||||
// ...
|
// ...
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case 2, 1:
|
case 3, 2, 1:
|
||||||
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
||||||
p.trackAllTypes = p.bool()
|
p.trackAllTypes = p.bool()
|
||||||
p.posInfoFormat = p.bool()
|
p.posInfoFormat = p.bool()
|
||||||
@ -307,26 +307,35 @@ func idealType(typ *Type) *Type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *importer) obj(tag int) {
|
func (p *importer) obj(tag int) {
|
||||||
|
var alias *Sym
|
||||||
|
if tag == aliasTag {
|
||||||
|
p.pos()
|
||||||
|
alias = importpkg.Lookup(p.string())
|
||||||
|
alias.Flags |= SymAlias
|
||||||
|
tag = p.tagOrIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
var sym *Sym
|
||||||
switch tag {
|
switch tag {
|
||||||
case constTag:
|
case constTag:
|
||||||
p.pos()
|
p.pos()
|
||||||
sym := p.qualifiedName()
|
sym = p.qualifiedName()
|
||||||
typ := p.typ()
|
typ := p.typ()
|
||||||
val := p.value(typ)
|
val := p.value(typ)
|
||||||
importconst(sym, idealType(typ), nodlit(val))
|
importconst(sym, idealType(typ), nodlit(val))
|
||||||
|
|
||||||
case typeTag:
|
case typeTag:
|
||||||
p.typ()
|
sym = p.typ().Sym
|
||||||
|
|
||||||
case varTag:
|
case varTag:
|
||||||
p.pos()
|
p.pos()
|
||||||
sym := p.qualifiedName()
|
sym = p.qualifiedName()
|
||||||
typ := p.typ()
|
typ := p.typ()
|
||||||
importvar(sym, typ)
|
importvar(sym, typ)
|
||||||
|
|
||||||
case funcTag:
|
case funcTag:
|
||||||
p.pos()
|
p.pos()
|
||||||
sym := p.qualifiedName()
|
sym = p.qualifiedName()
|
||||||
params := p.paramList()
|
params := p.paramList()
|
||||||
result := p.paramList()
|
result := p.paramList()
|
||||||
|
|
||||||
@ -357,6 +366,11 @@ func (p *importer) obj(tag int) {
|
|||||||
default:
|
default:
|
||||||
formatErrorf("unexpected object (tag = %d)", tag)
|
formatErrorf("unexpected object (tag = %d)", tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if alias != nil {
|
||||||
|
alias.Def = sym.Def
|
||||||
|
importsym(alias, sym.Def.Op)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *importer) pos() {
|
func (p *importer) pos() {
|
||||||
|
@ -63,6 +63,7 @@ const (
|
|||||||
SymSiggen
|
SymSiggen
|
||||||
SymAsm
|
SymAsm
|
||||||
SymAlgGen
|
SymAlgGen
|
||||||
|
SymAlias // alias, original is Sym.Def.Sym
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Class of a variable/function describes the "storage class"
|
// The Class of a variable/function describes the "storage class"
|
||||||
|
@ -928,7 +928,7 @@ func mkpackage(pkgname string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Def.Sym != s {
|
if s.Def.Sym != s && s.Flags&SymAlias == 0 {
|
||||||
// throw away top-level name left over
|
// throw away top-level name left over
|
||||||
// from previous import . "x"
|
// from previous import . "x"
|
||||||
if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
|
if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
|
||||||
@ -936,8 +936,6 @@ func mkpackage(pkgname string) {
|
|||||||
s.Def.Name.Pack.Used = true
|
s.Def.Name.Pack.Used = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(gri) This will also affect exported aliases.
|
|
||||||
// Need to fix this.
|
|
||||||
s.Def = nil
|
s.Def = nil
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,11 @@ func (p *noder) aliasDecl(decl *syntax.AliasDecl) {
|
|||||||
}
|
}
|
||||||
pkg.Used = true
|
pkg.Used = true
|
||||||
|
|
||||||
|
// Resolve original entity
|
||||||
orig := oldname(restrictlookup(qident.Sel.Value, pkg.Name.Pkg))
|
orig := oldname(restrictlookup(qident.Sel.Value, pkg.Name.Pkg))
|
||||||
|
if orig.Sym.Flags&SymAlias != 0 {
|
||||||
|
Fatalf("original %v marked as alias", orig.Sym)
|
||||||
|
}
|
||||||
|
|
||||||
// An alias declaration must not refer to package unsafe.
|
// An alias declaration must not refer to package unsafe.
|
||||||
if orig.Sym.Pkg == unsafepkg {
|
if orig.Sym.Pkg == unsafepkg {
|
||||||
@ -222,16 +226,16 @@ func (p *noder) aliasDecl(decl *syntax.AliasDecl) {
|
|||||||
redeclare(asym, "in alias declaration")
|
redeclare(asym, "in alias declaration")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
asym.Flags |= SymAlias
|
||||||
asym.Def = orig
|
asym.Def = orig
|
||||||
asym.Block = block
|
asym.Block = block
|
||||||
asym.Lastlineno = lineno
|
asym.Lastlineno = lineno
|
||||||
|
|
||||||
if exportname(asym.Name) {
|
if exportname(asym.Name) {
|
||||||
yyerror("cannot export alias %v: not yet implemented", asym)
|
|
||||||
// TODO(gri) newname(asym) is only needed to satisfy exportsym
|
// TODO(gri) newname(asym) is only needed to satisfy exportsym
|
||||||
// (and indirectly, exportlist). We should be able to just
|
// (and indirectly, exportlist). We should be able to just
|
||||||
// collect the Syms, eventually.
|
// collect the Syms, eventually.
|
||||||
// exportsym(newname(asym))
|
exportsym(newname(asym))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,10 +98,10 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||||||
|
|
||||||
// read version specific flags - extend as necessary
|
// read version specific flags - extend as necessary
|
||||||
switch p.version {
|
switch p.version {
|
||||||
// case 3:
|
// case 4:
|
||||||
// ...
|
// ...
|
||||||
// fallthrough
|
// fallthrough
|
||||||
case 2, 1:
|
case 3, 2, 1:
|
||||||
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
||||||
p.trackAllTypes = p.int() != 0
|
p.trackAllTypes = p.int() != 0
|
||||||
p.posInfoFormat = p.int() != 0
|
p.posInfoFormat = p.int() != 0
|
||||||
|
@ -50,7 +50,7 @@ func f => before.f // ERROR "before is not a package"
|
|||||||
var v => after.m // ERROR "after is not a package"
|
var v => after.m // ERROR "after is not a package"
|
||||||
func f => after.m // ERROR "after is not a package"
|
func f => after.m // ERROR "after is not a package"
|
||||||
|
|
||||||
// TODO(gri) fix error printing - should not print a qualified identifier...
|
// TODO(gri) fix error printing - should print correct qualified identifier...
|
||||||
var _ => Default.ARCH // ERROR "build.Default is not a package"
|
var _ => Default.ARCH // ERROR "build.Default is not a package"
|
||||||
|
|
||||||
// aliases may not refer to package unsafe
|
// aliases may not refer to package unsafe
|
||||||
@ -77,11 +77,11 @@ func sin1 => math.Pi // ERROR "math.Pi is not a function"
|
|||||||
// alias reference to a package marks package as used
|
// alias reference to a package marks package as used
|
||||||
func _ => fmt.Println
|
func _ => fmt.Println
|
||||||
|
|
||||||
// TODO(gri) aliased cannot be exported yet - fix this
|
// re-exported aliases
|
||||||
const Pi => math.Pi // ERROR "cannot export alias Pi"
|
const Pi => math.Pi
|
||||||
type Writer => io.Writer // ERROR "cannot export alias Writer"
|
type Writer => io.Writer
|
||||||
var Def => build.Default // ERROR "cannot export alias Def"
|
var Def => build.Default
|
||||||
func Sin => math.Sin // ERROR "cannot export alias Sin"
|
func Sin => math.Sin
|
||||||
|
|
||||||
// type aliases denote identical types
|
// type aliases denote identical types
|
||||||
type myPackage => build.Package
|
type myPackage => build.Package
|
||||||
|
54
test/alias3.dir/a.go
Normal file
54
test/alias3.dir/a.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
package a
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"go/build"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func F(c *build.Context, w io.Writer) {}
|
||||||
|
|
||||||
|
func Inlined() bool { var w Writer; return w == nil }
|
||||||
|
|
||||||
|
func Check() {
|
||||||
|
if Pi != math.Pi {
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var w Writer
|
||||||
|
F(new(Context), w)
|
||||||
|
F(new(build.Context), bytes.NewBuffer(nil))
|
||||||
|
|
||||||
|
if &Default != &build.Default {
|
||||||
|
panic(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if Sin(1) != math.Sin(1) {
|
||||||
|
panic(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ *LimitedReader = new(LimitedReader2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// export aliases
|
||||||
|
const Pi => math.Pi
|
||||||
|
|
||||||
|
type (
|
||||||
|
Context => build.Context // not an interface
|
||||||
|
Writer => io.Writer // interface
|
||||||
|
)
|
||||||
|
|
||||||
|
// different aliases may refer to the same original
|
||||||
|
type LimitedReader => io.LimitedReader
|
||||||
|
type LimitedReader2 => io.LimitedReader
|
||||||
|
|
||||||
|
var Default => build.Default
|
||||||
|
var Default2 => build.Default
|
||||||
|
|
||||||
|
func Sin => math.Sin
|
||||||
|
func Sin2 => math.Sin
|
61
test/alias3.dir/b.go
Normal file
61
test/alias3.dir/b.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
package b
|
||||||
|
|
||||||
|
import (
|
||||||
|
"./a"
|
||||||
|
"bytes"
|
||||||
|
"go/build"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func F => a.F
|
||||||
|
func Inlined => a.Inlined
|
||||||
|
|
||||||
|
var _ func(*Context, io.Writer) = a.F
|
||||||
|
|
||||||
|
// check aliases
|
||||||
|
func Check() {
|
||||||
|
if Pi != math.Pi {
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var w Writer
|
||||||
|
a.F(new(Context), w)
|
||||||
|
F(new(build.Context), bytes.NewBuffer(nil))
|
||||||
|
|
||||||
|
if !Inlined() {
|
||||||
|
panic(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if &Default != &build.Default {
|
||||||
|
panic(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if Sin(1) != math.Sin(1) {
|
||||||
|
panic(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ *LimitedReader = new(LimitedReader2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-export aliases
|
||||||
|
const Pi => a.Pi
|
||||||
|
|
||||||
|
type (
|
||||||
|
Context => a.Context // not an interface
|
||||||
|
Writer => a.Writer // interface
|
||||||
|
)
|
||||||
|
|
||||||
|
// different aliases may refer to the same original
|
||||||
|
type LimitedReader => a.LimitedReader
|
||||||
|
type LimitedReader2 => a.LimitedReader2
|
||||||
|
|
||||||
|
var Default => a.Default
|
||||||
|
var Default2 => a.Default2
|
||||||
|
|
||||||
|
func Sin => a.Sin
|
||||||
|
func Sin2 => a.Sin
|
66
test/alias3.dir/c.go
Normal file
66
test/alias3.dir/c.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"./a"
|
||||||
|
"./b"
|
||||||
|
"bytes"
|
||||||
|
"go/build"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f => b.F
|
||||||
|
func inlined => b.Inlined
|
||||||
|
|
||||||
|
var _ func(*context, a.Writer) = f
|
||||||
|
|
||||||
|
func Check() {
|
||||||
|
if pi != math.Pi {
|
||||||
|
panic(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var w writer
|
||||||
|
b.F(new(context), w)
|
||||||
|
f(new(build.Context), bytes.NewBuffer(nil))
|
||||||
|
|
||||||
|
if !inlined() {
|
||||||
|
panic(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if &default_ != &build.Default {
|
||||||
|
panic(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sin(1) != math.Sin(1) {
|
||||||
|
panic(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ *limitedReader = new(limitedReader2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// local aliases
|
||||||
|
const pi => b.Pi
|
||||||
|
|
||||||
|
type (
|
||||||
|
context => b.Context // not an interface
|
||||||
|
writer => b.Writer // interface
|
||||||
|
)
|
||||||
|
|
||||||
|
// different aliases may refer to the same original
|
||||||
|
type limitedReader => b.LimitedReader
|
||||||
|
type limitedReader2 => b.LimitedReader2
|
||||||
|
|
||||||
|
var default_ => b.Default
|
||||||
|
var default2 => b.Default2
|
||||||
|
|
||||||
|
func sin => b.Sin
|
||||||
|
func sin2 => b.Sin
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
a.Check()
|
||||||
|
b.Check()
|
||||||
|
Check()
|
||||||
|
}
|
7
test/alias3.go
Normal file
7
test/alias3.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// rundir
|
||||||
|
|
||||||
|
// Copyright 2016 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.
|
||||||
|
|
||||||
|
package ignored
|
Loading…
x
Reference in New Issue
Block a user