mirror of https://github.com/golang/go.git
[dev.power64] all: merge default into dev.power64
LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/164110043
This commit is contained in:
commit
5a653089ef
|
|
@ -42,6 +42,10 @@ identical to Go 1.1. The GCC 4.8.2 release includes a complete Go
|
|||
1.1.2 implementation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The GCC 4.9 releases include a complete Go 1.2 implementation.
|
||||
</p>
|
||||
|
||||
<h2 id="Source_code">Source code</h2>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ bufio: handling of empty tokens at EOF changed, may require scanner change (CL 1
|
|||
compress/flate, compress/gzip, compress/zlib: Reset support (https://codereview.appspot.com/97140043)
|
||||
crypto/tls: add support for ALPN (RFC 7301) (CL 108710046)
|
||||
crypto/tls: support programmatic selection of server certificates (CL 107400043)
|
||||
encoding/asn1: optional elements with a default value will now only be omitted if they have that value (CL 86960045)
|
||||
flag: it is now an error to set a flag multiple times (CL 156390043)
|
||||
fmt: print type *map[T]T as &map[k:v] (CL 154870043)
|
||||
encoding/csv: do not quote empty strings, quote \. (CL 164760043)
|
||||
encoding/gob: remove unsafe (CL 102680045)
|
||||
misc: deleted editor support; refer to https://code.google.com/p/go-wiki/wiki/IDEsAndTextEditorPlugins instead (CL 105470043)
|
||||
net/http: add Request.BasicAuth method (CL 76540043)
|
||||
|
|
@ -46,6 +48,6 @@ testing: add TestMain support (CL 148770043)
|
|||
text/scanner: add IsIdentRune field of Scanner. (CL 108030044)
|
||||
text/template: allow comparison of signed and unsigned integers (CL 149780043)
|
||||
time: use the micro symbol (µ (U+00B5)) to print microsecond duration (CL 105030046)
|
||||
encoding/asn1: optional elements with a default value will now only be omitted if they have that value (CL 86960045)
|
||||
unsafe: document the existing situation that unsafe programs are not go1-guaranteed (CL 162060043)
|
||||
|
||||
go.sys subrepo created: http://golang.org/s/go1.4-syscall
|
||||
|
|
|
|||
|
|
@ -104,6 +104,14 @@ outside of tests, and using it may cause a program to fail
|
|||
to compile in future releases.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Use of package <code>unsafe</code>. Packages that import
|
||||
<a href="/pkg/unsafe/"><code>unsafe</code></a>
|
||||
may depend on internal properties of the Go implementation.
|
||||
We reserve the right to make changes to the implementation
|
||||
that may break such programs.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -1115,7 +1115,7 @@ error but the situation can still be confusing, because sometimes a
|
|||
<a href="#different_method_sets">pointer
|
||||
is necessary to satisfy an interface</a>.
|
||||
The insight is that although a pointer to a concrete type can satisfy
|
||||
an interface, with one exception <em>a pointer to an interface can never satisfy a interface</em>.
|
||||
an interface, with one exception <em>a pointer to an interface can never satisfy an interface</em>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -1356,7 +1356,7 @@ to speed it up.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Go's goroutine scheduler is not as good as it needs to be. In future, it
|
||||
Go's goroutine scheduler is not as good as it needs to be. In the future, it
|
||||
should recognize such cases and optimize its use of OS threads. For now,
|
||||
<code>GOMAXPROCS</code> should be set on a per-application basis.
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of October 16, 2014",
|
||||
"Subtitle": "Version of October 23, 2014",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -6207,8 +6207,8 @@ type Error interface {
|
|||
The built-in package <code>unsafe</code>, known to the compiler,
|
||||
provides facilities for low-level programming including operations
|
||||
that violate the type system. A package using <code>unsafe</code>
|
||||
must be vetted manually for type safety. The package provides the
|
||||
following interface:
|
||||
must be vetted manually for type safety and may not be portable.
|
||||
The package provides the following interface:
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
|
|
@ -6223,10 +6223,11 @@ func Sizeof(variable ArbitraryType) uintptr
|
|||
</pre>
|
||||
|
||||
<p>
|
||||
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
|
||||
a <code>Pointer</code> type and vice versa.
|
||||
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
|
||||
value may not be <a href="#Address_operators">dereferenced</a>.
|
||||
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
|
||||
a <code>Pointer</code> type and vice versa.
|
||||
The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@
|
|||
|
||||
<Property Id="ARPCOMMENTS" Value="The Go programming language is a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language." />
|
||||
<Property Id="ARPCONTACT" Value="golang-nuts@googlegroups.com" />
|
||||
<Property Id="ARPHELPLINK" Value="golang.org/doc/community.html" />
|
||||
<Property Id="ARPREADME" Value="golang.org" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="golang.org" />
|
||||
<Property Id="ARPHELPLINK" Value="https://golang.org/help/" />
|
||||
<Property Id="ARPREADME" Value="https://golang.org" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://golang.org" />
|
||||
<Property Id="LicenseAccepted">1</Property>
|
||||
<Icon Id="gopher.ico" SourceFile="images\gopher.ico"/>
|
||||
<Property Id="ARPPRODUCTICON" Value="gopher.ico" />
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ walkexpr(Node **np, NodeList **init)
|
|||
if(oaslit(n, init))
|
||||
goto ret;
|
||||
|
||||
if(n->right == N)
|
||||
if(n->right == N || iszero(n->right) && !flag_race)
|
||||
goto ret;
|
||||
|
||||
switch(n->right->op) {
|
||||
|
|
@ -1390,12 +1390,6 @@ walkexpr(Node **np, NodeList **init)
|
|||
case OMAPLIT:
|
||||
case OSTRUCTLIT:
|
||||
case OPTRLIT:
|
||||
// NOTE(rsc): Race detector cannot handle seeing
|
||||
// a STRUCTLIT or ARRAYLIT representing a zero value,
|
||||
// so make a temporary for those always in race mode.
|
||||
// Otherwise, leave zero values in place.
|
||||
if(iszero(n) && !flag_race)
|
||||
goto ret;
|
||||
var = temp(n->type);
|
||||
anylit(0, n, var, init);
|
||||
n = var;
|
||||
|
|
|
|||
|
|
@ -1945,6 +1945,7 @@ func (tools gccgoToolchain) ld(b *builder, p *Package, out string, allactions []
|
|||
}
|
||||
ldflags = append(ldflags, afiles...)
|
||||
ldflags = append(ldflags, cgoldflags...)
|
||||
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
|
||||
ldflags = append(ldflags, p.CgoLDFLAGS...)
|
||||
if usesCgo && goos == "linux" {
|
||||
ldflags = append(ldflags, "-Wl,-E")
|
||||
|
|
|
|||
|
|
@ -272,8 +272,15 @@ func downloadPackage(p *Package) error {
|
|||
dir := filepath.Join(p.build.SrcRoot, rootPath)
|
||||
if remote, err := vcs.remoteRepo(vcs, dir); err == nil {
|
||||
if rr, err := repoRootForImportPath(p.ImportPath); err == nil {
|
||||
if remote != rr.repo {
|
||||
return fmt.Errorf("%s is from %s, should be from %s", dir, remote, rr.repo)
|
||||
repo := rr.repo
|
||||
if rr.vcs.resolveRepo != nil {
|
||||
resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo)
|
||||
if err == nil {
|
||||
repo = resolved
|
||||
}
|
||||
}
|
||||
if remote != repo {
|
||||
return fmt.Errorf("%s is from %s, should be from %s", dir, remote, repo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ type vcsCmd struct {
|
|||
scheme []string
|
||||
pingCmd string
|
||||
|
||||
remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
|
||||
remoteRepo func(v *vcsCmd, rootDir string) (remoteRepo string, err error)
|
||||
resolveRepo func(v *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error)
|
||||
}
|
||||
|
||||
// A tagCmd describes a command to list available tags
|
||||
|
|
@ -164,8 +165,51 @@ var vcsBzr = &vcsCmd{
|
|||
tagSyncCmd: "update -r {tag}",
|
||||
tagSyncDefault: "update -r revno:-1",
|
||||
|
||||
scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
||||
pingCmd: "info {scheme}://{repo}",
|
||||
scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
||||
pingCmd: "info {scheme}://{repo}",
|
||||
remoteRepo: bzrRemoteRepo,
|
||||
resolveRepo: bzrResolveRepo,
|
||||
}
|
||||
|
||||
func bzrRemoteRepo(vcsBzr *vcsCmd, rootDir string) (remoteRepo string, err error) {
|
||||
outb, err := vcsBzr.runOutput(rootDir, "config parent_location")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.TrimSpace(string(outb)), nil
|
||||
}
|
||||
|
||||
func bzrResolveRepo(vcsBzr *vcsCmd, rootDir, remoteRepo string) (realRepo string, err error) {
|
||||
outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
out := string(outb)
|
||||
|
||||
// Expect:
|
||||
// ...
|
||||
// (branch root|repository branch): <URL>
|
||||
// ...
|
||||
|
||||
found := false
|
||||
for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} {
|
||||
i := strings.Index(out, prefix)
|
||||
if i >= 0 {
|
||||
out = out[i+len(prefix):]
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return "", fmt.Errorf("unable to parse output of bzr info")
|
||||
}
|
||||
|
||||
i := strings.Index(out, "\n")
|
||||
if i < 0 {
|
||||
return "", fmt.Errorf("unable to parse output of bzr info")
|
||||
}
|
||||
out = out[:i]
|
||||
return strings.TrimSpace(string(out)), nil
|
||||
}
|
||||
|
||||
// vcsSvn describes how to use Subversion.
|
||||
|
|
|
|||
|
|
@ -115,10 +115,22 @@ func (w *Writer) WriteAll(records [][]string) (err error) {
|
|||
}
|
||||
|
||||
// fieldNeedsQuotes returns true if our field must be enclosed in quotes.
|
||||
// Empty fields, files with a Comma, fields with a quote or newline, and
|
||||
// Fields with a Comma, fields with a quote or newline, and
|
||||
// fields which start with a space must be enclosed in quotes.
|
||||
// We used to quote empty strings, but we do not anymore (as of Go 1.4).
|
||||
// The two representations should be equivalent, but Postgres distinguishes
|
||||
// quoted vs non-quoted empty string during database imports, and it has
|
||||
// an option to force the quoted behavior for non-quoted CSV but it has
|
||||
// no option to force the non-quoted behavior for quoted CSV, making
|
||||
// CSV with quoted empty strings strictly less useful.
|
||||
// Not quoting the empty string also makes this package match the behavior
|
||||
// of Microsoft Excel and Google Drive.
|
||||
// For Postgres, quote the data termating string `\.`.
|
||||
func (w *Writer) fieldNeedsQuotes(field string) bool {
|
||||
if len(field) == 0 || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
|
||||
if field == "" {
|
||||
return false
|
||||
}
|
||||
if field == `\.` || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,17 @@ var writeTests = []struct {
|
|||
{Input: [][]string{{"abc\ndef"}}, Output: "\"abc\r\ndef\"\r\n", UseCRLF: true},
|
||||
{Input: [][]string{{"abc\rdef"}}, Output: "\"abcdef\"\r\n", UseCRLF: true},
|
||||
{Input: [][]string{{"abc\rdef"}}, Output: "\"abc\rdef\"\n", UseCRLF: false},
|
||||
{Input: [][]string{{""}}, Output: "\n"},
|
||||
{Input: [][]string{{"", ""}}, Output: ",\n"},
|
||||
{Input: [][]string{{"", "", ""}}, Output: ",,\n"},
|
||||
{Input: [][]string{{"", "", "a"}}, Output: ",,a\n"},
|
||||
{Input: [][]string{{"", "a", ""}}, Output: ",a,\n"},
|
||||
{Input: [][]string{{"", "a", "a"}}, Output: ",a,a\n"},
|
||||
{Input: [][]string{{"a", "", ""}}, Output: "a,,\n"},
|
||||
{Input: [][]string{{"a", "", "a"}}, Output: "a,,a\n"},
|
||||
{Input: [][]string{{"a", "a", ""}}, Output: "a,a,\n"},
|
||||
{Input: [][]string{{"a", "a", "a"}}, Output: "a,a,a\n"},
|
||||
{Input: [][]string{{`\.`}}, Output: "\"\\.\"\n"},
|
||||
}
|
||||
|
||||
func TestWrite(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -162,6 +162,10 @@ func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
fmt.Fprintf(w, "Unknown profile: %s\n", name)
|
||||
return
|
||||
}
|
||||
gc, _ := strconv.Atoi(r.FormValue("gc"))
|
||||
if name == "heap" && gc > 0 {
|
||||
runtime.GC()
|
||||
}
|
||||
p.WriteTo(w, debug)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,16 @@ func lookupIPMerge(host string) (addrs []IP, err error) {
|
|||
addrsi, err, shared := lookupGroup.Do(host, func() (interface{}, error) {
|
||||
return lookupIP(host)
|
||||
})
|
||||
return lookupIPReturn(addrsi, err, shared)
|
||||
}
|
||||
|
||||
// lookupIPReturn turns the return values from singleflight.Do into
|
||||
// the return values from LookupIP.
|
||||
func lookupIPReturn(addrsi interface{}, err error, shared bool) ([]IP, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addrs = addrsi.([]IP)
|
||||
addrs := addrsi.([]IP)
|
||||
if shared {
|
||||
clone := make([]IP, len(addrs))
|
||||
copy(clone, addrs)
|
||||
|
|
@ -52,41 +58,40 @@ func lookupIPMerge(host string) (addrs []IP, err error) {
|
|||
return addrs, nil
|
||||
}
|
||||
|
||||
// lookupIPDeadline looks up a hostname with a deadline.
|
||||
func lookupIPDeadline(host string, deadline time.Time) (addrs []IP, err error) {
|
||||
if deadline.IsZero() {
|
||||
return lookupIPMerge(host)
|
||||
}
|
||||
|
||||
// TODO(bradfitz): consider pushing the deadline down into the
|
||||
// name resolution functions. But that involves fixing it for
|
||||
// the native Go resolver, cgo, Windows, etc.
|
||||
//
|
||||
// In the meantime, just use a goroutine. Most users affected
|
||||
// by http://golang.org/issue/2631 are due to TCP connections
|
||||
// to unresponsive hosts, not DNS.
|
||||
// We could push the deadline down into the name resolution
|
||||
// functions. However, the most commonly used implementation
|
||||
// calls getaddrinfo, which has no timeout.
|
||||
|
||||
timeout := deadline.Sub(time.Now())
|
||||
if timeout <= 0 {
|
||||
err = errTimeout
|
||||
return
|
||||
return nil, errTimeout
|
||||
}
|
||||
t := time.NewTimer(timeout)
|
||||
defer t.Stop()
|
||||
type res struct {
|
||||
addrs []IP
|
||||
err error
|
||||
}
|
||||
resc := make(chan res, 1)
|
||||
go func() {
|
||||
a, err := lookupIPMerge(host)
|
||||
resc <- res{a, err}
|
||||
}()
|
||||
|
||||
ch := lookupGroup.DoChan(host, func() (interface{}, error) {
|
||||
return lookupIP(host)
|
||||
})
|
||||
|
||||
select {
|
||||
case <-t.C:
|
||||
err = errTimeout
|
||||
case r := <-resc:
|
||||
addrs, err = r.addrs, r.err
|
||||
// The DNS lookup timed out for some reason. Force
|
||||
// future requests to start the DNS lookup again
|
||||
// rather than waiting for the current lookup to
|
||||
// complete. See issue 8602.
|
||||
lookupGroup.Forget(host)
|
||||
|
||||
return nil, errTimeout
|
||||
|
||||
case r := <-ch:
|
||||
return lookupIPReturn(r.v, r.err, r.shared)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// LookupPort looks up the port for the given network and service.
|
||||
|
|
|
|||
|
|
@ -8,10 +8,18 @@ import "sync"
|
|||
|
||||
// call is an in-flight or completed singleflight.Do call
|
||||
type call struct {
|
||||
wg sync.WaitGroup
|
||||
val interface{}
|
||||
err error
|
||||
dups int
|
||||
wg sync.WaitGroup
|
||||
|
||||
// These fields are written once before the WaitGroup is done
|
||||
// and are only read after the WaitGroup is done.
|
||||
val interface{}
|
||||
err error
|
||||
|
||||
// These fields are read and written with the singleflight
|
||||
// mutex held before the WaitGroup is done, and are read but
|
||||
// not written after the WaitGroup is done.
|
||||
dups int
|
||||
chans []chan<- singleflightResult
|
||||
}
|
||||
|
||||
// singleflight represents a class of work and forms a namespace in
|
||||
|
|
@ -21,6 +29,14 @@ type singleflight struct {
|
|||
m map[string]*call // lazily initialized
|
||||
}
|
||||
|
||||
// singleflightResult holds the results of Do, so they can be passed
|
||||
// on a channel.
|
||||
type singleflightResult struct {
|
||||
v interface{}
|
||||
err error
|
||||
shared bool
|
||||
}
|
||||
|
||||
// Do executes and returns the results of the given function, making
|
||||
// sure that only one execution is in-flight for a given key at a
|
||||
// time. If a duplicate comes in, the duplicate caller waits for the
|
||||
|
|
@ -42,12 +58,52 @@ func (g *singleflight) Do(key string, fn func() (interface{}, error)) (v interfa
|
|||
g.m[key] = c
|
||||
g.mu.Unlock()
|
||||
|
||||
g.doCall(c, key, fn)
|
||||
return c.val, c.err, c.dups > 0
|
||||
}
|
||||
|
||||
// DoChan is like Do but returns a channel that will receive the
|
||||
// results when they are ready.
|
||||
func (g *singleflight) DoChan(key string, fn func() (interface{}, error)) <-chan singleflightResult {
|
||||
ch := make(chan singleflightResult, 1)
|
||||
g.mu.Lock()
|
||||
if g.m == nil {
|
||||
g.m = make(map[string]*call)
|
||||
}
|
||||
if c, ok := g.m[key]; ok {
|
||||
c.dups++
|
||||
c.chans = append(c.chans, ch)
|
||||
g.mu.Unlock()
|
||||
return ch
|
||||
}
|
||||
c := &call{chans: []chan<- singleflightResult{ch}}
|
||||
c.wg.Add(1)
|
||||
g.m[key] = c
|
||||
g.mu.Unlock()
|
||||
|
||||
go g.doCall(c, key, fn)
|
||||
|
||||
return ch
|
||||
}
|
||||
|
||||
// doCall handles the single call for a key.
|
||||
func (g *singleflight) doCall(c *call, key string, fn func() (interface{}, error)) {
|
||||
c.val, c.err = fn()
|
||||
c.wg.Done()
|
||||
|
||||
g.mu.Lock()
|
||||
delete(g.m, key)
|
||||
for _, ch := range c.chans {
|
||||
ch <- singleflightResult{c.val, c.err, c.dups > 0}
|
||||
}
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
||||
// Forget tells the singleflight to forget about a key. Future calls
|
||||
// to Do for this key will call the function rather than waiting for
|
||||
// an earlier call to complete.
|
||||
func (g *singleflight) Forget(key string) {
|
||||
g.mu.Lock()
|
||||
delete(g.m, key)
|
||||
g.mu.Unlock()
|
||||
|
||||
return c.val, c.err, c.dups > 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,10 +84,13 @@ func symtabinit() {
|
|||
}
|
||||
}
|
||||
|
||||
// file table follows ftab.
|
||||
// The ftab ends with a half functab consisting only of
|
||||
// 'entry', followed by a uint32 giving the pcln-relative
|
||||
// offset of the file table.
|
||||
sp = (*sliceStruct)(unsafe.Pointer(&filetab))
|
||||
p = unsafe.Pointer(add(unsafe.Pointer(pcln), ftab[nftab].funcoff))
|
||||
sp.array = unsafe.Pointer(add(unsafe.Pointer(pcln), ftab[nftab].funcoff))
|
||||
end := unsafe.Pointer(&ftab[nftab].funcoff) // just beyond ftab
|
||||
fileoffset := *(*uint32)(end)
|
||||
sp.array = unsafe.Pointer(&pclntable[fileoffset])
|
||||
// length is in first element of array.
|
||||
// set len to 1 so we can get first element.
|
||||
sp.len = 1
|
||||
|
|
@ -224,7 +227,7 @@ func funcline(f *_func, targetpc uintptr, file *string) int32 {
|
|||
func funcspdelta(f *_func, targetpc uintptr) int32 {
|
||||
x := pcvalue(f, f.pcsp, targetpc, true)
|
||||
if x&(ptrSize-1) != 0 {
|
||||
print("invalid spdelta ", f.pcsp, " ", x, "\n")
|
||||
print("invalid spdelta ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
/*
|
||||
Package unsafe contains operations that step around the type safety of Go programs.
|
||||
|
||||
Packages that import unsafe may be non-portable and are not protected by the
|
||||
Go 1 compatibility guidelines.
|
||||
*/
|
||||
package unsafe
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
// run
|
||||
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Some uses of zeroed constants in non-assignment
|
||||
// expressions broke with our more aggressive zeroing
|
||||
// of assignments (internal compiler errors).
|
||||
|
||||
package main
|
||||
|
||||
func f1() {
|
||||
type T [2]int
|
||||
p := T{0, 1}
|
||||
switch p {
|
||||
case T{0, 0}:
|
||||
panic("wrong1")
|
||||
case T{0, 1}:
|
||||
// ok
|
||||
default:
|
||||
panic("wrong2")
|
||||
}
|
||||
|
||||
if p == (T{0, 0}) {
|
||||
panic("wrong3")
|
||||
} else if p == (T{0, 1}) {
|
||||
// ok
|
||||
} else {
|
||||
panic("wrong4")
|
||||
}
|
||||
}
|
||||
|
||||
type T struct {
|
||||
V int
|
||||
}
|
||||
|
||||
var X = T{}.V
|
||||
|
||||
func f2() {
|
||||
var x = T{}.V
|
||||
if x != 0 {
|
||||
panic("wrongx")
|
||||
}
|
||||
if X != 0 {
|
||||
panic("wrongX")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
f1()
|
||||
f2()
|
||||
}
|
||||
Loading…
Reference in New Issue