├── importer ├── gccgoimporter │ ├── testdata │ │ ├── pointer.go │ │ ├── conversions.go │ │ ├── imports.go │ │ ├── time.gox │ │ ├── unicode.gox │ │ ├── pointer.gox │ │ ├── complexnums.go │ │ ├── complexnums.gox │ │ ├── conversions.gox │ │ └── imports.gox │ ├── gccgoinstallation.go │ ├── parser_test.go │ ├── gccgoinstallation_test.go │ ├── importer_test.go │ └── importer.go ├── gcimporter │ ├── testdata │ │ ├── versions │ │ │ ├── test_go1.7_0.a │ │ │ ├── test_go1.7_1.a │ │ │ └── test.go │ │ ├── b.go │ │ ├── p.go │ │ ├── a.go │ │ ├── issue15920.go │ │ └── exports.go │ ├── exportdata.go │ └── gcimporter.go └── importer.go ├── types ├── testdata │ ├── blank.src │ ├── importdecl1b.src │ ├── importdecl1a.src │ ├── importC.src │ ├── cycles3.src │ ├── cycles1.src │ ├── importdecl0b.src │ ├── importdecl0a.src │ ├── init1.src │ ├── errors.src │ ├── decls2b.src │ ├── conversions.src │ ├── cycles4.src │ ├── init0.src │ ├── cycles2.src │ ├── cycles.src │ ├── constdecl.src │ ├── expr1.src │ ├── decls2a.src │ ├── init2.src │ ├── methodsets.src │ ├── expr0.src │ ├── labels.src │ ├── stmt1.src │ ├── decls1.src │ ├── decls0.src │ ├── vardecl.src │ ├── expr2.src │ ├── decls3.src │ └── issues.src ├── objset.go ├── token_test.go ├── exprstring_test.go ├── package.go ├── self_test.go ├── eval.go ├── errors.go ├── ordering.go ├── conversions.go ├── selection.go ├── typestring_test.go ├── hilbert_test.go ├── eval_test.go ├── return.go ├── exprstring.go ├── resolver_test.go ├── scope.go ├── sizes.go ├── universe.go └── issues_test.go ├── Makefile ├── LICENSE └── main.go /importer/gccgoimporter/testdata/pointer.go: -------------------------------------------------------------------------------- 1 | package pointer 2 | 3 | type Int8Ptr *int8 4 | -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/conversions.go: -------------------------------------------------------------------------------- 1 | package conversions 2 | 3 | type Units string 4 | 5 | const Bits = Units("bits") 6 | -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/imports.go: -------------------------------------------------------------------------------- 1 | package imports 2 | 3 | import "fmt" 4 | 5 | var Hello = fmt.Sprintf("Hello, world") 6 | -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/time.gox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukechampine/ply/HEAD/importer/gccgoimporter/testdata/time.gox -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/unicode.gox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukechampine/ply/HEAD/importer/gccgoimporter/testdata/unicode.gox -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/pointer.gox: -------------------------------------------------------------------------------- 1 | v1; 2 | package pointer; 3 | pkgpath pointer; 4 | type >>; 5 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/versions/test_go1.7_0.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukechampine/ply/HEAD/importer/gcimporter/testdata/versions/test_go1.7_0.a -------------------------------------------------------------------------------- /importer/gcimporter/testdata/versions/test_go1.7_1.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lukechampine/ply/HEAD/importer/gcimporter/testdata/versions/test_go1.7_1.a -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/complexnums.go: -------------------------------------------------------------------------------- 1 | package complexnums 2 | 3 | const NN = -1 - 1i 4 | const NP = -1 + 1i 5 | const PN = 1 - 1i 6 | const PP = 1 + 1i 7 | -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/complexnums.gox: -------------------------------------------------------------------------------- 1 | v1; 2 | package complexnums; 3 | pkgpath complexnums; 4 | priority 1; 5 | const NN = -0.1E1-0.1E1i ; 6 | const NP = -0.1E1+0.1E1i ; 7 | const PN = 0.1E1-0.1E1i ; 8 | const PP = 0.1E1+0.1E1i ; 9 | -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/conversions.gox: -------------------------------------------------------------------------------- 1 | v2; 2 | package conversions; 3 | prefix go; 4 | package conversions go.conversions go.conversions; 5 | const Bits > = convert(, "bits"); 6 | type ; 7 | -------------------------------------------------------------------------------- /types/testdata/blank.src: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package _ /* ERROR invalid package name */ 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ldflags = -X main.githash=`git rev-parse HEAD` \ 2 | -X main.version=0.1.0 \ 3 | -X 'main.builddate=`date`' 4 | 5 | # all builds a binary with the current commit hash 6 | all: 7 | go install -ldflags "$(ldflags)" ./... 8 | 9 | lint: 10 | go vet ./... 11 | -------------------------------------------------------------------------------- /types/testdata/importdecl1b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importdecl1 6 | 7 | import . /* ERROR "imported but not used" */ "unsafe" 8 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/b.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Input for TestIssue13566 6 | 7 | package b 8 | 9 | import "./a" 10 | 11 | type A a.A 12 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/p.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Input for TestIssue15517 6 | 7 | package p 8 | 9 | const C = 0 10 | 11 | var V int 12 | 13 | func F() {} 14 | -------------------------------------------------------------------------------- /types/testdata/importdecl1a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Test case for issue 8969. 6 | 7 | package importdecl1 8 | 9 | import . "unsafe" 10 | 11 | var _ Pointer // use dot-imported package unsafe 12 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/a.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Input for TestIssue13566 6 | 7 | package a 8 | 9 | import "encoding/json" 10 | 11 | type A struct { 12 | a *A 13 | json json.RawMessage 14 | } 15 | -------------------------------------------------------------------------------- /importer/gccgoimporter/testdata/imports.gox: -------------------------------------------------------------------------------- 1 | v1; 2 | package imports; 3 | pkgpath imports; 4 | priority 7; 5 | import fmt fmt "fmt"; 6 | init imports imports..import 7 math math..import 1 runtime runtime..import 1 strconv strconv..import 2 io io..import 3 reflect reflect..import 3 syscall syscall..import 3 time time..import 4 os os..import 5 fmt fmt..import 6; 7 | var Hello ; 8 | -------------------------------------------------------------------------------- /types/testdata/importC.src: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importC 6 | 7 | import "C" 8 | import _ /* ERROR cannot rename import "C" */ "C" 9 | import foo /* ERROR cannot rename import "C" */ "C" 10 | import . /* ERROR cannot rename import "C" */ "C" 11 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/issue15920.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | // The underlying type of Error is the underlying type of error. 8 | // Make sure we can import this again without problems. 9 | type Error error 10 | 11 | func F() Error { return nil } 12 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/versions/test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // To create a test case for a new export format version, 6 | // build this package with the latest compiler and store 7 | // the resulting .a file appropriately named in the versions 8 | // directory. The VersionHandling test will pick it up. 9 | // 10 | // In the testdata/versions: 11 | // 12 | // go build -o test_go1.$X_$Y.a test.go 13 | // 14 | // with $X = Go version and $Y = export format version. 15 | // 16 | // Make sure this source is extended such that it exercises 17 | // whatever export format change has taken place. 18 | 19 | package test 20 | 21 | // Any release before and including Go 1.7 didn't encode 22 | // the package for a blank struct field. 23 | type BlankField struct { 24 | _ int 25 | } 26 | -------------------------------------------------------------------------------- /types/testdata/cycles3.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | import "unsafe" 8 | 9 | var ( 10 | _ A = A(nil).a().b().c().d().e().f() 11 | _ A = A(nil).b().c().d().e().f() 12 | _ A = A(nil).c().d().e().f() 13 | _ A = A(nil).d().e().f() 14 | _ A = A(nil).e().f() 15 | _ A = A(nil).f() 16 | _ A = A(nil) 17 | ) 18 | 19 | type ( 20 | A interface { 21 | a() B 22 | B 23 | } 24 | 25 | B interface { 26 | b() C 27 | C 28 | } 29 | 30 | C interface { 31 | c() D 32 | D 33 | } 34 | 35 | D interface { 36 | d() E 37 | E 38 | } 39 | 40 | E interface { 41 | e() F 42 | F 43 | } 44 | 45 | F interface { 46 | f() A 47 | } 48 | ) 49 | 50 | type ( 51 | U interface { 52 | V 53 | } 54 | 55 | V interface { 56 | v() [unsafe.Sizeof(u)]int 57 | } 58 | ) 59 | 60 | var u U 61 | -------------------------------------------------------------------------------- /types/objset.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements objsets. 6 | // 7 | // An objset is similar to a Scope but objset elements 8 | // are identified by their unique id, instead of their 9 | // object name. 10 | 11 | package types 12 | 13 | // An objset is a set of objects identified by their unique id. 14 | // The zero value for objset is a ready-to-use empty objset. 15 | type objset map[string]Object // initialized lazily 16 | 17 | // insert attempts to insert an object obj into objset s. 18 | // If s already contains an alternative object alt with 19 | // the same name, insert leaves s unchanged and returns alt. 20 | // Otherwise it inserts obj and returns nil. 21 | func (s *objset) insert(obj Object) Object { 22 | id := obj.Id() 23 | if alt := (*s)[id]; alt != nil { 24 | return alt 25 | } 26 | if *s == nil { 27 | *s = make(map[string]Object) 28 | } 29 | (*s)[id] = obj 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Luke Champine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /types/testdata/cycles1.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | type ( 8 | A interface { 9 | a() interface { 10 | ABC1 11 | } 12 | } 13 | B interface { 14 | b() interface { 15 | ABC2 16 | } 17 | } 18 | C interface { 19 | c() interface { 20 | ABC3 21 | } 22 | } 23 | 24 | AB interface { 25 | A 26 | B 27 | } 28 | BC interface { 29 | B 30 | C 31 | } 32 | 33 | ABC1 interface { 34 | A 35 | B 36 | C 37 | } 38 | ABC2 interface { 39 | AB 40 | C 41 | } 42 | ABC3 interface { 43 | A 44 | BC 45 | } 46 | ) 47 | 48 | var ( 49 | x1 ABC1 50 | x2 ABC2 51 | x3 ABC3 52 | ) 53 | 54 | func _() { 55 | // all types have the same method set 56 | x1 = x2 57 | x2 = x1 58 | 59 | x1 = x3 60 | x3 = x1 61 | 62 | x2 = x3 63 | x3 = x2 64 | 65 | // all methods return the same type again 66 | x1 = x1.a() 67 | x1 = x1.b() 68 | x1 = x1.c() 69 | 70 | x2 = x2.a() 71 | x2 = x2.b() 72 | x2 = x2.c() 73 | 74 | x3 = x3.a() 75 | x3 = x3.b() 76 | x3 = x3.c() 77 | } 78 | -------------------------------------------------------------------------------- /types/testdata/importdecl0b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importdecl0 6 | 7 | import "math" 8 | import m "math" 9 | 10 | import . "testing" // declares T in file scope 11 | import . /* ERROR "imported but not used" */ "unsafe" 12 | import . "fmt" // declares Println in file scope 13 | 14 | import ( 15 | // TODO(gri) At the moment, 2 errors are reported because both go/parser 16 | // and the type checker report it. Eventually, this test should not be 17 | // done by the parser anymore. 18 | "" /* ERROR invalid import path */ /* ERROR invalid import path */ 19 | "a!b" /* ERROR invalid import path */ /* ERROR invalid import path */ 20 | "abc\xffdef" /* ERROR invalid import path */ /* ERROR invalid import path */ 21 | ) 22 | 23 | // using "math" in this file doesn't affect its use in other files 24 | const Pi0 = math.Pi 25 | const Pi1 = m.Pi 26 | 27 | type _ T // use "testing" 28 | 29 | func _() func() interface{} { 30 | return func() interface{} { 31 | return Println // use "fmt" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /types/token_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file checks invariants of token.Token ordering that we rely on 6 | // since package go/token doesn't provide any guarantees at the moment. 7 | 8 | package types 9 | 10 | import ( 11 | "go/token" 12 | "testing" 13 | ) 14 | 15 | var assignOps = map[token.Token]token.Token{ 16 | token.ADD_ASSIGN: token.ADD, 17 | token.SUB_ASSIGN: token.SUB, 18 | token.MUL_ASSIGN: token.MUL, 19 | token.QUO_ASSIGN: token.QUO, 20 | token.REM_ASSIGN: token.REM, 21 | token.AND_ASSIGN: token.AND, 22 | token.OR_ASSIGN: token.OR, 23 | token.XOR_ASSIGN: token.XOR, 24 | token.SHL_ASSIGN: token.SHL, 25 | token.SHR_ASSIGN: token.SHR, 26 | token.AND_NOT_ASSIGN: token.AND_NOT, 27 | } 28 | 29 | func TestZeroTok(t *testing.T) { 30 | // zero value for token.Token must be token.ILLEGAL 31 | var zero token.Token 32 | if token.ILLEGAL != zero { 33 | t.Errorf("%s == %d; want 0", token.ILLEGAL, zero) 34 | } 35 | } 36 | 37 | func TestAssignOp(t *testing.T) { 38 | // there are fewer than 256 tokens 39 | for i := 0; i < 256; i++ { 40 | tok := token.Token(i) 41 | got := assignOp(tok) 42 | want := assignOps[tok] 43 | if got != want { 44 | t.Errorf("for assignOp(%s): got %s; want %s", tok, got, want) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /types/testdata/importdecl0a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package importdecl0 6 | 7 | import () 8 | 9 | import ( 10 | // we can have multiple blank imports (was bug) 11 | _ "math" 12 | _ "net/rpc" 13 | init /* ERROR "cannot declare init" */ "fmt" 14 | // reflect defines a type "flag" which shows up in the gc export data 15 | "reflect" 16 | . /* ERROR "imported but not used" */ "reflect" 17 | ) 18 | 19 | import "math" /* ERROR "imported but not used" */ 20 | import m /* ERROR "imported but not used as m" */ "math" 21 | import _ "math" 22 | 23 | import ( 24 | "math/big" /* ERROR "imported but not used" */ 25 | b /* ERROR "imported but not used" */ "math/big" 26 | _ "math/big" 27 | ) 28 | 29 | import "fmt" 30 | import f1 "fmt" 31 | import f2 "fmt" 32 | 33 | // reflect.flag must not be visible in this package 34 | type flag int 35 | type _ reflect /* ERROR "not exported" */ .flag 36 | 37 | // imported package name may conflict with local objects 38 | type reflect /* ERROR "reflect already declared" */ int 39 | 40 | // dot-imported exported objects may conflict with local objects 41 | type Value /* ERROR "Value already declared through dot-import of package reflect" */ struct{} 42 | 43 | var _ = fmt.Println // use "fmt" 44 | 45 | func _() { 46 | f1.Println() // use "fmt" 47 | } 48 | 49 | func _() { 50 | _ = func() { 51 | f2.Println() // use "fmt" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /importer/gcimporter/testdata/exports.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file is used to generate an object file which 6 | // serves as test file for gcimporter_test.go. 7 | 8 | package exports 9 | 10 | import "go/ast" 11 | 12 | // Issue 3682: Correctly read dotted identifiers from export data. 13 | const init1 = 0 14 | 15 | func init() {} 16 | 17 | const ( 18 | C0 int = 0 19 | C1 = 3.14159265 20 | C2 = 2.718281828i 21 | C3 = -123.456e-789 22 | C4 = +123.456E+789 23 | C5 = 1234i 24 | C6 = "foo\n" 25 | C7 = `bar\n` 26 | ) 27 | 28 | type ( 29 | T1 int 30 | T2 [10]int 31 | T3 []int 32 | T4 *int 33 | T5 chan int 34 | T6a chan<- int 35 | T6b chan (<-chan int) 36 | T6c chan<- (chan int) 37 | T7 <-chan *ast.File 38 | T8 struct{} 39 | T9 struct { 40 | a int 41 | b, c float32 42 | d []string `go:"tag"` 43 | } 44 | T10 struct { 45 | T8 46 | T9 47 | _ *T10 48 | } 49 | T11 map[int]string 50 | T12 interface{} 51 | T13 interface { 52 | m1() 53 | m2(int) float32 54 | } 55 | T14 interface { 56 | T12 57 | T13 58 | m3(x ...struct{}) []T9 59 | } 60 | T15 func() 61 | T16 func(int) 62 | T17 func(x int) 63 | T18 func() float32 64 | T19 func() (x float32) 65 | T20 func(...interface{}) 66 | T21 struct{ next *T21 } 67 | T22 struct{ link *T23 } 68 | T23 struct{ link *T22 } 69 | T24 *T24 70 | T25 *T26 71 | T26 *T27 72 | T27 *T25 73 | T28 func(T28) T28 74 | ) 75 | 76 | var ( 77 | V0 int 78 | V1 = -991.0 79 | V2 float32 = 1.2 80 | ) 81 | 82 | func F1() {} 83 | func F2(x int) {} 84 | func F3() int { return 0 } 85 | func F4() float32 { return 0 } 86 | func F5(a, b, c int, u, v, w struct{ x, y T1 }, more ...interface{}) (p, q, r chan<- T10) 87 | 88 | func (p *T1) M1() 89 | -------------------------------------------------------------------------------- /types/testdata/init1.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // initialization cycles 6 | 7 | package init1 8 | 9 | // issue 6683 (marked as WorkingAsIntended) 10 | 11 | type T0 struct{} 12 | 13 | func (T0) m() int { return y0 } 14 | 15 | var x0 = T0{} 16 | 17 | var y0 /* ERROR initialization cycle */ = x0.m() 18 | 19 | type T1 struct{} 20 | 21 | func (T1) m() int { return y1 } 22 | 23 | var x1 interface { 24 | m() int 25 | } = T1{} 26 | 27 | var y1 = x1.m() // no cycle reported, x1 is of interface type 28 | 29 | // issue 6703 (modified) 30 | 31 | var x2 /* ERROR initialization cycle */ = T2.m 32 | 33 | var y2 = x2 34 | 35 | type T2 struct{} 36 | 37 | func (T2) m() int { 38 | _ = y2 39 | return 0 40 | } 41 | 42 | var x3 /* ERROR initialization cycle */ = T3.m(T3{}) // <<<< added (T3{}) 43 | 44 | var y3 = x3 45 | 46 | type T3 struct{} 47 | 48 | func (T3) m() int { 49 | _ = y3 50 | return 0 51 | } 52 | 53 | var x4 /* ERROR initialization cycle */ = T4{}.m // <<<< added {} 54 | 55 | var y4 = x4 56 | 57 | type T4 struct{} 58 | 59 | func (T4) m() int { 60 | _ = y4 61 | return 0 62 | } 63 | 64 | var x5 /* ERROR initialization cycle */ = T5{}.m() // <<<< added () 65 | 66 | var y5 = x5 67 | 68 | type T5 struct{} 69 | 70 | func (T5) m() int { 71 | _ = y5 72 | return 0 73 | } 74 | 75 | // issue 4847 76 | // simplified test case 77 | 78 | var x6 = f6 79 | var y6 /* ERROR initialization cycle */ = f6 80 | func f6() { _ = y6 } 81 | 82 | // full test case 83 | 84 | type ( 85 | E int 86 | S int 87 | ) 88 | 89 | type matcher func(s *S) E 90 | 91 | func matchList(s *S) E { return matcher(matchAnyFn)(s) } 92 | 93 | var foo = matcher(matchList) 94 | 95 | var matchAny /* ERROR initialization cycle */ = matcher(matchList) 96 | 97 | func matchAnyFn(s *S) (err E) { return matchAny(s) } -------------------------------------------------------------------------------- /types/testdata/errors.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package errors 6 | 7 | // Testing precise operand formatting in error messages 8 | // (matching messages are regular expressions, hence the \'s). 9 | func f(x int, m map[string]int) { 10 | // no values 11 | _ = f /* ERROR "f\(0, m\) \(no value\) used as value" */ (0, m) 12 | 13 | // built-ins 14 | _ = println /* ERROR "println \(built-in\) must be called" */ 15 | 16 | // types 17 | _ = complex128 /* ERROR "complex128 \(type\) is not an expression" */ 18 | 19 | // constants 20 | const c1 = 991 21 | const c2 float32 = 0.5 22 | 0 /* ERROR "0 \(untyped int constant\) is not used" */ 23 | c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */ 24 | c2 /* ERROR "c2 \(constant 0.5 of type float32\) is not used" */ 25 | c1 /* ERROR "c1 \+ c2 \(constant 991.5 of type float32\) is not used" */ + c2 26 | 27 | // variables 28 | x /* ERROR "x \(variable of type int\) is not used" */ 29 | 30 | // values 31 | x /* ERROR "x != x \(untyped bool value\) is not used" */ != x 32 | x /* ERROR "x \+ x \(value of type int\) is not used" */ + x 33 | 34 | // value, ok's 35 | const s = "foo" 36 | m /* ERROR "m\[s\] \(map index expression of type int\) is not used" */ [s] 37 | } 38 | 39 | // Valid ERROR comments can have a variety of forms. 40 | func _() { 41 | 0 /* ERROR "0 .* is not used" */ 42 | 0 /* ERROR 0 .* is not used */ 43 | 0 // ERROR "0 .* is not used" 44 | 0 // ERROR 0 .* is not used 45 | } 46 | 47 | // Don't report spurious errors as a consequence of earlier errors. 48 | // Add more tests as needed. 49 | func _() { 50 | if err := foo /* ERROR undeclared */ (); err != nil /* no error here */ {} 51 | } 52 | 53 | // Use unqualified names for package-local objects. 54 | type T struct{} 55 | var _ int = T /* ERROR value of type T */ {} // use T in error message rather then errors.T 56 | -------------------------------------------------------------------------------- /types/testdata/decls2b.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // method declarations 6 | 7 | package decls2 8 | 9 | import "io" 10 | 11 | const pi = 3.1415 12 | 13 | func (T1) m /* ERROR "already declared" */ () {} 14 | func (T2) m(io.Writer) {} 15 | 16 | type T3 struct { 17 | f *T3 18 | } 19 | 20 | type T6 struct { 21 | x int 22 | } 23 | 24 | func (t *T6) m1() int { 25 | return t.x 26 | } 27 | 28 | func f() { 29 | var t *T6 30 | t.m1() 31 | } 32 | 33 | // Double declarations across package files 34 | const c_double /* ERROR "redeclared" */ = 0 35 | type t_double /* ERROR "redeclared" */ int 36 | var v_double /* ERROR "redeclared" */ int 37 | func f_double /* ERROR "redeclared" */ () {} 38 | 39 | // Blank methods need to be type-checked. 40 | // Verify by checking that errors are reported. 41 | func (T /* ERROR "undeclared" */ ) _() {} 42 | func (T1) _(undeclared /* ERROR "undeclared" */ ) {} 43 | func (T1) _() int { return "foo" /* ERROR "cannot convert" */ } 44 | 45 | // Methods with undeclared receiver type can still be checked. 46 | // Verify by checking that errors are reported. 47 | func (Foo /* ERROR "undeclared" */ ) m() {} 48 | func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {} 49 | func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot convert" */ } 50 | 51 | func (Foo /* ERROR "undeclared" */ ) _() {} 52 | func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {} 53 | func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot convert" */ } 54 | 55 | // Receiver declarations are regular parameter lists; 56 | // receiver types may use parentheses, and the list 57 | // may have a trailing comma. 58 | type T7 struct {} 59 | 60 | func (T7) m1() {} 61 | func ((T7)) m2() {} 62 | func ((*T7)) m3() {} 63 | func (x *(T7),) m4() {} 64 | func (x (*(T7)),) m5() {} 65 | func (x ((*((T7)))),) m6() {} 66 | -------------------------------------------------------------------------------- /types/testdata/conversions.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // conversions 6 | 7 | package conversions 8 | 9 | import "unsafe" 10 | 11 | // argument count 12 | var ( 13 | _ = int() /* ERROR "missing argument" */ 14 | _ = int(1, 2 /* ERROR "too many arguments" */ ) 15 | ) 16 | 17 | // numeric constant conversions are in const1.src. 18 | 19 | func string_conversions() { 20 | const A = string(65) 21 | assert(A == "A") 22 | const E = string(-1) 23 | assert(E == "\uFFFD") 24 | assert(E == string(1234567890)) 25 | 26 | type myint int 27 | assert(A == string(myint(65))) 28 | 29 | type mystring string 30 | const _ mystring = mystring("foo") 31 | 32 | const _ = string(true /* ERROR "cannot convert" */ ) 33 | const _ = string(1.2 /* ERROR "cannot convert" */ ) 34 | const _ = string(nil /* ERROR "cannot convert" */ ) 35 | 36 | // issues 11357, 11353: argument must be of integer type 37 | _ = string(0.0 /* ERROR "cannot convert" */ ) 38 | _ = string(0i /* ERROR "cannot convert" */ ) 39 | _ = string(1 /* ERROR "cannot convert" */ + 2i) 40 | } 41 | 42 | func interface_conversions() { 43 | type E interface{} 44 | 45 | type I1 interface{ 46 | m1() 47 | } 48 | 49 | type I2 interface{ 50 | m1() 51 | m2(x int) 52 | } 53 | 54 | type I3 interface{ 55 | m1() 56 | m2() int 57 | } 58 | 59 | var e E 60 | var i1 I1 61 | var i2 I2 62 | var i3 I3 63 | 64 | _ = E(0) 65 | _ = E(nil) 66 | _ = E(e) 67 | _ = E(i1) 68 | _ = E(i2) 69 | 70 | _ = I1(0 /* ERROR "cannot convert" */ ) 71 | _ = I1(nil) 72 | _ = I1(i1) 73 | _ = I1(e /* ERROR "cannot convert" */ ) 74 | _ = I1(i2) 75 | 76 | _ = I2(nil) 77 | _ = I2(i1 /* ERROR "cannot convert" */ ) 78 | _ = I2(i2) 79 | _ = I2(i3 /* ERROR "cannot convert" */ ) 80 | 81 | _ = I3(nil) 82 | _ = I3(i1 /* ERROR "cannot convert" */ ) 83 | _ = I3(i2 /* ERROR "cannot convert" */ ) 84 | _ = I3(i3) 85 | 86 | // TODO(gri) add more tests, improve error message 87 | } 88 | 89 | func issue6326() { 90 | type T unsafe.Pointer 91 | var x T 92 | _ = uintptr(x) // see issue 6326 93 | } 94 | -------------------------------------------------------------------------------- /types/exprstring_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types_test 6 | 7 | import ( 8 | "go/parser" 9 | "testing" 10 | 11 | . "go/types" 12 | ) 13 | 14 | var testExprs = []testEntry{ 15 | // basic type literals 16 | dup("x"), 17 | dup("true"), 18 | dup("42"), 19 | dup("3.1415"), 20 | dup("2.71828i"), 21 | dup(`'a'`), 22 | dup(`"foo"`), 23 | dup("`bar`"), 24 | 25 | // func and composite literals 26 | {"func(){}", "(func() literal)"}, 27 | {"func(x int) complex128 {}", "(func(x int) complex128 literal)"}, 28 | {"[]int{1, 2, 3}", "([]int literal)"}, 29 | 30 | // non-type expressions 31 | dup("(x)"), 32 | dup("x.f"), 33 | dup("a[i]"), 34 | 35 | dup("s[:]"), 36 | dup("s[i:]"), 37 | dup("s[:j]"), 38 | dup("s[i:j]"), 39 | dup("s[:j:k]"), 40 | dup("s[i:j:k]"), 41 | 42 | dup("x.(T)"), 43 | 44 | dup("x.([10]int)"), 45 | dup("x.([...]int)"), 46 | 47 | dup("x.(struct{})"), 48 | dup("x.(struct{x int; y, z float32; E})"), 49 | 50 | dup("x.(func())"), 51 | dup("x.(func(x int))"), 52 | dup("x.(func() int)"), 53 | dup("x.(func(x, y int, z float32) (r int))"), 54 | dup("x.(func(a, b, c int))"), 55 | dup("x.(func(x ...T))"), 56 | 57 | dup("x.(interface{})"), 58 | dup("x.(interface{m(); n(x int); E})"), 59 | dup("x.(interface{m(); n(x int) T; E; F})"), 60 | 61 | dup("x.(map[K]V)"), 62 | 63 | dup("x.(chan E)"), 64 | dup("x.(<-chan E)"), 65 | dup("x.(chan<- chan int)"), 66 | dup("x.(chan<- <-chan int)"), 67 | dup("x.(<-chan chan int)"), 68 | dup("x.(chan (<-chan int))"), 69 | 70 | dup("f()"), 71 | dup("f(x)"), 72 | dup("int(x)"), 73 | dup("f(x, x + y)"), 74 | dup("f(s...)"), 75 | dup("f(a, s...)"), 76 | 77 | dup("*x"), 78 | dup("&x"), 79 | dup("x + y"), 80 | dup("x + y << (2 * s)"), 81 | } 82 | 83 | func TestExprString(t *testing.T) { 84 | for _, test := range testExprs { 85 | x, err := parser.ParseExpr(test.src) 86 | if err != nil { 87 | t.Errorf("%s: %s", test.src, err) 88 | continue 89 | } 90 | if got := ExprString(x); got != test.str { 91 | t.Errorf("%s: got %s, want %s", test.src, got, test.str) 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /types/testdata/cycles4.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | // Check that all methods of T are collected before 8 | // determining the result type of m (which embeds 9 | // all methods of T). 10 | 11 | type T interface { 12 | m() interface {T} 13 | E 14 | } 15 | 16 | var _ = T.m(nil).m().e() 17 | 18 | type E interface { 19 | e() int 20 | } 21 | 22 | // Check that unresolved forward chains are followed 23 | // (see also comment in resolver.go, checker.typeDecl). 24 | 25 | var _ = C.m(nil).m().e() 26 | 27 | type A B 28 | 29 | type B interface { 30 | m() interface{C} 31 | E 32 | } 33 | 34 | type C A 35 | 36 | // Check that interface type comparison for identity 37 | // does not recur endlessly. 38 | 39 | type T1 interface { 40 | m() interface{T1} 41 | } 42 | 43 | type T2 interface { 44 | m() interface{T2} 45 | } 46 | 47 | func _(x T1, y T2) { 48 | // Checking for assignability of interfaces must check 49 | // if all methods of x are present in y, and that they 50 | // have identical signatures. The signatures recur via 51 | // the result type, which is an interface that embeds 52 | // a single method m that refers to the very interface 53 | // that contains it. This requires cycle detection in 54 | // identity checks for interface types. 55 | x = y 56 | } 57 | 58 | type T3 interface { 59 | m() interface{T4} 60 | } 61 | 62 | type T4 interface { 63 | m() interface{T3} 64 | } 65 | 66 | func _(x T1, y T3) { 67 | x = y 68 | } 69 | 70 | // Check that interfaces are type-checked in order of 71 | // (embedded interface) dependencies (was issue 7158). 72 | 73 | var x1 T5 = T7(nil) 74 | 75 | type T5 interface { 76 | T6 77 | } 78 | 79 | type T6 interface { 80 | m() T7 81 | } 82 | type T7 interface { 83 | T5 84 | } 85 | 86 | // Actual test case from issue 7158. 87 | 88 | func wrapNode() Node { 89 | return wrapElement() 90 | } 91 | 92 | func wrapElement() Element { 93 | return nil 94 | } 95 | 96 | type EventTarget interface { 97 | AddEventListener(Event) 98 | } 99 | 100 | type Node interface { 101 | EventTarget 102 | } 103 | 104 | type Element interface { 105 | Node 106 | } 107 | 108 | type Event interface { 109 | Target() Element 110 | } 111 | -------------------------------------------------------------------------------- /types/testdata/init0.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // initialization cycles 6 | 7 | package init0 8 | 9 | // initialization cycles (we don't know the types) 10 | const ( 11 | s0 /* ERROR initialization cycle */ = s0 12 | 13 | x0 /* ERROR initialization cycle */ = y0 14 | y0 = x0 15 | 16 | a0 = b0 17 | b0 /* ERROR initialization cycle */ = c0 18 | c0 = d0 19 | d0 = b0 20 | ) 21 | 22 | var ( 23 | s1 /* ERROR initialization cycle */ = s1 24 | 25 | x1 /* ERROR initialization cycle */ = y1 26 | y1 = x1 27 | 28 | a1 = b1 29 | b1 /* ERROR initialization cycle */ = c1 30 | c1 = d1 31 | d1 = b1 32 | ) 33 | 34 | // initialization cycles (we know the types) 35 | const ( 36 | s2 /* ERROR initialization cycle */ int = s2 37 | 38 | x2 /* ERROR initialization cycle */ int = y2 39 | y2 = x2 40 | 41 | a2 = b2 42 | b2 /* ERROR initialization cycle */ int = c2 43 | c2 = d2 44 | d2 = b2 45 | ) 46 | 47 | var ( 48 | s3 /* ERROR initialization cycle */ int = s3 49 | 50 | x3 /* ERROR initialization cycle */ int = y3 51 | y3 = x3 52 | 53 | a3 = b3 54 | b3 /* ERROR initialization cycle */ int = c3 55 | c3 = d3 56 | d3 = b3 57 | ) 58 | 59 | // cycles via struct fields 60 | 61 | type S1 struct { 62 | f int 63 | } 64 | const cx3 S1 /* ERROR invalid constant type */ = S1{cx3.f} 65 | var vx3 /* ERROR initialization cycle */ S1 = S1{vx3.f} 66 | 67 | // cycles via functions 68 | 69 | var x4 = x5 70 | var x5 /* ERROR initialization cycle */ = f1() 71 | func f1() int { return x5*10 } 72 | 73 | var x6, x7 /* ERROR initialization cycle */ = f2() 74 | var x8 = x7 75 | func f2() (int, int) { return f3() + f3(), 0 } 76 | func f3() int { return x8 } 77 | 78 | // cycles via closures 79 | 80 | var x9 /* ERROR initialization cycle */ = func() int { return x9 }() 81 | 82 | var x10 /* ERROR initialization cycle */ = f4() 83 | 84 | func f4() int { 85 | _ = func() { 86 | _ = x10 87 | } 88 | return 0 89 | } 90 | 91 | // cycles via method expressions 92 | 93 | type T1 struct{} 94 | 95 | func (T1) m() bool { _ = x11; return false } 96 | 97 | var x11 /* ERROR initialization cycle */ = T1.m(T1{}) 98 | 99 | // cycles via method values 100 | 101 | type T2 struct{} 102 | 103 | func (T2) m() bool { _ = x12; return false } 104 | 105 | var t1 T2 106 | var x12 /* ERROR initialization cycle */ = t1.m 107 | -------------------------------------------------------------------------------- /types/testdata/cycles2.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package p 6 | 7 | import "unsafe" 8 | 9 | // Test case for issue 5090 10 | 11 | type t interface { 12 | f(u) 13 | } 14 | 15 | type u interface { 16 | t 17 | } 18 | 19 | func _() { 20 | var t t 21 | var u u 22 | 23 | t.f(t) 24 | t.f(u) 25 | 26 | u.f(t) 27 | u.f(u) 28 | } 29 | 30 | 31 | // Test case for issue 6589. 32 | 33 | type A interface { 34 | a() interface { 35 | AB 36 | } 37 | } 38 | 39 | type B interface { 40 | a() interface { 41 | AB 42 | } 43 | } 44 | 45 | type AB interface { 46 | a() interface { 47 | A 48 | B /* ERROR a redeclared */ 49 | } 50 | b() interface { 51 | A 52 | B /* ERROR a redeclared */ 53 | } 54 | } 55 | 56 | var x AB 57 | var y interface { 58 | A 59 | B /* ERROR a redeclared */ 60 | } 61 | var _ = x /* ERROR cannot compare */ == y 62 | 63 | 64 | // Test case for issue 6638. 65 | 66 | type T interface { 67 | m() [T /* ERROR no value */ (nil).m()[0]]int 68 | } 69 | 70 | // Variations of this test case. 71 | 72 | type T1 interface { 73 | m() [x1 /* ERROR no value */ .m()[0]]int 74 | } 75 | 76 | var x1 T1 77 | 78 | type T2 interface { 79 | m() [len(x2 /* ERROR no value */ .m())]int 80 | } 81 | 82 | var x2 T2 83 | 84 | type T3 interface { 85 | m() [unsafe.Sizeof(x3.m)]int 86 | } 87 | 88 | var x3 T3 89 | 90 | // The test case below should also report an error for 91 | // the cast inside the T4 interface (like it does for the 92 | // variable initialization). The reason why it does not is 93 | // that inside T4, the method x4.m depends on T4 which is not 94 | // fully set up yet. The x4.m method happens to have an empty 95 | // signature which is why the cast is permitted. 96 | // TODO(gri) Consider marking methods as incomplete and provide 97 | // a better error message in that case. 98 | 99 | type T4 interface { 100 | m() [unsafe.Sizeof(cast4(x4.m))]int 101 | } 102 | 103 | var x4 T4 104 | var _ = cast4(x4 /* ERROR cannot convert */.m) 105 | 106 | type cast4 func() 107 | 108 | // This test is symmetric to the T4 case: Here the cast is 109 | // "correct", but it doesn't work inside the T5 interface. 110 | 111 | type T5 interface { 112 | m() [unsafe.Sizeof(cast5(x5 /* ERROR cannot convert */ .m))]int 113 | } 114 | 115 | var x5 T5 116 | var _ = cast5(x5.m) 117 | 118 | type cast5 func() [0]int 119 | -------------------------------------------------------------------------------- /types/package.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types 6 | 7 | import ( 8 | "fmt" 9 | "go/token" 10 | ) 11 | 12 | // A Package describes a Go package. 13 | type Package struct { 14 | path string 15 | name string 16 | scope *Scope 17 | complete bool 18 | imports []*Package 19 | fake bool // scope lookup errors are silently dropped if package is fake (internal use only) 20 | } 21 | 22 | // NewPackage returns a new Package for the given package path and name; 23 | // the name must not be the blank identifier. 24 | // The package is not complete and contains no explicit imports. 25 | func NewPackage(path, name string) *Package { 26 | if name == "_" { 27 | panic("invalid package name _") 28 | } 29 | scope := NewScope(Universe, token.NoPos, token.NoPos, fmt.Sprintf("package %q", path)) 30 | return &Package{path: path, name: name, scope: scope} 31 | } 32 | 33 | // Path returns the package path. 34 | func (pkg *Package) Path() string { return pkg.path } 35 | 36 | // Name returns the package name. 37 | func (pkg *Package) Name() string { return pkg.name } 38 | 39 | // SetName sets the package name. 40 | func (pkg *Package) SetName(name string) { pkg.name = name } 41 | 42 | // Scope returns the (complete or incomplete) package scope 43 | // holding the objects declared at package level (TypeNames, 44 | // Consts, Vars, and Funcs). 45 | func (pkg *Package) Scope() *Scope { return pkg.scope } 46 | 47 | // A package is complete if its scope contains (at least) all 48 | // exported objects; otherwise it is incomplete. 49 | func (pkg *Package) Complete() bool { return pkg.complete } 50 | 51 | // MarkComplete marks a package as complete. 52 | func (pkg *Package) MarkComplete() { pkg.complete = true } 53 | 54 | // Imports returns the list of packages directly imported by 55 | // pkg; the list is in source order. Package unsafe is excluded. 56 | // 57 | // If pkg was loaded from export data, Imports includes packages that 58 | // provide package-level objects referenced by pkg. This may be more or 59 | // less than the set of packages directly imported by pkg's source code. 60 | func (pkg *Package) Imports() []*Package { return pkg.imports } 61 | 62 | // SetImports sets the list of explicitly imported packages to list. 63 | // It is the caller's responsibility to make sure list elements are unique. 64 | func (pkg *Package) SetImports(list []*Package) { pkg.imports = list } 65 | 66 | func (pkg *Package) String() string { 67 | return fmt.Sprintf("package %s (%q)", pkg.name, pkg.path) 68 | } 69 | -------------------------------------------------------------------------------- /importer/gccgoimporter/gccgoinstallation.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gccgoimporter 6 | 7 | import ( 8 | "bufio" 9 | "github.com/lukechampine/ply/types" 10 | "os" 11 | "os/exec" 12 | "path/filepath" 13 | "strings" 14 | ) 15 | 16 | // Information about a specific installation of gccgo. 17 | type GccgoInstallation struct { 18 | // Version of gcc (e.g. 4.8.0). 19 | GccVersion string 20 | 21 | // Target triple (e.g. x86_64-unknown-linux-gnu). 22 | TargetTriple string 23 | 24 | // Built-in library paths used by this installation. 25 | LibPaths []string 26 | } 27 | 28 | // Ask the driver at the given path for information for this GccgoInstallation. 29 | func (inst *GccgoInstallation) InitFromDriver(gccgoPath string) (err error) { 30 | cmd := exec.Command(gccgoPath, "-###", "-S", "-x", "go", "-") 31 | stderr, err := cmd.StderrPipe() 32 | if err != nil { 33 | return 34 | } 35 | 36 | err = cmd.Start() 37 | if err != nil { 38 | return 39 | } 40 | 41 | scanner := bufio.NewScanner(stderr) 42 | for scanner.Scan() { 43 | line := scanner.Text() 44 | switch { 45 | case strings.HasPrefix(line, "Target: "): 46 | inst.TargetTriple = line[8:] 47 | 48 | case line[0] == ' ': 49 | args := strings.Fields(line) 50 | for _, arg := range args[1:] { 51 | if strings.HasPrefix(arg, "-L") { 52 | inst.LibPaths = append(inst.LibPaths, arg[2:]) 53 | } 54 | } 55 | } 56 | } 57 | 58 | stdout, err := exec.Command(gccgoPath, "-dumpversion").Output() 59 | if err != nil { 60 | return 61 | } 62 | inst.GccVersion = strings.TrimSpace(string(stdout)) 63 | 64 | return 65 | } 66 | 67 | // Return the list of export search paths for this GccgoInstallation. 68 | func (inst *GccgoInstallation) SearchPaths() (paths []string) { 69 | for _, lpath := range inst.LibPaths { 70 | spath := filepath.Join(lpath, "go", inst.GccVersion) 71 | fi, err := os.Stat(spath) 72 | if err != nil || !fi.IsDir() { 73 | continue 74 | } 75 | paths = append(paths, spath) 76 | 77 | spath = filepath.Join(spath, inst.TargetTriple) 78 | fi, err = os.Stat(spath) 79 | if err != nil || !fi.IsDir() { 80 | continue 81 | } 82 | paths = append(paths, spath) 83 | } 84 | 85 | paths = append(paths, inst.LibPaths...) 86 | 87 | return 88 | } 89 | 90 | // Return an importer that searches incpaths followed by the gcc installation's 91 | // built-in search paths and the current directory. 92 | func (inst *GccgoInstallation) GetImporter(incpaths []string, initmap map[*types.Package]InitData) Importer { 93 | return GetImporter(append(append(incpaths, inst.SearchPaths()...), "."), initmap) 94 | } 95 | -------------------------------------------------------------------------------- /importer/gcimporter/exportdata.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements FindExportData. 6 | 7 | package gcimporter 8 | 9 | import ( 10 | "bufio" 11 | "fmt" 12 | "io" 13 | "strconv" 14 | "strings" 15 | ) 16 | 17 | func readGopackHeader(r *bufio.Reader) (name string, size int, err error) { 18 | // See $GOROOT/include/ar.h. 19 | hdr := make([]byte, 16+12+6+6+8+10+2) 20 | _, err = io.ReadFull(r, hdr) 21 | if err != nil { 22 | return 23 | } 24 | // leave for debugging 25 | if false { 26 | fmt.Printf("header: %s", hdr) 27 | } 28 | s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10])) 29 | size, err = strconv.Atoi(s) 30 | if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' { 31 | err = fmt.Errorf("invalid archive header") 32 | return 33 | } 34 | name = strings.TrimSpace(string(hdr[:16])) 35 | return 36 | } 37 | 38 | // FindExportData positions the reader r at the beginning of the 39 | // export data section of an underlying GC-created object/archive 40 | // file by reading from it. The reader must be positioned at the 41 | // start of the file before calling this function. The hdr result 42 | // is the string before the export data, either "$$" or "$$B". 43 | // 44 | func FindExportData(r *bufio.Reader) (hdr string, err error) { 45 | // Read first line to make sure this is an object file. 46 | line, err := r.ReadSlice('\n') 47 | if err != nil { 48 | err = fmt.Errorf("can't find export data (%v)", err) 49 | return 50 | } 51 | 52 | if string(line) == "!\n" { 53 | // Archive file. Scan to __.PKGDEF. 54 | var name string 55 | if name, _, err = readGopackHeader(r); err != nil { 56 | return 57 | } 58 | 59 | // First entry should be __.PKGDEF. 60 | if name != "__.PKGDEF" { 61 | err = fmt.Errorf("go archive is missing __.PKGDEF") 62 | return 63 | } 64 | 65 | // Read first line of __.PKGDEF data, so that line 66 | // is once again the first line of the input. 67 | if line, err = r.ReadSlice('\n'); err != nil { 68 | err = fmt.Errorf("can't find export data (%v)", err) 69 | return 70 | } 71 | } 72 | 73 | // Now at __.PKGDEF in archive or still at beginning of file. 74 | // Either way, line should begin with "go object ". 75 | if !strings.HasPrefix(string(line), "go object ") { 76 | err = fmt.Errorf("not a Go object file") 77 | return 78 | } 79 | 80 | // Skip over object header to export data. 81 | // Begins after first line starting with $$. 82 | for line[0] != '$' { 83 | if line, err = r.ReadSlice('\n'); err != nil { 84 | err = fmt.Errorf("can't find export data (%v)", err) 85 | return 86 | } 87 | } 88 | hdr = string(line) 89 | 90 | return 91 | } 92 | -------------------------------------------------------------------------------- /types/self_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types_test 6 | 7 | import ( 8 | "flag" 9 | "fmt" 10 | "go/ast" 11 | "go/importer" 12 | "go/parser" 13 | "go/token" 14 | "path/filepath" 15 | "testing" 16 | "time" 17 | 18 | . "go/types" 19 | ) 20 | 21 | var benchmark = flag.Bool("b", false, "run benchmarks") 22 | 23 | func TestSelf(t *testing.T) { 24 | fset := token.NewFileSet() 25 | files, err := pkgFiles(fset, ".") 26 | if err != nil { 27 | t.Fatal(err) 28 | } 29 | 30 | conf := Config{Importer: importer.Default()} 31 | _, err = conf.Check("go/types", fset, files, nil) 32 | if err != nil { 33 | // Importing go/constant doesn't work in the 34 | // build dashboard environment. Don't report an error 35 | // for now so that the build remains green. 36 | // TODO(gri) fix this 37 | t.Log(err) // replace w/ t.Fatal eventually 38 | return 39 | } 40 | } 41 | 42 | func TestBenchmark(t *testing.T) { 43 | if !*benchmark { 44 | return 45 | } 46 | 47 | // We're not using testing's benchmarking mechanism directly 48 | // because we want custom output. 49 | 50 | for _, p := range []string{"types", "constant", filepath.Join("internal", "gcimporter")} { 51 | path := filepath.Join("..", p) 52 | runbench(t, path, false) 53 | runbench(t, path, true) 54 | fmt.Println() 55 | } 56 | } 57 | 58 | func runbench(t *testing.T, path string, ignoreFuncBodies bool) { 59 | fset := token.NewFileSet() 60 | files, err := pkgFiles(fset, path) 61 | if err != nil { 62 | t.Fatal(err) 63 | } 64 | 65 | b := testing.Benchmark(func(b *testing.B) { 66 | for i := 0; i < b.N; i++ { 67 | conf := Config{IgnoreFuncBodies: ignoreFuncBodies} 68 | conf.Check(path, fset, files, nil) 69 | } 70 | }) 71 | 72 | // determine line count 73 | lines := 0 74 | fset.Iterate(func(f *token.File) bool { 75 | lines += f.LineCount() 76 | return true 77 | }) 78 | 79 | d := time.Duration(b.NsPerOp()) 80 | fmt.Printf( 81 | "%s: %s for %d lines (%d lines/s), ignoreFuncBodies = %v\n", 82 | filepath.Base(path), d, lines, int64(float64(lines)/d.Seconds()), ignoreFuncBodies, 83 | ) 84 | } 85 | 86 | func pkgFiles(fset *token.FileSet, path string) ([]*ast.File, error) { 87 | filenames, err := pkgFilenames(path) // from stdlib_test.go 88 | if err != nil { 89 | return nil, err 90 | } 91 | 92 | var files []*ast.File 93 | for _, filename := range filenames { 94 | file, err := parser.ParseFile(fset, filename, nil, 0) 95 | if err != nil { 96 | return nil, err 97 | } 98 | files = append(files, file) 99 | } 100 | 101 | return files, nil 102 | } 103 | -------------------------------------------------------------------------------- /types/eval.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types 6 | 7 | import ( 8 | "fmt" 9 | "go/parser" 10 | "go/token" 11 | ) 12 | 13 | // Eval returns the type and, if constant, the value for the 14 | // expression expr, evaluated at position pos of package pkg, 15 | // which must have been derived from type-checking an AST with 16 | // complete position information relative to the provided file 17 | // set. 18 | // 19 | // If the expression contains function literals, their bodies 20 | // are ignored (i.e., the bodies are not type-checked). 21 | // 22 | // If pkg == nil, the Universe scope is used and the provided 23 | // position pos is ignored. If pkg != nil, and pos is invalid, 24 | // the package scope is used. Otherwise, pos must belong to the 25 | // package. 26 | // 27 | // An error is returned if pos is not within the package or 28 | // if the node cannot be evaluated. 29 | // 30 | // Note: Eval should not be used instead of running Check to compute 31 | // types and values, but in addition to Check. Eval will re-evaluate 32 | // its argument each time, and it also does not know about the context 33 | // in which an expression is used (e.g., an assignment). Thus, top- 34 | // level untyped constants will return an untyped type rather then the 35 | // respective context-specific type. 36 | // 37 | func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAndValue, error) { 38 | // determine scope 39 | var scope *Scope 40 | if pkg == nil { 41 | scope = Universe 42 | pos = token.NoPos 43 | } else if !pos.IsValid() { 44 | scope = pkg.scope 45 | } else { 46 | // The package scope extent (position information) may be 47 | // incorrect (files spread across a wide range of fset 48 | // positions) - ignore it and just consider its children 49 | // (file scopes). 50 | for _, fscope := range pkg.scope.children { 51 | if scope = fscope.Innermost(pos); scope != nil { 52 | break 53 | } 54 | } 55 | if scope == nil || debug { 56 | s := scope 57 | for s != nil && s != pkg.scope { 58 | s = s.parent 59 | } 60 | // s == nil || s == pkg.scope 61 | if s == nil { 62 | return TypeAndValue{}, fmt.Errorf("no position %s found in package %s", fset.Position(pos), pkg.name) 63 | } 64 | } 65 | } 66 | 67 | // parse expressions 68 | node, err := parser.ParseExprFrom(fset, "eval", expr, 0) 69 | if err != nil { 70 | return TypeAndValue{}, err 71 | } 72 | 73 | // initialize checker 74 | check := NewChecker(nil, fset, pkg, nil) 75 | check.scope = scope 76 | check.pos = pos 77 | defer check.handleBailout(&err) 78 | 79 | // evaluate node 80 | var x operand 81 | check.rawExpr(&x, node, nil) 82 | return TypeAndValue{x.mode, x.typ, x.val}, err 83 | } 84 | -------------------------------------------------------------------------------- /types/testdata/cycles.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package cycles 6 | 7 | type ( 8 | T0 int 9 | T1 /* ERROR cycle */ T1 10 | T2 *T2 11 | 12 | T3 /* ERROR cycle */ T4 13 | T4 T5 14 | T5 T3 15 | 16 | T6 T7 17 | T7 *T8 18 | T8 T6 19 | 20 | // arrays 21 | A0 /* ERROR cycle */ [10]A0 22 | A1 [10]*A1 23 | 24 | A2 /* ERROR cycle */ [10]A3 25 | A3 [10]A4 26 | A4 A2 27 | 28 | A5 [10]A6 29 | A6 *A5 30 | 31 | // slices 32 | L0 []L0 33 | 34 | // structs 35 | S0 /* ERROR cycle */ struct{ _ S0 } 36 | S1 /* ERROR cycle */ struct{ S1 } 37 | S2 struct{ _ *S2 } 38 | S3 struct{ *S3 } 39 | 40 | S4 /* ERROR cycle */ struct{ S5 } 41 | S5 struct{ S6 } 42 | S6 S4 43 | 44 | // pointers 45 | P0 *P0 46 | 47 | // functions 48 | F0 func(F0) 49 | F1 func() F1 50 | F2 func(F2) F2 51 | 52 | // interfaces 53 | I0 /* ERROR cycle */ interface{ I0 } 54 | 55 | I1 interface{ I2 } 56 | I2 interface{ I3 } 57 | I3 /* ERROR cycle */ interface{ I1 } 58 | 59 | I4 interface{ f(I4) } 60 | 61 | // testcase for issue 5090 62 | I5 interface{ f(I6) } 63 | I6 interface{ I5 } 64 | 65 | // maps 66 | M0 map[M0 /* ERROR invalid map key */ ]M0 67 | 68 | // channels 69 | C0 chan C0 70 | ) 71 | 72 | func _() { 73 | type ( 74 | t1 /* ERROR cycle */ t1 75 | t2 *t2 76 | 77 | t3 t4 /* ERROR undeclared */ 78 | t4 t5 /* ERROR undeclared */ 79 | t5 t3 80 | 81 | // arrays 82 | a0 /* ERROR cycle */ [10]a0 83 | a1 [10]*a1 84 | 85 | // slices 86 | l0 []l0 87 | 88 | // structs 89 | s0 /* ERROR cycle */ struct{ _ s0 } 90 | s1 /* ERROR cycle */ struct{ s1 } 91 | s2 struct{ _ *s2 } 92 | s3 struct{ *s3 } 93 | 94 | // pointers 95 | p0 *p0 96 | 97 | // functions 98 | f0 func(f0) 99 | f1 func() f1 100 | f2 func(f2) f2 101 | 102 | // interfaces 103 | i0 /* ERROR cycle */ interface{ i0 } 104 | 105 | // maps 106 | m0 map[m0 /* ERROR invalid map key */ ]m0 107 | 108 | // channels 109 | c0 chan c0 110 | ) 111 | } 112 | 113 | // test cases for issue 6667 114 | 115 | type A [10]map[A /* ERROR invalid map key */ ]bool 116 | 117 | type S struct { 118 | m map[S /* ERROR invalid map key */ ]bool 119 | } 120 | 121 | // test cases for issue 7236 122 | // (cycle detection must not be dependent on starting point of resolution) 123 | 124 | type ( 125 | P1 *T9 126 | T9 /* ERROR cycle */ T9 127 | 128 | T10 /* ERROR cycle */ T10 129 | P2 *T10 130 | ) 131 | 132 | func (T11) m() {} 133 | 134 | type T11 /* ERROR cycle */ struct{ T11 } 135 | 136 | type T12 /* ERROR cycle */ struct{ T12 } 137 | 138 | func (*T12) m() {} 139 | 140 | type ( 141 | P3 *T13 142 | T13 /* ERROR cycle */ T13 143 | ) -------------------------------------------------------------------------------- /importer/importer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package importer provides access to export data importers. 6 | package importer 7 | 8 | import ( 9 | "io" 10 | "runtime" 11 | 12 | "github.com/lukechampine/ply/importer/gccgoimporter" 13 | "github.com/lukechampine/ply/importer/gcimporter" 14 | "github.com/lukechampine/ply/types" 15 | ) 16 | 17 | // A Lookup function returns a reader to access package data for 18 | // a given import path, or an error if no matching package is found. 19 | type Lookup func(path string) (io.ReadCloser, error) 20 | 21 | // For returns an Importer for the given compiler and lookup interface, 22 | // or nil. Supported compilers are "gc", and "gccgo". If lookup is nil, 23 | // the default package lookup mechanism for the given compiler is used. 24 | // BUG(issue13847): For does not support non-nil lookup functions. 25 | func For(compiler string, lookup Lookup) types.Importer { 26 | switch compiler { 27 | case "gc": 28 | if lookup != nil { 29 | panic("gc importer for custom import path lookup not yet implemented") 30 | } 31 | 32 | return make(gcimports) 33 | 34 | case "gccgo": 35 | if lookup != nil { 36 | panic("gccgo importer for custom import path lookup not yet implemented") 37 | } 38 | 39 | var inst gccgoimporter.GccgoInstallation 40 | if err := inst.InitFromDriver("gccgo"); err != nil { 41 | return nil 42 | } 43 | return &gccgoimports{ 44 | packages: make(map[string]*types.Package), 45 | importer: inst.GetImporter(nil, nil), 46 | } 47 | } 48 | 49 | // compiler not supported 50 | return nil 51 | } 52 | 53 | // Default returns an Importer for the compiler that built the running binary. 54 | // If available, the result implements types.ImporterFrom. 55 | func Default() types.Importer { 56 | return For(runtime.Compiler, nil) 57 | } 58 | 59 | // gc support 60 | 61 | type gcimports map[string]*types.Package 62 | 63 | func (m gcimports) Import(path string) (*types.Package, error) { 64 | return m.ImportFrom(path, "" /* no vendoring */, 0) 65 | } 66 | 67 | func (m gcimports) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) { 68 | if mode != 0 { 69 | panic("mode must be 0") 70 | } 71 | return gcimporter.Import(m, path, srcDir) 72 | } 73 | 74 | // gccgo support 75 | 76 | type gccgoimports struct { 77 | packages map[string]*types.Package 78 | importer gccgoimporter.Importer 79 | } 80 | 81 | func (m *gccgoimports) Import(path string) (*types.Package, error) { 82 | return m.ImportFrom(path, "" /* no vendoring */, 0) 83 | } 84 | 85 | func (m *gccgoimports) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) { 86 | if mode != 0 { 87 | panic("mode must be 0") 88 | } 89 | // TODO(gri) pass srcDir 90 | return m.importer(m.packages, path) 91 | } 92 | -------------------------------------------------------------------------------- /types/testdata/constdecl.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package constdecl 6 | 7 | import "math" 8 | 9 | var v int 10 | 11 | // Const decls must be initialized by constants. 12 | const _ = v /* ERROR "not constant" */ 13 | const _ = math /* ERROR "not constant" */ .Sin(0) 14 | const _ = int /* ERROR "not an expression" */ 15 | 16 | func _() { 17 | const _ = v /* ERROR "not constant" */ 18 | const _ = math /* ERROR "not constant" */ .Sin(0) 19 | const _ = int /* ERROR "not an expression" */ 20 | } 21 | 22 | // Identifier and expression arity must match. 23 | // The first error message is produced by the parser. 24 | // In a real-world scenario, the type-checker would not be run 25 | // in this case and the 2nd error message would not appear. 26 | const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ 27 | const _ = 1, 2 /* ERROR "extra init expr 2" */ 28 | 29 | const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int 30 | const _ int = 1, 2 /* ERROR "extra init expr 2" */ 31 | 32 | const ( 33 | _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ 34 | _ = 1, 2 /* ERROR "extra init expr 2" */ 35 | 36 | _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int 37 | _ int = 1, 2 /* ERROR "extra init expr 2" */ 38 | ) 39 | 40 | const ( 41 | _ = 1 42 | _ 43 | _, _ /* ERROR "missing init expr for _" */ 44 | _ 45 | ) 46 | 47 | const ( 48 | _, _ = 1, 2 49 | _, _ 50 | _ /* ERROR "extra init expr at" */ 51 | _, _ 52 | _, _, _ /* ERROR "missing init expr for _" */ 53 | _, _ 54 | ) 55 | 56 | func _() { 57 | const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ 58 | const _ = 1, 2 /* ERROR "extra init expr 2" */ 59 | 60 | const _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int 61 | const _ int = 1, 2 /* ERROR "extra init expr 2" */ 62 | 63 | const ( 64 | _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ 65 | _ = 1, 2 /* ERROR "extra init expr 2" */ 66 | 67 | _ /* ERROR "missing constant value" */ /* ERROR "missing init expr for _" */ int 68 | _ int = 1, 2 /* ERROR "extra init expr 2" */ 69 | ) 70 | 71 | const ( 72 | _ = 1 73 | _ 74 | _, _ /* ERROR "missing init expr for _" */ 75 | _ 76 | ) 77 | 78 | const ( 79 | _, _ = 1, 2 80 | _, _ 81 | _ /* ERROR "extra init expr at" */ 82 | _, _ 83 | _, _, _ /* ERROR "missing init expr for _" */ 84 | _, _ 85 | ) 86 | } 87 | 88 | // Test case for constant with invalid initialization. 89 | // Caused panic because the constant value was not set up (gri - 7/8/2014). 90 | func _() { 91 | const ( 92 | x string = missing /* ERROR "undeclared name" */ 93 | y = x + "" 94 | ) 95 | } 96 | 97 | // TODO(gri) move extra tests from testdata/const0.src into here 98 | -------------------------------------------------------------------------------- /importer/gccgoimporter/parser_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gccgoimporter 6 | 7 | import ( 8 | "bytes" 9 | "github.com/lukechampine/ply/types" 10 | "strings" 11 | "testing" 12 | "text/scanner" 13 | ) 14 | 15 | var typeParserTests = []struct { 16 | id, typ, want, underlying, methods string 17 | }{ 18 | {id: "foo", typ: "", want: "int8"}, 19 | {id: "foo", typ: ">", want: "*error"}, 20 | {id: "foo", typ: "", want: "unsafe.Pointer"}, 21 | {id: "foo", typ: ">>", want: "foo.Bar", underlying: "*foo.Bar"}, 22 | {id: "foo", typ: " func (? ) M (); >", want: "bar.Foo", underlying: "int8", methods: "func (bar.Foo).M()"}, 23 | {id: "foo", typ: ">", want: "bar.foo", underlying: "int8"}, 24 | {id: "foo", typ: ">", want: "[]int8"}, 25 | {id: "foo", typ: ">", want: "[42]int8"}, 26 | {id: "foo", typ: "] >", want: "map[int8]int16"}, 27 | {id: "foo", typ: ">", want: "chan int8"}, 28 | {id: "foo", typ: ">", want: "<-chan int8"}, 29 | {id: "foo", typ: ">", want: "chan<- int8"}, 30 | {id: "foo", typ: "; I16 \"i16\"; }>", want: "struct{I8 int8; I16 int16 \"i16\"}"}, 31 | {id: "foo", typ: ", b ) ; Bar (? , ? ...) (? , ? ); Baz (); }>", want: "interface{Bar(int16, ...int8) (int16, int8); Baz(); Foo(a int8, b int16) int8}"}, 32 | {id: "foo", typ: ") >", want: "func(int8) int16"}, 33 | } 34 | 35 | func TestTypeParser(t *testing.T) { 36 | for _, test := range typeParserTests { 37 | var p parser 38 | p.init("test.gox", strings.NewReader(test.typ), make(map[string]*types.Package)) 39 | p.pkgname = test.id 40 | p.pkgpath = test.id 41 | p.maybeCreatePackage() 42 | typ := p.parseType(p.pkg) 43 | 44 | if p.tok != scanner.EOF { 45 | t.Errorf("expected full parse, stopped at %q", p.lit) 46 | } 47 | 48 | got := typ.String() 49 | if got != test.want { 50 | t.Errorf("got type %q, expected %q", got, test.want) 51 | } 52 | 53 | if test.underlying != "" { 54 | underlying := typ.Underlying().String() 55 | if underlying != test.underlying { 56 | t.Errorf("got underlying type %q, expected %q", underlying, test.underlying) 57 | } 58 | } 59 | 60 | if test.methods != "" { 61 | nt := typ.(*types.Named) 62 | var buf bytes.Buffer 63 | for i := 0; i != nt.NumMethods(); i++ { 64 | buf.WriteString(nt.Method(i).String()) 65 | } 66 | methods := buf.String() 67 | if methods != test.methods { 68 | t.Errorf("got methods %q, expected %q", methods, test.methods) 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /types/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements various error reporters. 6 | 7 | package types 8 | 9 | import ( 10 | "fmt" 11 | "go/ast" 12 | "go/token" 13 | "strings" 14 | ) 15 | 16 | func assert(p bool) { 17 | if !p { 18 | panic("assertion failed") 19 | } 20 | } 21 | 22 | func unreachable() { 23 | panic("unreachable") 24 | } 25 | 26 | func (check *Checker) qualifier(pkg *Package) string { 27 | if pkg != check.pkg { 28 | return pkg.path 29 | } 30 | return "" 31 | } 32 | 33 | func (check *Checker) sprintf(format string, args ...interface{}) string { 34 | for i, arg := range args { 35 | switch a := arg.(type) { 36 | case nil: 37 | arg = "" 38 | case operand: 39 | panic("internal error: should always pass *operand") 40 | case *operand: 41 | arg = operandString(a, check.qualifier) 42 | case token.Pos: 43 | arg = check.fset.Position(a).String() 44 | case ast.Expr: 45 | arg = ExprString(a) 46 | case Object: 47 | arg = ObjectString(a, check.qualifier) 48 | case Type: 49 | arg = TypeString(a, check.qualifier) 50 | } 51 | args[i] = arg 52 | } 53 | return fmt.Sprintf(format, args...) 54 | } 55 | 56 | func (check *Checker) trace(pos token.Pos, format string, args ...interface{}) { 57 | fmt.Printf("%s:\t%s%s\n", 58 | check.fset.Position(pos), 59 | strings.Repeat(". ", check.indent), 60 | check.sprintf(format, args...), 61 | ) 62 | } 63 | 64 | // dump is only needed for debugging 65 | func (check *Checker) dump(format string, args ...interface{}) { 66 | fmt.Println(check.sprintf(format, args...)) 67 | } 68 | 69 | func (check *Checker) err(pos token.Pos, msg string, soft bool) { 70 | err := Error{check.fset, pos, msg, soft} 71 | if check.firstErr == nil { 72 | check.firstErr = err 73 | } 74 | f := check.conf.Error 75 | if f == nil { 76 | panic(bailout{}) // report only first error 77 | } 78 | f(err) 79 | } 80 | 81 | func (check *Checker) error(pos token.Pos, msg string) { 82 | check.err(pos, msg, false) 83 | } 84 | 85 | func (check *Checker) errorf(pos token.Pos, format string, args ...interface{}) { 86 | check.err(pos, check.sprintf(format, args...), false) 87 | } 88 | 89 | func (check *Checker) softErrorf(pos token.Pos, format string, args ...interface{}) { 90 | check.err(pos, check.sprintf(format, args...), true) 91 | } 92 | 93 | func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) { 94 | check.errorf(pos, "invalid AST: "+format, args...) 95 | } 96 | 97 | func (check *Checker) invalidArg(pos token.Pos, format string, args ...interface{}) { 98 | check.errorf(pos, "invalid argument: "+format, args...) 99 | } 100 | 101 | func (check *Checker) invalidOp(pos token.Pos, format string, args ...interface{}) { 102 | check.errorf(pos, "invalid operation: "+format, args...) 103 | } 104 | -------------------------------------------------------------------------------- /types/testdata/expr1.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // binary expressions 6 | 7 | package expr1 8 | 9 | type mybool bool 10 | 11 | func _(x, y bool, z mybool) { 12 | x = x || y 13 | x = x || true 14 | x = x || false 15 | x = x && y 16 | x = x && true 17 | x = x && false 18 | 19 | z = z /* ERROR mismatched types */ || y 20 | z = z || true 21 | z = z || false 22 | z = z /* ERROR mismatched types */ && y 23 | z = z && true 24 | z = z && false 25 | } 26 | 27 | type myint int 28 | 29 | func _(x, y int, z myint) { 30 | x = x + 1 31 | x = x + 1.0 32 | x = x + 1.1 // ERROR truncated to int 33 | x = x + y 34 | x = x - y 35 | x = x * y 36 | x = x / y 37 | x = x % y 38 | x = x << y // ERROR must be unsigned integer 39 | x = x >> y // ERROR must be unsigned integer 40 | 41 | z = z + 1 42 | z = z + 1.0 43 | z = z + 1.1 // ERROR truncated to int 44 | z = z /* ERROR mismatched types */ + y 45 | z = z /* ERROR mismatched types */ - y 46 | z = z /* ERROR mismatched types */ * y 47 | z = z /* ERROR mismatched types */ / y 48 | z = z /* ERROR mismatched types */ % y 49 | z = z << y // ERROR must be unsigned integer 50 | z = z >> y // ERROR must be unsigned integer 51 | } 52 | 53 | type myuint uint 54 | 55 | func _(x, y uint, z myuint) { 56 | x = x + 1 57 | x = x + - /* ERROR overflows uint */ 1 58 | x = x + 1.0 59 | x = x + 1.1 // ERROR truncated to uint 60 | x = x + y 61 | x = x - y 62 | x = x * y 63 | x = x / y 64 | x = x % y 65 | x = x << y 66 | x = x >> y 67 | 68 | z = z + 1 69 | z = x + - /* ERROR overflows uint */ 1 70 | z = z + 1.0 71 | z = z + 1.1 // ERROR truncated to uint 72 | z = z /* ERROR mismatched types */ + y 73 | z = z /* ERROR mismatched types */ - y 74 | z = z /* ERROR mismatched types */ * y 75 | z = z /* ERROR mismatched types */ / y 76 | z = z /* ERROR mismatched types */ % y 77 | z = z << y 78 | z = z >> y 79 | } 80 | 81 | type myfloat64 float64 82 | 83 | func _(x, y float64, z myfloat64) { 84 | x = x + 1 85 | x = x + -1 86 | x = x + 1.0 87 | x = x + 1.1 88 | x = x + y 89 | x = x - y 90 | x = x * y 91 | x = x / y 92 | x = x /* ERROR not defined */ % y 93 | x = x /* ERROR operand x .* must be integer */ << y 94 | x = x /* ERROR operand x .* must be integer */ >> y 95 | 96 | z = z + 1 97 | z = z + -1 98 | z = z + 1.0 99 | z = z + 1.1 100 | z = z /* ERROR mismatched types */ + y 101 | z = z /* ERROR mismatched types */ - y 102 | z = z /* ERROR mismatched types */ * y 103 | z = z /* ERROR mismatched types */ / y 104 | z = z /* ERROR mismatched types */ % y 105 | z = z /* ERROR operand z .* must be integer */ << y 106 | z = z /* ERROR operand z .* must be integer */ >> y 107 | } 108 | 109 | type mystring string 110 | 111 | func _(x, y string, z mystring) { 112 | x = x + "foo" 113 | x = x /* ERROR not defined */ - "foo" 114 | x = x + 1 // ERROR cannot convert 115 | x = x + y 116 | x = x /* ERROR not defined */ - y 117 | x = x * 10 // ERROR cannot convert 118 | } 119 | 120 | func f() (a, b int) { return } 121 | 122 | func _(x int) { 123 | _ = f /* ERROR 2-valued f */ () + 1 124 | _ = x + f /* ERROR 2-valued f */ () 125 | _ = f /* ERROR 2-valued f */ () + f 126 | _ = f /* ERROR 2-valued f */ () + f /* ERROR 2-valued f */ () 127 | } 128 | -------------------------------------------------------------------------------- /types/testdata/decls2a.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // method declarations 6 | 7 | package decls2 8 | 9 | import "time" 10 | import "unsafe" 11 | 12 | // T1 declared before its methods. 13 | type T1 struct{ 14 | f int 15 | } 16 | 17 | func (T1) m() {} 18 | func (T1) m /* ERROR "already declared" */ () {} 19 | func (x *T1) f /* ERROR "field and method" */ () {} 20 | 21 | // Conflict between embedded field and method name, 22 | // with the embedded field being a basic type. 23 | type T1b struct { 24 | int 25 | } 26 | 27 | func (T1b) int /* ERROR "field and method" */ () {} 28 | 29 | type T1c struct { 30 | time.Time 31 | } 32 | 33 | func (T1c) Time /* ERROR "field and method" */ () int { return 0 } 34 | 35 | // Disabled for now: LookupFieldOrMethod will find Pointer even though 36 | // it's double-declared (it would cost extra in the common case to verify 37 | // this). But the MethodSet computation will not find it due to the name 38 | // collision caused by the double-declaration, leading to an internal 39 | // inconsistency while we are verifying one computation against the other. 40 | // var _ = T1c{}.Pointer 41 | 42 | // T2's method declared before the type. 43 | func (*T2) f /* ERROR "field and method" */ () {} 44 | 45 | type T2 struct { 46 | f int 47 | } 48 | 49 | // Methods declared without a declared type. 50 | func (undeclared /* ERROR "undeclared" */) m() {} 51 | func (x *undeclared /* ERROR "undeclared" */) m() {} 52 | 53 | func (pi /* ERROR "not a type" */) m1() {} 54 | func (x pi /* ERROR "not a type" */) m2() {} 55 | func (x *pi /* ERROR "not a type" */ ) m3() {} 56 | 57 | // Blank types. 58 | type _ struct { m int } 59 | type _ struct { m int } 60 | 61 | func (_ /* ERROR "cannot use _" */) m() {} 62 | func m(_ /* ERROR "cannot use _" */) {} 63 | 64 | // Methods with receiver base type declared in another file. 65 | func (T3) m1() {} 66 | func (*T3) m2() {} 67 | func (x T3) m3() {} 68 | func (x *T3) f /* ERROR "field and method" */ () {} 69 | 70 | // Methods of non-struct type. 71 | type T4 func() 72 | 73 | func (self T4) m() func() { return self } 74 | 75 | // Methods associated with an interface. 76 | type T5 interface { 77 | m() int 78 | } 79 | 80 | func (T5 /* ERROR "invalid receiver" */ ) m1() {} 81 | func (T5 /* ERROR "invalid receiver" */ ) m2() {} 82 | 83 | // Methods associated with a named pointer type. 84 | type ptr *int 85 | func (ptr /* ERROR "invalid receiver" */ ) _() {} 86 | func (* /* ERROR "invalid receiver" */ ptr) _() {} 87 | 88 | // Methods with zero or multiple receivers. 89 | func ( /* ERROR "missing receiver" */ ) _() {} 90 | func (T3, * /* ERROR "exactly one receiver" */ T3) _() {} 91 | func (T3, T3, T3 /* ERROR "exactly one receiver" */ ) _() {} 92 | func (a, b /* ERROR "exactly one receiver" */ T3) _() {} 93 | func (a, b, c /* ERROR "exactly one receiver" */ T3) _() {} 94 | 95 | // Methods associated with non-local or unnamed types. 96 | func (int /* ERROR "invalid receiver" */ ) m() {} 97 | func ([ /* ERROR "invalid receiver" */ ]int) m() {} 98 | func (time /* ERROR "invalid receiver" */ .Time) m() {} 99 | func (* /* ERROR "invalid receiver" */ time.Time) m() {} 100 | func (x /* ERROR "invalid receiver" */ interface{}) m() {} 101 | 102 | // Unsafe.Pointer is treated like a pointer when used as receiver type. 103 | type UP unsafe.Pointer 104 | func (UP /* ERROR "invalid" */ ) m1() {} 105 | func (* /* ERROR "invalid" */ UP) m2() {} 106 | 107 | // Double declarations across package files 108 | const c_double = 0 109 | type t_double int 110 | var v_double int 111 | func f_double() {} 112 | -------------------------------------------------------------------------------- /types/ordering.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements resolveOrder. 6 | 7 | package types 8 | 9 | import ( 10 | "go/ast" 11 | "sort" 12 | ) 13 | 14 | // resolveOrder computes the order in which package-level objects 15 | // must be type-checked. 16 | // 17 | // Interface types appear first in the list, sorted topologically 18 | // by dependencies on embedded interfaces that are also declared 19 | // in this package, followed by all other objects sorted in source 20 | // order. 21 | // 22 | // TODO(gri) Consider sorting all types by dependencies here, and 23 | // in the process check _and_ report type cycles. This may simplify 24 | // the full type-checking phase. 25 | // 26 | func (check *Checker) resolveOrder() []Object { 27 | var ifaces, others []Object 28 | 29 | // collect interface types with their dependencies, and all other objects 30 | for obj := range check.objMap { 31 | if ityp := check.interfaceFor(obj); ityp != nil { 32 | ifaces = append(ifaces, obj) 33 | // determine dependencies on embedded interfaces 34 | for _, f := range ityp.Methods.List { 35 | if len(f.Names) == 0 { 36 | // Embedded interface: The type must be a (possibly 37 | // qualified) identifier denoting another interface. 38 | // Imported interfaces are already fully resolved, 39 | // so we can ignore qualified identifiers. 40 | if ident, _ := f.Type.(*ast.Ident); ident != nil { 41 | embedded := check.pkg.scope.Lookup(ident.Name) 42 | if check.interfaceFor(embedded) != nil { 43 | check.objMap[obj].addDep(embedded) 44 | } 45 | } 46 | } 47 | } 48 | } else { 49 | others = append(others, obj) 50 | } 51 | } 52 | 53 | // final object order 54 | var order []Object 55 | 56 | // sort interface types topologically by dependencies, 57 | // and in source order if there are no dependencies 58 | sort.Sort(inSourceOrder(ifaces)) 59 | if debug { 60 | for _, obj := range ifaces { 61 | assert(check.objMap[obj].mark == 0) 62 | } 63 | } 64 | for _, obj := range ifaces { 65 | check.appendInPostOrder(&order, obj) 66 | } 67 | 68 | // sort everything else in source order 69 | sort.Sort(inSourceOrder(others)) 70 | 71 | return append(order, others...) 72 | } 73 | 74 | // interfaceFor returns the AST interface denoted by obj, or nil. 75 | func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType { 76 | tname, _ := obj.(*TypeName) 77 | if tname == nil { 78 | return nil // not a type 79 | } 80 | d := check.objMap[obj] 81 | if d == nil { 82 | check.dump("%s: %s should have been declared", obj.Pos(), obj.Name()) 83 | unreachable() 84 | } 85 | if d.typ == nil { 86 | return nil // invalid AST - ignore (will be handled later) 87 | } 88 | ityp, _ := d.typ.(*ast.InterfaceType) 89 | return ityp 90 | } 91 | 92 | func (check *Checker) appendInPostOrder(order *[]Object, obj Object) { 93 | d := check.objMap[obj] 94 | if d.mark != 0 { 95 | // We've already seen this object; either because it's 96 | // already added to order, or because we have a cycle. 97 | // In both cases we stop. Cycle errors are reported 98 | // when type-checking types. 99 | return 100 | } 101 | d.mark = 1 102 | 103 | for _, obj := range orderedSetObjects(d.deps) { 104 | check.appendInPostOrder(order, obj) 105 | } 106 | 107 | *order = append(*order, obj) 108 | } 109 | 110 | func orderedSetObjects(set map[Object]bool) []Object { 111 | list := make([]Object, len(set)) 112 | i := 0 113 | for obj := range set { 114 | // we don't care about the map element value 115 | list[i] = obj 116 | i++ 117 | } 118 | sort.Sort(inSourceOrder(list)) 119 | return list 120 | } 121 | 122 | // inSourceOrder implements the sort.Sort interface. 123 | type inSourceOrder []Object 124 | 125 | func (a inSourceOrder) Len() int { return len(a) } 126 | func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() } 127 | func (a inSourceOrder) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 128 | -------------------------------------------------------------------------------- /types/testdata/init2.src: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // initialization cycles 6 | 7 | package init2 8 | 9 | // cycles through functions 10 | 11 | func f1() int { _ = x1; return 0 } 12 | var x1 /* ERROR initialization cycle */ = f1 13 | 14 | func f2() int { _ = x2; return 0 } 15 | var x2 /* ERROR initialization cycle */ = f2() 16 | 17 | // cycles through method expressions 18 | 19 | type T3 int 20 | func (T3) m() int { _ = x3; return 0 } 21 | var x3 /* ERROR initialization cycle */ = T3.m 22 | 23 | type T4 int 24 | func (T4) m() int { _ = x4; return 0 } 25 | var x4 /* ERROR initialization cycle */ = T4.m(0) 26 | 27 | type T3p int 28 | func (*T3p) m() int { _ = x3p; return 0 } 29 | var x3p /* ERROR initialization cycle */ = (*T3p).m 30 | 31 | type T4p int 32 | func (*T4p) m() int { _ = x4p; return 0 } 33 | var x4p /* ERROR initialization cycle */ = (*T4p).m(nil) 34 | 35 | // cycles through method expressions of embedded methods 36 | 37 | type T5 struct { E5 } 38 | type E5 int 39 | func (E5) m() int { _ = x5; return 0 } 40 | var x5 /* ERROR initialization cycle */ = T5.m 41 | 42 | type T6 struct { E6 } 43 | type E6 int 44 | func (E6) m() int { _ = x6; return 0 } 45 | var x6 /* ERROR initialization cycle */ = T6.m(T6{0}) 46 | 47 | type T5p struct { E5p } 48 | type E5p int 49 | func (*E5p) m() int { _ = x5p; return 0 } 50 | var x5p /* ERROR initialization cycle */ = (*T5p).m 51 | 52 | type T6p struct { E6p } 53 | type E6p int 54 | func (*E6p) m() int { _ = x6p; return 0 } 55 | var x6p /* ERROR initialization cycle */ = (*T6p).m(nil) 56 | 57 | // cycles through method values 58 | 59 | type T7 int 60 | func (T7) m() int { _ = x7; return 0 } 61 | var x7 /* ERROR initialization cycle */ = T7(0).m 62 | 63 | type T8 int 64 | func (T8) m() int { _ = x8; return 0 } 65 | var x8 /* ERROR initialization cycle */ = T8(0).m() 66 | 67 | type T7p int 68 | func (*T7p) m() int { _ = x7p; return 0 } 69 | var x7p /* ERROR initialization cycle */ = new(T7p).m 70 | 71 | type T8p int 72 | func (*T8p) m() int { _ = x8p; return 0 } 73 | var x8p /* ERROR initialization cycle */ = new(T8p).m() 74 | 75 | type T7v int 76 | func (T7v) m() int { _ = x7v; return 0 } 77 | var x7var T7v 78 | var x7v /* ERROR initialization cycle */ = x7var.m 79 | 80 | type T8v int 81 | func (T8v) m() int { _ = x8v; return 0 } 82 | var x8var T8v 83 | var x8v /* ERROR initialization cycle */ = x8var.m() 84 | 85 | type T7pv int 86 | func (*T7pv) m() int { _ = x7pv; return 0 } 87 | var x7pvar *T7pv 88 | var x7pv /* ERROR initialization cycle */ = x7pvar.m 89 | 90 | type T8pv int 91 | func (*T8pv) m() int { _ = x8pv; return 0 } 92 | var x8pvar *T8pv 93 | var x8pv /* ERROR initialization cycle */ = x8pvar.m() 94 | 95 | // cycles through method values of embedded methods 96 | 97 | type T9 struct { E9 } 98 | type E9 int 99 | func (E9) m() int { _ = x9; return 0 } 100 | var x9 /* ERROR initialization cycle */ = T9{0}.m 101 | 102 | type T10 struct { E10 } 103 | type E10 int 104 | func (E10) m() int { _ = x10; return 0 } 105 | var x10 /* ERROR initialization cycle */ = T10{0}.m() 106 | 107 | type T9p struct { E9p } 108 | type E9p int 109 | func (*E9p) m() int { _ = x9p; return 0 } 110 | var x9p /* ERROR initialization cycle */ = new(T9p).m 111 | 112 | type T10p struct { E10p } 113 | type E10p int 114 | func (*E10p) m() int { _ = x10p; return 0 } 115 | var x10p /* ERROR initialization cycle */ = new(T10p).m() 116 | 117 | type T9v struct { E9v } 118 | type E9v int 119 | func (E9v) m() int { _ = x9v; return 0 } 120 | var x9var T9v 121 | var x9v /* ERROR initialization cycle */ = x9var.m 122 | 123 | type T10v struct { E10v } 124 | type E10v int 125 | func (E10v) m() int { _ = x10v; return 0 } 126 | var x10var T10v 127 | var x10v /* ERROR initialization cycle */ = x10var.m() 128 | 129 | type T9pv struct { E9pv } 130 | type E9pv int 131 | func (*E9pv) m() int { _ = x9pv; return 0 } 132 | var x9pvar *T9pv 133 | var x9pv /* ERROR initialization cycle */ = x9pvar.m 134 | 135 | type T10pv struct { E10pv } 136 | type E10pv int 137 | func (*E10pv) m() int { _ = x10pv; return 0 } 138 | var x10pvar *T10pv 139 | var x10pv /* ERROR initialization cycle */ = x10pvar.m() 140 | -------------------------------------------------------------------------------- /types/testdata/methodsets.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package methodsets 6 | 7 | type T0 struct {} 8 | 9 | func (T0) v0() {} 10 | func (*T0) p0() {} 11 | 12 | type T1 struct {} // like T0 with different method names 13 | 14 | func (T1) v1() {} 15 | func (*T1) p1() {} 16 | 17 | type T2 interface { 18 | v2() 19 | p2() 20 | } 21 | 22 | type T3 struct { 23 | T0 24 | *T1 25 | T2 26 | } 27 | 28 | // Method expressions 29 | func _() { 30 | var ( 31 | _ func(T0) = T0.v0 32 | _ = T0 /* ERROR "not in method set" */ .p0 33 | 34 | _ func (*T0) = (*T0).v0 35 | _ func (*T0) = (*T0).p0 36 | 37 | // T1 is like T0 38 | 39 | _ func(T2) = T2.v2 40 | _ func(T2) = T2.p2 41 | 42 | _ func(T3) = T3.v0 43 | _ func(T3) = T3 /* ERROR "not in method set" */ .p0 44 | _ func(T3) = T3.v1 45 | _ func(T3) = T3.p1 46 | _ func(T3) = T3.v2 47 | _ func(T3) = T3.p2 48 | 49 | _ func(*T3) = (*T3).v0 50 | _ func(*T3) = (*T3).p0 51 | _ func(*T3) = (*T3).v1 52 | _ func(*T3) = (*T3).p1 53 | _ func(*T3) = (*T3).v2 54 | _ func(*T3) = (*T3).p2 55 | ) 56 | } 57 | 58 | // Method values with addressable receivers 59 | func _() { 60 | var ( 61 | v0 T0 62 | _ func() = v0.v0 63 | _ func() = v0.p0 64 | ) 65 | 66 | var ( 67 | p0 *T0 68 | _ func() = p0.v0 69 | _ func() = p0.p0 70 | ) 71 | 72 | // T1 is like T0 73 | 74 | var ( 75 | v2 T2 76 | _ func() = v2.v2 77 | _ func() = v2.p2 78 | ) 79 | 80 | var ( 81 | v4 T3 82 | _ func() = v4.v0 83 | _ func() = v4.p0 84 | _ func() = v4.v1 85 | _ func() = v4.p1 86 | _ func() = v4.v2 87 | _ func() = v4.p2 88 | ) 89 | 90 | var ( 91 | p4 *T3 92 | _ func() = p4.v0 93 | _ func() = p4.p0 94 | _ func() = p4.v1 95 | _ func() = p4.p1 96 | _ func() = p4.v2 97 | _ func() = p4.p2 98 | ) 99 | } 100 | 101 | // Method calls with addressable receivers 102 | func _() { 103 | var v0 T0 104 | v0.v0() 105 | v0.p0() 106 | 107 | var p0 *T0 108 | p0.v0() 109 | p0.p0() 110 | 111 | // T1 is like T0 112 | 113 | var v2 T2 114 | v2.v2() 115 | v2.p2() 116 | 117 | var v4 T3 118 | v4.v0() 119 | v4.p0() 120 | v4.v1() 121 | v4.p1() 122 | v4.v2() 123 | v4.p2() 124 | 125 | var p4 *T3 126 | p4.v0() 127 | p4.p0() 128 | p4.v1() 129 | p4.p1() 130 | p4.v2() 131 | p4.p2() 132 | } 133 | 134 | // Method values with value receivers 135 | func _() { 136 | var ( 137 | _ func() = T0{}.v0 138 | _ func() = T0 /* ERROR "not in method set" */ {}.p0 139 | 140 | _ func() = (&T0{}).v0 141 | _ func() = (&T0{}).p0 142 | 143 | // T1 is like T0 144 | 145 | // no values for T2 146 | 147 | _ func() = T3{}.v0 148 | _ func() = T3 /* ERROR "not in method set" */ {}.p0 149 | _ func() = T3{}.v1 150 | _ func() = T3{}.p1 151 | _ func() = T3{}.v2 152 | _ func() = T3{}.p2 153 | 154 | _ func() = (&T3{}).v0 155 | _ func() = (&T3{}).p0 156 | _ func() = (&T3{}).v1 157 | _ func() = (&T3{}).p1 158 | _ func() = (&T3{}).v2 159 | _ func() = (&T3{}).p2 160 | ) 161 | } 162 | 163 | // Method calls with value receivers 164 | func _() { 165 | T0{}.v0() 166 | T0 /* ERROR "not in method set" */ {}.p0() 167 | 168 | (&T0{}).v0() 169 | (&T0{}).p0() 170 | 171 | // T1 is like T0 172 | 173 | // no values for T2 174 | 175 | T3{}.v0() 176 | T3 /* ERROR "not in method set" */ {}.p0() 177 | T3{}.v1() 178 | T3{}.p1() 179 | T3{}.v2() 180 | T3{}.p2() 181 | 182 | (&T3{}).v0() 183 | (&T3{}).p0() 184 | (&T3{}).v1() 185 | (&T3{}).p1() 186 | (&T3{}).v2() 187 | (&T3{}).p2() 188 | } 189 | 190 | // *T has no methods if T is an interface type 191 | func issue5918() { 192 | var ( 193 | err error 194 | _ = err.Error() 195 | _ func() string = err.Error 196 | _ func(error) string = error.Error 197 | 198 | perr = &err 199 | _ = perr /* ERROR "no field or method" */ .Error() 200 | _ func() string = perr /* ERROR "no field or method" */ .Error 201 | _ func(*error) string = ( /* ERROR "no field or method" */ *error).Error 202 | ) 203 | 204 | type T *interface{ m() int } 205 | var ( 206 | x T 207 | _ = (*x).m() 208 | _ = (*x).m 209 | 210 | _ = x /* ERROR "no field or method" */ .m() 211 | _ = x /* ERROR "no field or method" */ .m 212 | _ = T /* ERROR "no field or method" */ .m 213 | ) 214 | } 215 | -------------------------------------------------------------------------------- /types/testdata/expr0.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // unary expressions 6 | 7 | package expr0 8 | 9 | type mybool bool 10 | 11 | var ( 12 | // bool 13 | b0 = true 14 | b1 bool = b0 15 | b2 = !true 16 | b3 = !b1 17 | b4 bool = !true 18 | b5 bool = !b4 19 | b6 = +b0 /* ERROR "not defined" */ 20 | b7 = -b0 /* ERROR "not defined" */ 21 | b8 = ^b0 /* ERROR "not defined" */ 22 | b9 = *b0 /* ERROR "cannot indirect" */ 23 | b10 = &true /* ERROR "cannot take address" */ 24 | b11 = &b0 25 | b12 = <-b0 /* ERROR "cannot receive" */ 26 | b13 = & & /* ERROR "cannot take address" */ b0 27 | 28 | // byte 29 | _ = byte(0) 30 | _ = byte(- /* ERROR "cannot convert" */ 1) 31 | _ = - /* ERROR "-byte\(1\) \(constant -1 of type byte\) overflows byte" */ byte(1) // test for issue 11367 32 | _ = byte /* ERROR "overflows byte" */ (0) - byte(1) 33 | 34 | // int 35 | i0 = 1 36 | i1 int = i0 37 | i2 = +1 38 | i3 = +i0 39 | i4 int = +1 40 | i5 int = +i4 41 | i6 = -1 42 | i7 = -i0 43 | i8 int = -1 44 | i9 int = -i4 45 | i10 = !i0 /* ERROR "not defined" */ 46 | i11 = ^1 47 | i12 = ^i0 48 | i13 int = ^1 49 | i14 int = ^i4 50 | i15 = *i0 /* ERROR "cannot indirect" */ 51 | i16 = &i0 52 | i17 = *i16 53 | i18 = <-i16 /* ERROR "cannot receive" */ 54 | 55 | // uint 56 | u0 = uint(1) 57 | u1 uint = u0 58 | u2 = +1 59 | u3 = +u0 60 | u4 uint = +1 61 | u5 uint = +u4 62 | u6 = -1 63 | u7 = -u0 64 | u8 uint = - /* ERROR "overflows" */ 1 65 | u9 uint = -u4 66 | u10 = !u0 /* ERROR "not defined" */ 67 | u11 = ^1 68 | u12 = ^i0 69 | u13 uint = ^ /* ERROR "overflows" */ 1 70 | u14 uint = ^u4 71 | u15 = *u0 /* ERROR "cannot indirect" */ 72 | u16 = &u0 73 | u17 = *u16 74 | u18 = <-u16 /* ERROR "cannot receive" */ 75 | u19 = ^uint(0) 76 | 77 | // float64 78 | f0 = float64(1) 79 | f1 float64 = f0 80 | f2 = +1 81 | f3 = +f0 82 | f4 float64 = +1 83 | f5 float64 = +f4 84 | f6 = -1 85 | f7 = -f0 86 | f8 float64 = -1 87 | f9 float64 = -f4 88 | f10 = !f0 /* ERROR "not defined" */ 89 | f11 = ^1 90 | f12 = ^i0 91 | f13 float64 = ^1 92 | f14 float64 = ^f4 /* ERROR "not defined" */ 93 | f15 = *f0 /* ERROR "cannot indirect" */ 94 | f16 = &f0 95 | f17 = *u16 96 | f18 = <-u16 /* ERROR "cannot receive" */ 97 | 98 | // complex128 99 | c0 = complex128(1) 100 | c1 complex128 = c0 101 | c2 = +1 102 | c3 = +c0 103 | c4 complex128 = +1 104 | c5 complex128 = +c4 105 | c6 = -1 106 | c7 = -c0 107 | c8 complex128 = -1 108 | c9 complex128 = -c4 109 | c10 = !c0 /* ERROR "not defined" */ 110 | c11 = ^1 111 | c12 = ^i0 112 | c13 complex128 = ^1 113 | c14 complex128 = ^c4 /* ERROR "not defined" */ 114 | c15 = *c0 /* ERROR "cannot indirect" */ 115 | c16 = &c0 116 | c17 = *u16 117 | c18 = <-u16 /* ERROR "cannot receive" */ 118 | 119 | // string 120 | s0 = "foo" 121 | s1 = +"foo" /* ERROR "not defined" */ 122 | s2 = -s0 /* ERROR "not defined" */ 123 | s3 = !s0 /* ERROR "not defined" */ 124 | s4 = ^s0 /* ERROR "not defined" */ 125 | s5 = *s4 126 | s6 = &s4 127 | s7 = *s6 128 | s8 = <-s7 129 | 130 | // channel 131 | ch chan int 132 | rc <-chan float64 133 | sc chan <- string 134 | ch0 = +ch /* ERROR "not defined" */ 135 | ch1 = -ch /* ERROR "not defined" */ 136 | ch2 = !ch /* ERROR "not defined" */ 137 | ch3 = ^ch /* ERROR "not defined" */ 138 | ch4 = *ch /* ERROR "cannot indirect" */ 139 | ch5 = &ch 140 | ch6 = *ch5 141 | ch7 = <-ch 142 | ch8 = <-rc 143 | ch9 = <-sc /* ERROR "cannot receive" */ 144 | ch10, ok = <-ch 145 | // ok is of type bool 146 | ch11, myok = <-ch 147 | _ mybool = myok /* ERROR "cannot use .* in variable declaration" */ 148 | ) 149 | 150 | // address of composite literals 151 | type T struct{x, y int} 152 | 153 | func f() T { return T{} } 154 | 155 | var ( 156 | _ = &T{1, 2} 157 | _ = &[...]int{} 158 | _ = &[]int{} 159 | _ = &[]int{} 160 | _ = &map[string]T{} 161 | _ = &(T{1, 2}) 162 | _ = &((((T{1, 2})))) 163 | _ = &f /* ERROR "cannot take address" */ () 164 | ) 165 | 166 | // recursive pointer types 167 | type P *P 168 | 169 | var ( 170 | p1 P = new(P) 171 | p2 P = *p1 172 | p3 P = &p2 173 | ) 174 | 175 | func g() (a, b int) { return } 176 | 177 | func _() { 178 | _ = -g /* ERROR 2-valued g */ () 179 | _ = <-g /* ERROR 2-valued g */ () 180 | } 181 | -------------------------------------------------------------------------------- /types/testdata/labels.src: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file is a modified concatenation of the files 6 | // $GOROOT/test/label.go and $GOROOT/test/label1.go. 7 | 8 | package labels 9 | 10 | var x int 11 | 12 | func f0() { 13 | L1 /* ERROR "label L1 declared but not used" */ : 14 | for { 15 | } 16 | L2 /* ERROR "label L2 declared but not used" */ : 17 | select { 18 | } 19 | L3 /* ERROR "label L3 declared but not used" */ : 20 | switch { 21 | } 22 | L4 /* ERROR "label L4 declared but not used" */ : 23 | if true { 24 | } 25 | L5 /* ERROR "label L5 declared but not used" */ : 26 | f0() 27 | L6: 28 | f0() 29 | L6 /* ERROR "label L6 already declared" */ : 30 | f0() 31 | if x == 20 { 32 | goto L6 33 | } 34 | 35 | L7: 36 | for { 37 | break L7 38 | break L8 /* ERROR "invalid break label L8" */ 39 | } 40 | 41 | // A label must be directly associated with a switch, select, or 42 | // for statement; it cannot be the label of a labeled statement. 43 | 44 | L7a /* ERROR "declared but not used" */ : L7b: 45 | for { 46 | break L7a /* ERROR "invalid break label L7a" */ 47 | continue L7a /* ERROR "invalid continue label L7a" */ 48 | continue L7b 49 | } 50 | 51 | L8: 52 | for { 53 | if x == 21 { 54 | continue L8 55 | continue L7 /* ERROR "invalid continue label L7" */ 56 | } 57 | } 58 | 59 | L9: 60 | switch { 61 | case true: 62 | break L9 63 | defalt /* ERROR "label defalt declared but not used" */ : 64 | } 65 | 66 | L10: 67 | select { 68 | default: 69 | break L10 70 | break L9 /* ERROR "invalid break label L9" */ 71 | } 72 | 73 | goto L10a 74 | L10a: L10b: 75 | select { 76 | default: 77 | break L10a /* ERROR "invalid break label L10a" */ 78 | break L10b 79 | continue L10b /* ERROR "invalid continue label L10b" */ 80 | } 81 | } 82 | 83 | func f1() { 84 | L1: 85 | for { 86 | if x == 0 { 87 | break L1 88 | } 89 | if x == 1 { 90 | continue L1 91 | } 92 | goto L1 93 | } 94 | 95 | L2: 96 | select { 97 | default: 98 | if x == 0 { 99 | break L2 100 | } 101 | if x == 1 { 102 | continue L2 /* ERROR "invalid continue label L2" */ 103 | } 104 | goto L2 105 | } 106 | 107 | L3: 108 | switch { 109 | case x > 10: 110 | if x == 11 { 111 | break L3 112 | } 113 | if x == 12 { 114 | continue L3 /* ERROR "invalid continue label L3" */ 115 | } 116 | goto L3 117 | } 118 | 119 | L4: 120 | if true { 121 | if x == 13 { 122 | break L4 /* ERROR "invalid break label L4" */ 123 | } 124 | if x == 14 { 125 | continue L4 /* ERROR "invalid continue label L4" */ 126 | } 127 | if x == 15 { 128 | goto L4 129 | } 130 | } 131 | 132 | L5: 133 | f1() 134 | if x == 16 { 135 | break L5 /* ERROR "invalid break label L5" */ 136 | } 137 | if x == 17 { 138 | continue L5 /* ERROR "invalid continue label L5" */ 139 | } 140 | if x == 18 { 141 | goto L5 142 | } 143 | 144 | for { 145 | if x == 19 { 146 | break L1 /* ERROR "invalid break label L1" */ 147 | } 148 | if x == 20 { 149 | continue L1 /* ERROR "invalid continue label L1" */ 150 | } 151 | if x == 21 { 152 | goto L1 153 | } 154 | } 155 | } 156 | 157 | // Additional tests not in the original files. 158 | 159 | func f2() { 160 | L1 /* ERROR "label L1 declared but not used" */ : 161 | if x == 0 { 162 | for { 163 | continue L1 /* ERROR "invalid continue label L1" */ 164 | } 165 | } 166 | } 167 | 168 | func f3() { 169 | L1: 170 | L2: 171 | L3: 172 | for { 173 | break L1 /* ERROR "invalid break label L1" */ 174 | break L2 /* ERROR "invalid break label L2" */ 175 | break L3 176 | continue L1 /* ERROR "invalid continue label L1" */ 177 | continue L2 /* ERROR "invalid continue label L2" */ 178 | continue L3 179 | goto L1 180 | goto L2 181 | goto L3 182 | } 183 | } 184 | 185 | // Blank labels are never declared. 186 | 187 | func f4() { 188 | _: 189 | _: // multiple blank labels are ok 190 | goto _ /* ERROR "label _ not declared" */ 191 | } 192 | 193 | func f5() { 194 | _: 195 | for { 196 | break _ /* ERROR "invalid break label _" */ 197 | continue _ /* ERROR "invalid continue label _" */ 198 | } 199 | } 200 | 201 | func f6() { 202 | _: 203 | switch { 204 | default: 205 | break _ /* ERROR "invalid break label _" */ 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /types/testdata/stmt1.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // terminating statements 6 | 7 | package stmt1 8 | 9 | func _() {} 10 | 11 | func _() int {} /* ERROR "missing return" */ 12 | 13 | func _() int { panic(0) } 14 | func _() int { (panic(0)) } 15 | 16 | // block statements 17 | func _(x, y int) (z int) { 18 | { 19 | return 20 | } 21 | } 22 | 23 | func _(x, y int) (z int) { 24 | { 25 | return; ; ; // trailing empty statements are ok 26 | } 27 | ; ; ; 28 | } 29 | 30 | func _(x, y int) (z int) { 31 | { 32 | } 33 | } /* ERROR "missing return" */ 34 | 35 | func _(x, y int) (z int) { 36 | { 37 | ; ; ; 38 | } 39 | ; ; ; 40 | } /* ERROR "missing return" */ 41 | 42 | // if statements 43 | func _(x, y int) (z int) { 44 | if x < y { return } 45 | return 1 46 | } 47 | 48 | func _(x, y int) (z int) { 49 | if x < y { return; ; ; ; } 50 | return 1 51 | } 52 | 53 | func _(x, y int) (z int) { 54 | if x < y { return } 55 | return 1; ; 56 | } 57 | 58 | func _(x, y int) (z int) { 59 | if x < y { return } 60 | } /* ERROR "missing return" */ 61 | 62 | func _(x, y int) (z int) { 63 | if x < y { 64 | } else { return 1 65 | } 66 | } /* ERROR "missing return" */ 67 | 68 | func _(x, y int) (z int) { 69 | if x < y { return 70 | } else { return 71 | } 72 | } 73 | 74 | // for statements 75 | func _(x, y int) (z int) { 76 | for x < y { 77 | return 78 | } 79 | } /* ERROR "missing return" */ 80 | 81 | func _(x, y int) (z int) { 82 | for { 83 | return 84 | } 85 | } 86 | 87 | func _(x, y int) (z int) { 88 | for { 89 | return; ; ; ; 90 | } 91 | } 92 | 93 | func _(x, y int) (z int) { 94 | for { 95 | return 96 | break 97 | } 98 | ; ; ; 99 | } /* ERROR "missing return" */ 100 | 101 | func _(x, y int) (z int) { 102 | for { 103 | for { break } 104 | return 105 | } 106 | } 107 | 108 | func _(x, y int) (z int) { 109 | for { 110 | for { break } 111 | return ; ; 112 | } 113 | ; 114 | } 115 | 116 | func _(x, y int) (z int) { 117 | L: for { 118 | for { break L } 119 | return 120 | } 121 | } /* ERROR "missing return" */ 122 | 123 | // switch statements 124 | func _(x, y int) (z int) { 125 | switch x { 126 | case 0: return 127 | default: return 128 | } 129 | } 130 | 131 | func _(x, y int) (z int) { 132 | switch x { 133 | case 0: return; 134 | default: return; ; ; 135 | } 136 | } 137 | 138 | func _(x, y int) (z int) { 139 | switch x { 140 | case 0: return 141 | } 142 | } /* ERROR "missing return" */ 143 | 144 | func _(x, y int) (z int) { 145 | switch x { 146 | case 0: return 147 | case 1: break 148 | } 149 | } /* ERROR "missing return" */ 150 | 151 | func _(x, y int) (z int) { 152 | switch x { 153 | case 0: return 154 | default: 155 | switch y { 156 | case 0: break 157 | } 158 | panic(0) 159 | } 160 | } 161 | 162 | func _(x, y int) (z int) { 163 | switch x { 164 | case 0: return 165 | default: 166 | switch y { 167 | case 0: break 168 | } 169 | panic(0); ; ; 170 | } 171 | ; 172 | } 173 | 174 | func _(x, y int) (z int) { 175 | L: switch x { 176 | case 0: return 177 | default: 178 | switch y { 179 | case 0: break L 180 | } 181 | panic(0) 182 | } 183 | } /* ERROR "missing return" */ 184 | 185 | // select statements 186 | func _(ch chan int) (z int) { 187 | select {} 188 | } // nice! 189 | 190 | func _(ch chan int) (z int) { 191 | select {} 192 | ; ; 193 | } 194 | 195 | func _(ch chan int) (z int) { 196 | select { 197 | default: break 198 | } 199 | } /* ERROR "missing return" */ 200 | 201 | func _(ch chan int) (z int) { 202 | select { 203 | case <-ch: return 204 | default: break 205 | } 206 | } /* ERROR "missing return" */ 207 | 208 | func _(ch chan int) (z int) { 209 | select { 210 | case <-ch: return 211 | default: 212 | for i := 0; i < 10; i++ { 213 | break 214 | } 215 | return 216 | } 217 | } 218 | 219 | func _(ch chan int) (z int) { 220 | select { 221 | case <-ch: return; ; ; 222 | default: 223 | for i := 0; i < 10; i++ { 224 | break 225 | } 226 | return; ; ; 227 | } 228 | ; ; ; 229 | } 230 | 231 | func _(ch chan int) (z int) { 232 | L: select { 233 | case <-ch: return 234 | default: 235 | for i := 0; i < 10; i++ { 236 | break L 237 | } 238 | return 239 | } 240 | ; ; ; 241 | } /* ERROR "missing return" */ 242 | -------------------------------------------------------------------------------- /types/testdata/decls1.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // variable declarations 6 | 7 | package decls1 8 | 9 | import ( 10 | "math" 11 | ) 12 | 13 | // Global variables without initialization 14 | var ( 15 | a, b bool 16 | c byte 17 | d uint8 18 | r rune 19 | i int 20 | j, k, l int 21 | x, y float32 22 | xx, yy float64 23 | u, v complex64 24 | uu, vv complex128 25 | s, t string 26 | array []byte 27 | iface interface{} 28 | 29 | blank _ /* ERROR "cannot use _" */ 30 | ) 31 | 32 | // Global variables with initialization 33 | var ( 34 | s1 = i + j 35 | s2 = i /* ERROR "mismatched types" */ + x 36 | s3 = c + d 37 | s4 = s + t 38 | s5 = s /* ERROR "invalid operation" */ / t 39 | s6 = array[t1] 40 | s7 = array[x /* ERROR "integer" */] 41 | s8 = &a 42 | s10 = &42 /* ERROR "cannot take address" */ 43 | s11 = &v 44 | s12 = -(u + *t11) / *&v 45 | s13 = a /* ERROR "shifted operand" */ << d 46 | s14 = i << j /* ERROR "must be unsigned" */ 47 | s18 = math.Pi * 10.0 48 | s19 = s1 /* ERROR "cannot call" */ () 49 | s20 = f0 /* ERROR "no value" */ () 50 | s21 = f6(1, s1, i) 51 | s22 = f6(1, s1, uu /* ERROR "cannot use .* in argument" */ ) 52 | 53 | t1 int = i + j 54 | t2 int = i /* ERROR "mismatched types" */ + x 55 | t3 int = c /* ERROR "cannot use .* variable declaration" */ + d 56 | t4 string = s + t 57 | t5 string = s /* ERROR "invalid operation" */ / t 58 | t6 byte = array[t1] 59 | t7 byte = array[x /* ERROR "must be integer" */] 60 | t8 *int = & /* ERROR "cannot use .* variable declaration" */ a 61 | t10 *int = &42 /* ERROR "cannot take address" */ 62 | t11 *complex64 = &v 63 | t12 complex64 = -(u + *t11) / *&v 64 | t13 int = a /* ERROR "shifted operand" */ << d 65 | t14 int = i << j /* ERROR "must be unsigned" */ 66 | t15 math /* ERROR "not in selector" */ 67 | t16 math /* ERROR "not declared" */ .xxx 68 | t17 math /* ERROR "not a type" */ .Pi 69 | t18 float64 = math.Pi * 10.0 70 | t19 int = t1 /* ERROR "cannot call" */ () 71 | t20 int = f0 /* ERROR "no value" */ () 72 | t21 int = a /* ERROR "cannot use .* variable declaration" */ 73 | ) 74 | 75 | // Various more complex expressions 76 | var ( 77 | u1 = x /* ERROR "not an interface" */ .(int) 78 | u2 = iface.([]int) 79 | u3 = iface.(a /* ERROR "not a type" */ ) 80 | u4, ok = iface.(int) 81 | u5, ok2, ok3 = iface /* ERROR "assignment count mismatch" */ .(int) 82 | ) 83 | 84 | // Constant expression initializations 85 | var ( 86 | v1 = 1 /* ERROR "cannot convert" */ + "foo" 87 | v2 = c + 255 88 | v3 = c + 256 /* ERROR "overflows" */ 89 | v4 = r + 2147483647 90 | v5 = r + 2147483648 /* ERROR "overflows" */ 91 | v6 = 42 92 | v7 = v6 + 9223372036854775807 93 | v8 = v6 + 9223372036854775808 /* ERROR "overflows" */ 94 | v9 = i + 1 << 10 95 | v10 byte = 1024 /* ERROR "overflows" */ 96 | v11 = xx/yy*yy - xx 97 | v12 = true && false 98 | v13 = nil /* ERROR "use of untyped nil" */ 99 | ) 100 | 101 | // Multiple assignment expressions 102 | var ( 103 | m1a, m1b = 1, 2 104 | m2a, m2b, m2c /* ERROR "missing init expr for m2c" */ = 1, 2 105 | m3a, m3b = 1, 2, 3 /* ERROR "extra init expr 3" */ 106 | ) 107 | 108 | func _() { 109 | var ( 110 | m1a, m1b = 1, 2 111 | m2a, m2b, m2c /* ERROR "missing init expr for m2c" */ = 1, 2 112 | m3a, m3b = 1, 2, 3 /* ERROR "extra init expr 3" */ 113 | ) 114 | 115 | _, _ = m1a, m1b 116 | _, _, _ = m2a, m2b, m2c 117 | _, _ = m3a, m3b 118 | } 119 | 120 | // Declaration of parameters and results 121 | func f0() {} 122 | func f1(a /* ERROR "not a type" */) {} 123 | func f2(a, b, c d /* ERROR "not a type" */) {} 124 | 125 | func f3() int { return 0 } 126 | func f4() a /* ERROR "not a type" */ { return 0 } 127 | func f5() (a, b, c d /* ERROR "not a type" */) { return } 128 | 129 | func f6(a, b, c int) complex128 { return 0 } 130 | 131 | // Declaration of receivers 132 | type T struct{} 133 | 134 | func (T) m0() {} 135 | func (*T) m1() {} 136 | func (x T) m2() {} 137 | func (x *T) m3() {} 138 | 139 | // Initialization functions 140 | func init() {} 141 | func /* ERROR "no arguments and no return values" */ init(int) {} 142 | func /* ERROR "no arguments and no return values" */ init() int { return 0 } 143 | func /* ERROR "no arguments and no return values" */ init(int) int { return 0 } 144 | func (T) init(int) int { return 0 } 145 | -------------------------------------------------------------------------------- /importer/gcimporter/gcimporter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package gcimporter implements Import for gc-generated object files. 6 | package gcimporter 7 | 8 | import ( 9 | "bufio" 10 | "fmt" 11 | "go/build" 12 | "go/token" 13 | "io/ioutil" 14 | "os" 15 | "path/filepath" 16 | "strings" 17 | 18 | "github.com/lukechampine/ply/types" 19 | ) 20 | 21 | // debugging/development support 22 | const debug = false 23 | 24 | var pkgExts = [...]string{".a", ".o"} 25 | 26 | // FindPkg returns the filename and unique package id for an import 27 | // path based on package information provided by build.Import (using 28 | // the build.Default build.Context). A relative srcDir is interpreted 29 | // relative to the current working directory. 30 | // If no file was found, an empty filename is returned. 31 | // 32 | func FindPkg(path, srcDir string) (filename, id string) { 33 | if path == "" { 34 | return 35 | } 36 | 37 | var noext string 38 | switch { 39 | default: 40 | // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" 41 | // Don't require the source files to be present. 42 | if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 43 | srcDir = abs 44 | } 45 | bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) 46 | if bp.PkgObj == "" { 47 | return 48 | } 49 | noext = strings.TrimSuffix(bp.PkgObj, ".a") 50 | id = bp.ImportPath 51 | 52 | case build.IsLocalImport(path): 53 | // "./x" -> "/this/directory/x.ext", "/this/directory/x" 54 | noext = filepath.Join(srcDir, path) 55 | id = noext 56 | 57 | case filepath.IsAbs(path): 58 | // for completeness only - go/build.Import 59 | // does not support absolute imports 60 | // "/x" -> "/x.ext", "/x" 61 | noext = path 62 | id = path 63 | } 64 | 65 | if false { // for debugging 66 | if path != id { 67 | fmt.Printf("%s -> %s\n", path, id) 68 | } 69 | } 70 | 71 | // try extensions 72 | for _, ext := range pkgExts { 73 | filename = noext + ext 74 | if f, err := os.Stat(filename); err == nil && !f.IsDir() { 75 | return 76 | } 77 | } 78 | 79 | filename = "" // not found 80 | return 81 | } 82 | 83 | // Import imports a gc-generated package given its import path and srcDir, adds 84 | // the corresponding package object to the packages map, and returns the object. 85 | // The packages map must contain all packages already imported. 86 | // 87 | func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) { 88 | filename, id := FindPkg(path, srcDir) 89 | if filename == "" { 90 | if path == "unsafe" { 91 | return types.Unsafe, nil 92 | } 93 | err = fmt.Errorf("can't find import: %s", id) 94 | return 95 | } 96 | 97 | // no need to re-import if the package was imported completely before 98 | if pkg = packages[id]; pkg != nil && pkg.Complete() { 99 | return 100 | } 101 | 102 | // open file 103 | f, err := os.Open(filename) 104 | if err != nil { 105 | return 106 | } 107 | defer func() { 108 | f.Close() 109 | if err != nil { 110 | // add file name to error 111 | err = fmt.Errorf("%s: %v", filename, err) 112 | } 113 | }() 114 | 115 | var hdr string 116 | buf := bufio.NewReader(f) 117 | if hdr, err = FindExportData(buf); err != nil { 118 | return 119 | } 120 | 121 | switch hdr { 122 | case "$$\n": 123 | err = fmt.Errorf("import %q: old export format no longer supported (recompile library)", path) 124 | case "$$B\n": 125 | var data []byte 126 | data, err = ioutil.ReadAll(buf) 127 | if err == nil { 128 | // TODO(gri): allow clients of go/importer to provide a FileSet. 129 | // Or, define a new standard github.com/lukechampine/ply/types/gcexportdata package. 130 | fset := token.NewFileSet() 131 | _, pkg, err = BImportData(fset, packages, data, id) 132 | return 133 | } 134 | default: 135 | err = fmt.Errorf("unknown export data header: %q", hdr) 136 | } 137 | 138 | return 139 | } 140 | 141 | func deref(typ types.Type) types.Type { 142 | if p, _ := typ.(*types.Pointer); p != nil { 143 | return p.Elem() 144 | } 145 | return typ 146 | } 147 | 148 | type byPath []*types.Package 149 | 150 | func (a byPath) Len() int { return len(a) } 151 | func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 152 | func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() } 153 | -------------------------------------------------------------------------------- /types/conversions.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements typechecking of conversions. 6 | 7 | package types 8 | 9 | import "go/constant" 10 | 11 | // Conversion type-checks the conversion T(x). 12 | // The result is in x. 13 | func (check *Checker) conversion(x *operand, T Type) { 14 | constArg := x.mode == constant_ 15 | 16 | var ok bool 17 | switch { 18 | case constArg && isConstType(T): 19 | // constant conversion 20 | switch t := T.Underlying().(*Basic); { 21 | case representableConst(x.val, check.conf, t, &x.val): 22 | ok = true 23 | case isInteger(x.typ) && isString(t): 24 | codepoint := int64(-1) 25 | if i, ok := constant.Int64Val(x.val); ok { 26 | codepoint = i 27 | } 28 | // If codepoint < 0 the absolute value is too large (or unknown) for 29 | // conversion. This is the same as converting any other out-of-range 30 | // value - let string(codepoint) do the work. 31 | x.val = constant.MakeString(string(codepoint)) 32 | ok = true 33 | } 34 | case x.convertibleTo(check.conf, T): 35 | // non-constant conversion 36 | x.mode = value 37 | ok = true 38 | } 39 | 40 | if !ok { 41 | check.errorf(x.pos(), "cannot convert %s to %s", x, T) 42 | x.mode = invalid 43 | return 44 | } 45 | 46 | // The conversion argument types are final. For untyped values the 47 | // conversion provides the type, per the spec: "A constant may be 48 | // given a type explicitly by a constant declaration or conversion,...". 49 | final := x.typ 50 | if isUntyped(x.typ) { 51 | final = T 52 | // - For conversions to interfaces, use the argument's default type. 53 | // - For conversions of untyped constants to non-constant types, also 54 | // use the default type (e.g., []byte("foo") should report string 55 | // not []byte as type for the constant "foo"). 56 | // - Keep untyped nil for untyped nil arguments. 57 | if IsInterface(T) || constArg && !isConstType(T) { 58 | final = defaultType(x.typ) 59 | } 60 | check.updateExprType(x.expr, final, true) 61 | } 62 | 63 | x.typ = T 64 | } 65 | 66 | func (x *operand) convertibleTo(conf *Config, T Type) bool { 67 | // "x is assignable to T" 68 | if x.assignableTo(conf, T, nil) { 69 | return true 70 | } 71 | 72 | // "x's type and T have identical underlying types" 73 | V := x.typ 74 | Vu := V.Underlying() 75 | Tu := T.Underlying() 76 | if Identical(Vu, Tu) { 77 | return true 78 | } 79 | 80 | // "x's type and T are unnamed pointer types and their pointer base types have identical underlying types" 81 | if V, ok := V.(*Pointer); ok { 82 | if T, ok := T.(*Pointer); ok { 83 | if Identical(V.base.Underlying(), T.base.Underlying()) { 84 | return true 85 | } 86 | } 87 | } 88 | 89 | // "x's type and T are both integer or floating point types" 90 | if (isInteger(V) || isFloat(V)) && (isInteger(T) || isFloat(T)) { 91 | return true 92 | } 93 | 94 | // "x's type and T are both complex types" 95 | if isComplex(V) && isComplex(T) { 96 | return true 97 | } 98 | 99 | // "x is an integer or a slice of bytes or runes and T is a string type" 100 | if (isInteger(V) || isBytesOrRunes(Vu)) && isString(T) { 101 | return true 102 | } 103 | 104 | // "x is a string and T is a slice of bytes or runes" 105 | if isString(V) && isBytesOrRunes(Tu) { 106 | return true 107 | } 108 | 109 | // package unsafe: 110 | // "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" 111 | if (isPointer(Vu) || isUintptr(Vu)) && isUnsafePointer(T) { 112 | return true 113 | } 114 | // "and vice versa" 115 | if isUnsafePointer(V) && (isPointer(Tu) || isUintptr(Tu)) { 116 | return true 117 | } 118 | 119 | return false 120 | } 121 | 122 | func isUintptr(typ Type) bool { 123 | t, ok := typ.Underlying().(*Basic) 124 | return ok && t.kind == Uintptr 125 | } 126 | 127 | func isUnsafePointer(typ Type) bool { 128 | // TODO(gri): Is this (typ.Underlying() instead of just typ) correct? 129 | // The spec does not say so, but gc claims it is. See also 130 | // issue 6326. 131 | t, ok := typ.Underlying().(*Basic) 132 | return ok && t.kind == UnsafePointer 133 | } 134 | 135 | func isPointer(typ Type) bool { 136 | _, ok := typ.Underlying().(*Pointer) 137 | return ok 138 | } 139 | 140 | func isBytesOrRunes(typ Type) bool { 141 | if s, ok := typ.(*Slice); ok { 142 | t, ok := s.elem.Underlying().(*Basic) 143 | return ok && (t.kind == Byte || t.kind == Rune) 144 | } 145 | return false 146 | } 147 | -------------------------------------------------------------------------------- /importer/gccgoimporter/gccgoinstallation_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gccgoimporter 6 | 7 | import ( 8 | "github.com/lukechampine/ply/types" 9 | "runtime" 10 | "testing" 11 | ) 12 | 13 | var importablePackages = [...]string{ 14 | "archive/tar", 15 | "archive/zip", 16 | "bufio", 17 | "bytes", 18 | "compress/bzip2", 19 | "compress/flate", 20 | "compress/gzip", 21 | "compress/lzw", 22 | "compress/zlib", 23 | "container/heap", 24 | "container/list", 25 | "container/ring", 26 | "crypto/aes", 27 | "crypto/cipher", 28 | "crypto/des", 29 | "crypto/dsa", 30 | "crypto/ecdsa", 31 | "crypto/elliptic", 32 | "crypto", 33 | "crypto/hmac", 34 | "crypto/md5", 35 | "crypto/rand", 36 | "crypto/rc4", 37 | "crypto/rsa", 38 | "crypto/sha1", 39 | "crypto/sha256", 40 | "crypto/sha512", 41 | "crypto/subtle", 42 | "crypto/tls", 43 | "crypto/x509", 44 | "crypto/x509/pkix", 45 | "database/sql/driver", 46 | "database/sql", 47 | "debug/dwarf", 48 | "debug/elf", 49 | "debug/gosym", 50 | "debug/macho", 51 | "debug/pe", 52 | "encoding/ascii85", 53 | "encoding/asn1", 54 | "encoding/base32", 55 | "encoding/base64", 56 | "encoding/binary", 57 | "encoding/csv", 58 | "encoding/gob", 59 | "encoding", 60 | "encoding/hex", 61 | "encoding/json", 62 | "encoding/pem", 63 | "encoding/xml", 64 | "errors", 65 | "exp/proxy", 66 | "exp/terminal", 67 | "expvar", 68 | "flag", 69 | "fmt", 70 | "go/ast", 71 | "go/build", 72 | "go/doc", 73 | "go/format", 74 | "go/parser", 75 | "go/printer", 76 | "go/scanner", 77 | "go/token", 78 | "hash/adler32", 79 | "hash/crc32", 80 | "hash/crc64", 81 | "hash/fnv", 82 | "hash", 83 | "html", 84 | "html/template", 85 | "image/color", 86 | "image/color/palette", 87 | "image/draw", 88 | "image/gif", 89 | "image", 90 | "image/jpeg", 91 | "image/png", 92 | "index/suffixarray", 93 | "io", 94 | "io/ioutil", 95 | "log", 96 | "log/syslog", 97 | "math/big", 98 | "math/cmplx", 99 | "math", 100 | "math/rand", 101 | "mime", 102 | "mime/multipart", 103 | "net", 104 | "net/http/cgi", 105 | "net/http/cookiejar", 106 | "net/http/fcgi", 107 | "net/http", 108 | "net/http/httptest", 109 | "net/http/httputil", 110 | "net/http/pprof", 111 | "net/mail", 112 | "net/rpc", 113 | "net/rpc/jsonrpc", 114 | "net/smtp", 115 | "net/textproto", 116 | "net/url", 117 | "old/regexp", 118 | "old/template", 119 | "os/exec", 120 | "os", 121 | "os/signal", 122 | "os/user", 123 | "path/filepath", 124 | "path", 125 | "reflect", 126 | "regexp", 127 | "regexp/syntax", 128 | "runtime/debug", 129 | "runtime", 130 | "runtime/pprof", 131 | "sort", 132 | "strconv", 133 | "strings", 134 | "sync/atomic", 135 | "sync", 136 | "syscall", 137 | "testing", 138 | "testing/iotest", 139 | "testing/quick", 140 | "text/scanner", 141 | "text/tabwriter", 142 | "text/template", 143 | "text/template/parse", 144 | "time", 145 | "unicode", 146 | "unicode/utf16", 147 | "unicode/utf8", 148 | } 149 | 150 | func TestInstallationImporter(t *testing.T) { 151 | // This test relies on gccgo being around, which it most likely will be if we 152 | // were compiled with gccgo. 153 | if runtime.Compiler != "gccgo" { 154 | t.Skip("This test needs gccgo") 155 | return 156 | } 157 | 158 | var inst GccgoInstallation 159 | err := inst.InitFromDriver("gccgo") 160 | if err != nil { 161 | t.Fatal(err) 162 | } 163 | imp := inst.GetImporter(nil, nil) 164 | 165 | // Ensure we don't regress the number of packages we can parse. First import 166 | // all packages into the same map and then each individually. 167 | pkgMap := make(map[string]*types.Package) 168 | for _, pkg := range importablePackages { 169 | _, err = imp(pkgMap, pkg) 170 | if err != nil { 171 | t.Error(err) 172 | } 173 | } 174 | 175 | for _, pkg := range importablePackages { 176 | _, err = imp(make(map[string]*types.Package), pkg) 177 | if err != nil { 178 | t.Error(err) 179 | } 180 | } 181 | 182 | // Test for certain specific entities in the imported data. 183 | for _, test := range [...]importerTest{ 184 | {pkgpath: "io", name: "Reader", want: "type Reader interface{Read(p []uint8) (n int, err error)}"}, 185 | {pkgpath: "io", name: "ReadWriter", want: "type ReadWriter interface{Reader; Writer}"}, 186 | {pkgpath: "math", name: "Pi", want: "const Pi untyped float"}, 187 | {pkgpath: "math", name: "Sin", want: "func Sin(x float64) float64"}, 188 | {pkgpath: "sort", name: "Ints", want: "func Ints(a []int)"}, 189 | {pkgpath: "unsafe", name: "Pointer", want: "type Pointer unsafe.Pointer"}, 190 | } { 191 | runImporterTest(t, imp, nil, &test) 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /types/selection.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements Selections. 6 | 7 | package types 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | ) 13 | 14 | // SelectionKind describes the kind of a selector expression x.f 15 | // (excluding qualified identifiers). 16 | type SelectionKind int 17 | 18 | const ( 19 | FieldVal SelectionKind = iota // x.f is a struct field selector 20 | MethodVal // x.f is a method selector 21 | MethodExpr // x.f is a method expression 22 | ) 23 | 24 | // A Selection describes a selector expression x.f. 25 | // For the declarations: 26 | // 27 | // type T struct{ x int; E } 28 | // type E struct{} 29 | // func (e E) m() {} 30 | // var p *T 31 | // 32 | // the following relations exist: 33 | // 34 | // Selector Kind Recv Obj Type Index Indirect 35 | // 36 | // p.x FieldVal T x int {0} true 37 | // p.m MethodVal *T m func (e *T) m() {1, 0} true 38 | // T.m MethodExpr T m func m(_ T) {1, 0} false 39 | // 40 | type Selection struct { 41 | kind SelectionKind 42 | recv Type // type of x 43 | obj Object // object denoted by x.f 44 | index []int // path from x to x.f 45 | indirect bool // set if there was any pointer indirection on the path 46 | } 47 | 48 | // Kind returns the selection kind. 49 | func (s *Selection) Kind() SelectionKind { return s.kind } 50 | 51 | // Recv returns the type of x in x.f. 52 | func (s *Selection) Recv() Type { return s.recv } 53 | 54 | // Obj returns the object denoted by x.f; a *Var for 55 | // a field selection, and a *Func in all other cases. 56 | func (s *Selection) Obj() Object { return s.obj } 57 | 58 | // Type returns the type of x.f, which may be different from the type of f. 59 | // See Selection for more information. 60 | func (s *Selection) Type() Type { 61 | switch s.kind { 62 | case MethodVal: 63 | // The type of x.f is a method with its receiver type set 64 | // to the type of x. 65 | sig := *s.obj.(*Func).typ.(*Signature) 66 | recv := *sig.recv 67 | recv.typ = s.recv 68 | sig.recv = &recv 69 | return &sig 70 | 71 | case MethodExpr: 72 | // The type of x.f is a function (without receiver) 73 | // and an additional first argument with the same type as x. 74 | // TODO(gri) Similar code is already in call.go - factor! 75 | // TODO(gri) Compute this eagerly to avoid allocations. 76 | sig := *s.obj.(*Func).typ.(*Signature) 77 | arg0 := *sig.recv 78 | sig.recv = nil 79 | arg0.typ = s.recv 80 | var params []*Var 81 | if sig.params != nil { 82 | params = sig.params.vars 83 | } 84 | sig.params = NewTuple(append([]*Var{&arg0}, params...)...) 85 | return &sig 86 | } 87 | 88 | // In all other cases, the type of x.f is the type of x. 89 | return s.obj.Type() 90 | } 91 | 92 | // Index describes the path from x to f in x.f. 93 | // The last index entry is the field or method index of the type declaring f; 94 | // either: 95 | // 96 | // 1) the list of declared methods of a named type; or 97 | // 2) the list of methods of an interface type; or 98 | // 3) the list of fields of a struct type. 99 | // 100 | // The earlier index entries are the indices of the embedded fields implicitly 101 | // traversed to get from (the type of) x to f, starting at embedding depth 0. 102 | func (s *Selection) Index() []int { return s.index } 103 | 104 | // Indirect reports whether any pointer indirection was required to get from 105 | // x to f in x.f. 106 | func (s *Selection) Indirect() bool { return s.indirect } 107 | 108 | func (s *Selection) String() string { return SelectionString(s, nil) } 109 | 110 | // SelectionString returns the string form of s. 111 | // The Qualifier controls the printing of 112 | // package-level objects, and may be nil. 113 | // 114 | // Examples: 115 | // "field (T) f int" 116 | // "method (T) f(X) Y" 117 | // "method expr (T) f(X) Y" 118 | // 119 | func SelectionString(s *Selection, qf Qualifier) string { 120 | var k string 121 | switch s.kind { 122 | case FieldVal: 123 | k = "field " 124 | case MethodVal: 125 | k = "method " 126 | case MethodExpr: 127 | k = "method expr " 128 | default: 129 | unreachable() 130 | } 131 | var buf bytes.Buffer 132 | buf.WriteString(k) 133 | buf.WriteByte('(') 134 | WriteType(&buf, s.Recv(), qf) 135 | fmt.Fprintf(&buf, ") %s", s.obj.Name()) 136 | if T := s.Type(); s.kind == FieldVal { 137 | buf.WriteByte(' ') 138 | WriteType(&buf, T, qf) 139 | } else { 140 | WriteSignature(&buf, T.(*Signature), qf) 141 | } 142 | return buf.String() 143 | } 144 | -------------------------------------------------------------------------------- /types/typestring_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types_test 6 | 7 | import ( 8 | "go/ast" 9 | "go/importer" 10 | "go/parser" 11 | "go/token" 12 | "internal/testenv" 13 | "testing" 14 | 15 | . "go/types" 16 | ) 17 | 18 | const filename = "" 19 | 20 | func makePkg(t *testing.T, src string) (*Package, error) { 21 | fset := token.NewFileSet() 22 | file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors) 23 | if err != nil { 24 | return nil, err 25 | } 26 | // use the package name as package path 27 | conf := Config{Importer: importer.Default()} 28 | return conf.Check(file.Name.Name, fset, []*ast.File{file}, nil) 29 | } 30 | 31 | type testEntry struct { 32 | src, str string 33 | } 34 | 35 | // dup returns a testEntry where both src and str are the same. 36 | func dup(s string) testEntry { 37 | return testEntry{s, s} 38 | } 39 | 40 | // types that don't depend on any other type declarations 41 | var independentTestTypes = []testEntry{ 42 | // basic types 43 | dup("int"), 44 | dup("float32"), 45 | dup("string"), 46 | 47 | // arrays 48 | dup("[10]int"), 49 | 50 | // slices 51 | dup("[]int"), 52 | dup("[][]int"), 53 | 54 | // structs 55 | dup("struct{}"), 56 | dup("struct{x int}"), 57 | {`struct { 58 | x, y int 59 | z float32 "foo" 60 | }`, `struct{x int; y int; z float32 "foo"}`}, 61 | {`struct { 62 | string 63 | elems []complex128 64 | }`, `struct{string; elems []complex128}`}, 65 | 66 | // pointers 67 | dup("*int"), 68 | dup("***struct{}"), 69 | dup("*struct{a int; b float32}"), 70 | 71 | // functions 72 | dup("func()"), 73 | dup("func(x int)"), 74 | {"func(x, y int)", "func(x int, y int)"}, 75 | {"func(x, y int, z string)", "func(x int, y int, z string)"}, 76 | dup("func(int)"), 77 | {"func(int, string, byte)", "func(int, string, byte)"}, 78 | 79 | dup("func() int"), 80 | {"func() (string)", "func() string"}, 81 | dup("func() (u int)"), 82 | {"func() (u, v int, w string)", "func() (u int, v int, w string)"}, 83 | 84 | dup("func(int) string"), 85 | dup("func(x int) string"), 86 | dup("func(x int) (u string)"), 87 | {"func(x, y int) (u string)", "func(x int, y int) (u string)"}, 88 | 89 | dup("func(...int) string"), 90 | dup("func(x ...int) string"), 91 | dup("func(x ...int) (u string)"), 92 | {"func(x, y ...int) (u string)", "func(x int, y ...int) (u string)"}, 93 | 94 | // interfaces 95 | dup("interface{}"), 96 | dup("interface{m()}"), 97 | dup(`interface{String() string; m(int) float32}`), 98 | 99 | // maps 100 | dup("map[string]int"), 101 | {"map[struct{x, y int}][]byte", "map[struct{x int; y int}][]byte"}, 102 | 103 | // channels 104 | dup("chan<- chan int"), 105 | dup("chan<- <-chan int"), 106 | dup("<-chan <-chan int"), 107 | dup("chan (<-chan int)"), 108 | dup("chan<- func()"), 109 | dup("<-chan []func() int"), 110 | } 111 | 112 | // types that depend on other type declarations (src in TestTypes) 113 | var dependentTestTypes = []testEntry{ 114 | // interfaces 115 | dup(`interface{io.Reader; io.Writer}`), 116 | dup(`interface{m() int; io.Writer}`), 117 | {`interface{m() interface{T}}`, `interface{m() interface{p.T}}`}, 118 | } 119 | 120 | func TestTypeString(t *testing.T) { 121 | testenv.MustHaveGoBuild(t) 122 | 123 | var tests []testEntry 124 | tests = append(tests, independentTestTypes...) 125 | tests = append(tests, dependentTestTypes...) 126 | 127 | for _, test := range tests { 128 | src := `package p; import "io"; type _ io.Writer; type T ` + test.src 129 | pkg, err := makePkg(t, src) 130 | if err != nil { 131 | t.Errorf("%s: %s", src, err) 132 | continue 133 | } 134 | typ := pkg.Scope().Lookup("T").Type().Underlying() 135 | if got := typ.String(); got != test.str { 136 | t.Errorf("%s: got %s, want %s", test.src, got, test.str) 137 | } 138 | } 139 | } 140 | 141 | func TestQualifiedTypeString(t *testing.T) { 142 | p, _ := pkgFor("p.go", "package p; type T int", nil) 143 | q, _ := pkgFor("q.go", "package q", nil) 144 | 145 | pT := p.Scope().Lookup("T").Type() 146 | for _, test := range []struct { 147 | typ Type 148 | this *Package 149 | want string 150 | }{ 151 | {nil, nil, ""}, 152 | {pT, nil, "p.T"}, 153 | {pT, p, "T"}, 154 | {pT, q, "p.T"}, 155 | {NewPointer(pT), p, "*T"}, 156 | {NewPointer(pT), q, "*p.T"}, 157 | } { 158 | qualifier := func(pkg *Package) string { 159 | if pkg != test.this { 160 | return pkg.Name() 161 | } 162 | return "" 163 | } 164 | if got := TypeString(test.typ, qualifier); got != test.want { 165 | t.Errorf("TypeString(%s, %s) = %s, want %s", 166 | test.this, test.typ, got, test.want) 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /types/hilbert_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types_test 6 | 7 | import ( 8 | "bytes" 9 | "flag" 10 | "fmt" 11 | "go/ast" 12 | "go/importer" 13 | "go/parser" 14 | "go/token" 15 | "io/ioutil" 16 | "testing" 17 | 18 | . "go/types" 19 | ) 20 | 21 | var ( 22 | H = flag.Int("H", 5, "Hilbert matrix size") 23 | out = flag.String("out", "", "write generated program to out") 24 | ) 25 | 26 | func TestHilbert(t *testing.T) { 27 | // generate source 28 | src := program(*H, *out) 29 | if *out != "" { 30 | ioutil.WriteFile(*out, src, 0666) 31 | return 32 | } 33 | 34 | // parse source 35 | fset := token.NewFileSet() 36 | f, err := parser.ParseFile(fset, "hilbert.go", src, 0) 37 | if err != nil { 38 | t.Fatal(err) 39 | } 40 | 41 | // type-check file 42 | DefPredeclaredTestFuncs() // define assert built-in 43 | conf := Config{Importer: importer.Default()} 44 | _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) 45 | if err != nil { 46 | t.Fatal(err) 47 | } 48 | } 49 | 50 | func program(n int, out string) []byte { 51 | var g gen 52 | 53 | g.p(`// WARNING: GENERATED FILE - DO NOT MODIFY MANUALLY! 54 | // (To generate, in go/types directory: go test -run=Hilbert -H=%d -out=%q) 55 | 56 | // This program tests arbitrary precision constant arithmetic 57 | // by generating the constant elements of a Hilbert matrix H, 58 | // its inverse I, and the product P = H*I. The product should 59 | // be the identity matrix. 60 | package main 61 | 62 | func main() { 63 | if !ok { 64 | printProduct() 65 | return 66 | } 67 | println("PASS") 68 | } 69 | 70 | `, n, out) 71 | g.hilbert(n) 72 | g.inverse(n) 73 | g.product(n) 74 | g.verify(n) 75 | g.printProduct(n) 76 | g.binomials(2*n - 1) 77 | g.factorials(2*n - 1) 78 | 79 | return g.Bytes() 80 | } 81 | 82 | type gen struct { 83 | bytes.Buffer 84 | } 85 | 86 | func (g *gen) p(format string, args ...interface{}) { 87 | fmt.Fprintf(&g.Buffer, format, args...) 88 | } 89 | 90 | func (g *gen) hilbert(n int) { 91 | g.p(`// Hilbert matrix, n = %d 92 | const ( 93 | `, n) 94 | for i := 0; i < n; i++ { 95 | g.p("\t") 96 | for j := 0; j < n; j++ { 97 | if j > 0 { 98 | g.p(", ") 99 | } 100 | g.p("h%d_%d", i, j) 101 | } 102 | if i == 0 { 103 | g.p(" = ") 104 | for j := 0; j < n; j++ { 105 | if j > 0 { 106 | g.p(", ") 107 | } 108 | g.p("1.0/(iota + %d)", j+1) 109 | } 110 | } 111 | g.p("\n") 112 | } 113 | g.p(")\n\n") 114 | } 115 | 116 | func (g *gen) inverse(n int) { 117 | g.p(`// Inverse Hilbert matrix 118 | const ( 119 | `) 120 | for i := 0; i < n; i++ { 121 | for j := 0; j < n; j++ { 122 | s := "+" 123 | if (i+j)&1 != 0 { 124 | s = "-" 125 | } 126 | g.p("\ti%d_%d = %s%d * b%d_%d * b%d_%d * b%d_%d * b%d_%d\n", 127 | i, j, s, i+j+1, n+i, n-j-1, n+j, n-i-1, i+j, i, i+j, i) 128 | } 129 | g.p("\n") 130 | } 131 | g.p(")\n\n") 132 | } 133 | 134 | func (g *gen) product(n int) { 135 | g.p(`// Product matrix 136 | const ( 137 | `) 138 | for i := 0; i < n; i++ { 139 | for j := 0; j < n; j++ { 140 | g.p("\tp%d_%d = ", i, j) 141 | for k := 0; k < n; k++ { 142 | if k > 0 { 143 | g.p(" + ") 144 | } 145 | g.p("h%d_%d*i%d_%d", i, k, k, j) 146 | } 147 | g.p("\n") 148 | } 149 | g.p("\n") 150 | } 151 | g.p(")\n\n") 152 | } 153 | 154 | func (g *gen) verify(n int) { 155 | g.p(`// Verify that product is the identity matrix 156 | const ok = 157 | `) 158 | for i := 0; i < n; i++ { 159 | for j := 0; j < n; j++ { 160 | if j == 0 { 161 | g.p("\t") 162 | } else { 163 | g.p(" && ") 164 | } 165 | v := 0 166 | if i == j { 167 | v = 1 168 | } 169 | g.p("p%d_%d == %d", i, j, v) 170 | } 171 | g.p(" &&\n") 172 | } 173 | g.p("\ttrue\n\n") 174 | 175 | // verify ok at type-check time 176 | if *out == "" { 177 | g.p("const _ = assert(ok)\n\n") 178 | } 179 | } 180 | 181 | func (g *gen) printProduct(n int) { 182 | g.p("func printProduct() {\n") 183 | for i := 0; i < n; i++ { 184 | g.p("\tprintln(") 185 | for j := 0; j < n; j++ { 186 | if j > 0 { 187 | g.p(", ") 188 | } 189 | g.p("p%d_%d", i, j) 190 | } 191 | g.p(")\n") 192 | } 193 | g.p("}\n\n") 194 | } 195 | 196 | func (g *gen) binomials(n int) { 197 | g.p(`// Binomials 198 | const ( 199 | `) 200 | for j := 0; j <= n; j++ { 201 | if j > 0 { 202 | g.p("\n") 203 | } 204 | for k := 0; k <= j; k++ { 205 | g.p("\tb%d_%d = f%d / (f%d*f%d)\n", j, k, j, k, j-k) 206 | } 207 | } 208 | g.p(")\n\n") 209 | } 210 | 211 | func (g *gen) factorials(n int) { 212 | g.p(`// Factorials 213 | const ( 214 | f0 = 1 215 | f1 = 1 216 | `) 217 | for i := 2; i <= n; i++ { 218 | g.p("\tf%d = f%d * %d\n", i, i-1, i) 219 | } 220 | g.p(")\n\n") 221 | } 222 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "go/build" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "path/filepath" 12 | "strings" 13 | 14 | "github.com/lukechampine/ply/codegen" 15 | ) 16 | 17 | var ( 18 | // to be supplied at build time 19 | version = "?" 20 | githash = "?" 21 | builddate = "?" 22 | ) 23 | 24 | func isFileList(args []string) bool { 25 | return len(args) > 0 && (strings.HasSuffix(args[0], ".go") || strings.HasSuffix(args[0], ".ply")) 26 | } 27 | 28 | // adhoc parses args as a set of files comprising an ad-hoc package. All files 29 | // must be in the same directory. 30 | func adhoc(args []string) (dir string, files []string, _ error) { 31 | dir = filepath.Dir(args[0]) 32 | for _, arg := range args { 33 | if !(strings.HasSuffix(arg, ".go") || strings.HasSuffix(arg, ".ply")) { 34 | return "", nil, fmt.Errorf("named files must be .go or .ply files: %s", arg) 35 | } else if filepath.Dir(arg) != dir { 36 | return "", nil, fmt.Errorf("named files must all be in one directory; have %s and %s", dir, filepath.Dir(arg)) 37 | } 38 | files = append(files, arg) 39 | } 40 | return dir, files, nil 41 | } 42 | 43 | // packages parses args as a set of package files, keyed by their directory. 44 | // If xtest is true, files ending in _test are excluded. 45 | func packages(args []string, xtest bool) (map[string][]string, error) { 46 | pkgs := make(map[string][]string) 47 | if len(args) == 0 { 48 | args = []string{"."} // current directory 49 | } 50 | for _, arg := range args { 51 | pkg, err := build.Import(arg, ".", build.FindOnly) 52 | if err != nil { 53 | return nil, err 54 | } 55 | dir, err := os.Open(pkg.Dir) 56 | if err != nil { 57 | return nil, err 58 | } 59 | defer dir.Close() 60 | filenames, err := dir.Readdirnames(0) 61 | if err != nil { 62 | return nil, err 63 | } 64 | for _, file := range filenames { 65 | if strings.HasPrefix(file, "ply-") { 66 | // don't include previous codegen; it will cause redefinition 67 | // errors 68 | continue 69 | } 70 | if xtest && (strings.HasSuffix(file, "_test.go") || strings.HasSuffix(file, "_test.ply")) { 71 | // exclude test files if xtest is set 72 | continue 73 | } 74 | if strings.HasSuffix(file, ".go") || strings.HasSuffix(file, ".ply") { 75 | pkgs[pkg.Dir] = append(pkgs[pkg.Dir], filepath.Join(pkg.Dir, file)) 76 | } 77 | } 78 | } 79 | return pkgs, nil 80 | } 81 | 82 | func main() { 83 | log.SetFlags(0) 84 | goFlags := flag.String("goflags", "", "Flags to be supplied to the Go compiler") 85 | flag.Parse() 86 | args := flag.Args() 87 | if len(args) == 0 || args[0] == "version" { 88 | fmt.Printf("ply v%s\nCommit: %s\nBuild Date: %s\n", version, githash, builddate) 89 | return 90 | } 91 | 92 | if isFileList(args[1:]) { 93 | dir, pkg, err := adhoc(args[1:]) 94 | if err != nil { 95 | log.Fatal(err) 96 | } 97 | 98 | // delete .ply files from args 99 | noply := args[:0] 100 | for _, arg := range args { 101 | if filepath.Ext(arg) != ".ply" { 102 | noply = append(noply, arg) 103 | } 104 | } 105 | args = noply 106 | 107 | plyFiles, err := codegen.Compile(pkg) 108 | if err != nil { 109 | log.Fatal(err) 110 | } 111 | for name, code := range plyFiles { 112 | // .go -> .ply 113 | filename := filepath.Join(dir, "ply-"+strings.Replace(filepath.Base(name), ".ply", ".go", -1)) 114 | err = ioutil.WriteFile(filename, code, 0666) 115 | if err != nil { 116 | log.Fatal(err) 117 | } 118 | // add compiled .ply files to args 119 | args = append(args, filename) 120 | } 121 | } else if args[0] == "run" { 122 | log.Fatal("ply run: no .ply or .go files listed") 123 | } else { 124 | xtest := args[0] != "test" 125 | pkgs, err := packages(args[1:], xtest) 126 | if err != nil { 127 | log.Fatal(err) 128 | } 129 | 130 | // for each package, compile the .ply files and write them to the 131 | // package directory. 132 | for dir, pkg := range pkgs { 133 | plyFiles, err := codegen.Compile(pkg) 134 | if err != nil { 135 | log.Fatal(err) 136 | } 137 | for name, code := range plyFiles { 138 | // .go -> .ply 139 | filename := filepath.Join(dir, "ply-"+strings.Replace(filepath.Base(name), ".ply", ".go", -1)) 140 | err = ioutil.WriteFile(filename, code, 0666) 141 | if err != nil { 142 | log.Fatal(err) 143 | } 144 | } 145 | } 146 | } 147 | 148 | // if just compiling, exit early 149 | if args[0] == "compile" { 150 | return 151 | } 152 | 153 | // invoke the Go compiler, passing on any flags 154 | args = append(append([]string{args[0]}, strings.Fields(*goFlags)...), args[1:]...) 155 | cmd := exec.Command("go", args...) 156 | cmd.Stdout = os.Stdout 157 | cmd.Stderr = os.Stderr 158 | err := cmd.Run() 159 | if _, ok := err.(*exec.ExitError); !ok && err != nil { 160 | log.Fatal(err) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /types/testdata/decls0.src: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // type declarations 6 | 7 | package decls0 8 | 9 | import "unsafe" 10 | 11 | const pi = 3.1415 12 | 13 | type ( 14 | N undeclared /* ERROR "undeclared" */ 15 | B bool 16 | I int32 17 | A [10]P 18 | T struct { 19 | x, y P 20 | } 21 | P *T 22 | R (*R) 23 | F func(A) I 24 | Y interface { 25 | f(A) I 26 | } 27 | S [](((P))) 28 | M map[I]F 29 | C chan<- I 30 | 31 | // blank types must be typechecked 32 | _ pi /* ERROR "not a type" */ 33 | _ struct{} 34 | _ struct{ pi /* ERROR "not a type" */ } 35 | ) 36 | 37 | 38 | // declarations of init 39 | const _, init /* ERROR "cannot declare init" */ , _ = 0, 1, 2 40 | type init /* ERROR "cannot declare init" */ struct{} 41 | var _, init /* ERROR "cannot declare init" */ int 42 | 43 | func init() {} 44 | func init /* ERROR "missing function body" */ () 45 | 46 | func _() { const init = 0 } 47 | func _() { type init int } 48 | func _() { var init int; _ = init } 49 | 50 | // invalid array types 51 | type ( 52 | iA0 [... /* ERROR "invalid use of '...'" */ ]byte 53 | // The error message below could be better. At the moment 54 | // we believe an integer that is too large is not an integer. 55 | // But at least we get an error. 56 | iA1 [1 /* ERROR "must be integer" */ <<100]int 57 | iA2 [- /* ERROR "invalid array length" */ 1]complex128 58 | iA3 ["foo" /* ERROR "must be integer" */ ]string 59 | iA4 [float64 /* ERROR "must be integer" */ (0)]int 60 | ) 61 | 62 | 63 | type ( 64 | p1 pi /* ERROR "no field or method foo" */ .foo 65 | p2 unsafe.Pointer 66 | ) 67 | 68 | 69 | type ( 70 | Pi pi /* ERROR "not a type" */ 71 | 72 | a /* ERROR "illegal cycle" */ a 73 | a /* ERROR "redeclared" */ int 74 | 75 | // where the cycle error appears depends on the 76 | // order in which declarations are processed 77 | // (which depends on the order in which a map 78 | // is iterated through) 79 | b /* ERROR "illegal cycle" */ c 80 | c d 81 | d e 82 | e b 83 | 84 | t *t 85 | 86 | U V 87 | V *W 88 | W U 89 | 90 | P1 *S2 91 | P2 P1 92 | 93 | S0 struct { 94 | } 95 | S1 struct { 96 | a, b, c int 97 | u, v, a /* ERROR "redeclared" */ float32 98 | } 99 | S2 struct { 100 | S0 // anonymous field 101 | S0 /* ERROR "redeclared" */ int 102 | } 103 | S3 struct { 104 | x S2 105 | } 106 | S4/* ERROR "illegal cycle" */ struct { 107 | S4 108 | } 109 | S5 /* ERROR "illegal cycle" */ struct { 110 | S6 111 | } 112 | S6 struct { 113 | field S7 114 | } 115 | S7 struct { 116 | S5 117 | } 118 | 119 | L1 []L1 120 | L2 []int 121 | 122 | A1 [10.0]int 123 | A2 /* ERROR "illegal cycle" */ [10]A2 124 | A3 /* ERROR "illegal cycle" */ [10]struct { 125 | x A4 126 | } 127 | A4 [10]A3 128 | 129 | F1 func() 130 | F2 func(x, y, z float32) 131 | F3 func(x, y, x /* ERROR "redeclared" */ float32) 132 | F4 func() (x, y, x /* ERROR "redeclared" */ float32) 133 | F5 func(x int) (x /* ERROR "redeclared" */ float32) 134 | F6 func(x ...int) 135 | 136 | I1 interface{} 137 | I2 interface { 138 | m1() 139 | } 140 | I3 interface { 141 | m1() 142 | m1 /* ERROR "redeclared" */ () 143 | } 144 | I4 interface { 145 | m1(x, y, x /* ERROR "redeclared" */ float32) 146 | m2() (x, y, x /* ERROR "redeclared" */ float32) 147 | m3(x int) (x /* ERROR "redeclared" */ float32) 148 | } 149 | I5 interface { 150 | m1(I5) 151 | } 152 | I6 interface { 153 | S0 /* ERROR "not an interface" */ 154 | } 155 | I7 interface { 156 | I1 157 | I1 158 | } 159 | I8 /* ERROR "illegal cycle" */ interface { 160 | I8 161 | } 162 | I9 interface { 163 | I10 164 | } 165 | I10 interface { 166 | I11 167 | } 168 | I11 /* ERROR "illegal cycle" */ interface { 169 | I9 170 | } 171 | 172 | C1 chan int 173 | C2 <-chan int 174 | C3 chan<- C3 175 | C4 chan C5 176 | C5 chan C6 177 | C6 chan C4 178 | 179 | M1 map[Last]string 180 | M2 map[string]M2 181 | 182 | Last int 183 | ) 184 | 185 | // cycles in function/method declarations 186 | // (test cases for issue 5217 and variants) 187 | func f1(x f1 /* ERROR "not a type" */ ) {} 188 | func f2(x *f2 /* ERROR "not a type" */ ) {} 189 | func f3() (x f3 /* ERROR "not a type" */ ) { return } 190 | func f4() (x *f4 /* ERROR "not a type" */ ) { return } 191 | 192 | func (S0) m1(x S0 /* ERROR "field or method" */ .m1) {} 193 | func (S0) m2(x *S0 /* ERROR "field or method" */ .m2) {} 194 | func (S0) m3() (x S0 /* ERROR "field or method" */ .m3) { return } 195 | func (S0) m4() (x *S0 /* ERROR "field or method" */ .m4) { return } 196 | 197 | // interfaces may not have any blank methods 198 | type BlankI interface { 199 | _ /* ERROR "invalid method name" */ () 200 | _ /* ERROR "invalid method name" */ (float32) int 201 | m() 202 | } 203 | 204 | // non-interface types may have multiple blank methods 205 | type BlankT struct{} 206 | 207 | func (BlankT) _() {} 208 | func (BlankT) _(int) {} 209 | func (BlankT) _() int { return 0 } 210 | func (BlankT) _(int) int { return 0} 211 | -------------------------------------------------------------------------------- /types/testdata/vardecl.src: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package vardecl 6 | 7 | // Prerequisites. 8 | import "math" 9 | func f() {} 10 | func g() (x, y int) { return } 11 | var m map[string]int 12 | 13 | // Var decls must have a type or an initializer. 14 | var _ int 15 | var _, _ int 16 | 17 | // The first error message is produced by the parser. 18 | // In a real-world scenario, the type-checker would not be run 19 | // in this case and the 2nd error message would not appear. 20 | var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */ 21 | var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */, _ 22 | var _ /* ERROR "missing variable type" */ /* ERROR "missing type or init expr" */, _, _ 23 | 24 | // The initializer must be an expression. 25 | var _ = int /* ERROR "not an expression" */ 26 | var _ = f /* ERROR "used as value" */ () 27 | 28 | // Identifier and expression arity must match. 29 | var _, _ = 1, 2 30 | var _ = 1, 2 /* ERROR "extra init expr 2" */ 31 | var _, _ = 1 /* ERROR "assignment count mismatch" */ 32 | var _, _, _ /* ERROR "missing init expr for _" */ = 1, 2 33 | 34 | var _ = g /* ERROR "2-valued g" */ () 35 | var _, _ = g() 36 | var _, _, _ = g /* ERROR "assignment count mismatch" */ () 37 | 38 | var _ = m["foo"] 39 | var _, _ = m["foo"] 40 | var _, _, _ = m /* ERROR "assignment count mismatch" */ ["foo"] 41 | 42 | var _, _ int = 1, 2 43 | var _ int = 1, 2 /* ERROR "extra init expr 2" */ 44 | var _, _ int = 1 /* ERROR "assignment count mismatch" */ 45 | var _, _, _ /* ERROR "missing init expr for _" */ int = 1, 2 46 | 47 | var ( 48 | _, _ = 1, 2 49 | _ = 1, 2 /* ERROR "extra init expr 2" */ 50 | _, _ = 1 /* ERROR "assignment count mismatch" */ 51 | _, _, _ /* ERROR "missing init expr for _" */ = 1, 2 52 | 53 | _ = g /* ERROR "2-valued g" */ () 54 | _, _ = g() 55 | _, _, _ = g /* ERROR "assignment count mismatch" */ () 56 | 57 | _ = m["foo"] 58 | _, _ = m["foo"] 59 | _, _, _ = m /* ERROR "assignment count mismatch" */ ["foo"] 60 | 61 | _, _ int = 1, 2 62 | _ int = 1, 2 /* ERROR "extra init expr 2" */ 63 | _, _ int = 1 /* ERROR "assignment count mismatch" */ 64 | _, _, _ /* ERROR "missing init expr for _" */ int = 1, 2 65 | ) 66 | 67 | // Variables declared in function bodies must be 'used'. 68 | type T struct{} 69 | func (r T) _(a, b, c int) (u, v, w int) { 70 | var x1 /* ERROR "declared but not used" */ int 71 | var x2 /* ERROR "declared but not used" */ int 72 | x1 = 1 73 | (x2) = 2 74 | 75 | y1 /* ERROR "declared but not used" */ := 1 76 | y2 /* ERROR "declared but not used" */ := 2 77 | y1 = 1 78 | (y1) = 2 79 | 80 | { 81 | var x1 /* ERROR "declared but not used" */ int 82 | var x2 /* ERROR "declared but not used" */ int 83 | x1 = 1 84 | (x2) = 2 85 | 86 | y1 /* ERROR "declared but not used" */ := 1 87 | y2 /* ERROR "declared but not used" */ := 2 88 | y1 = 1 89 | (y1) = 2 90 | } 91 | 92 | if x /* ERROR "declared but not used" */ := 0; a < b {} 93 | 94 | switch x /* ERROR "declared but not used" */, y := 0, 1; a { 95 | case 0: 96 | _ = y 97 | case 1: 98 | x /* ERROR "declared but not used" */ := 0 99 | } 100 | 101 | var t interface{} 102 | switch t /* ERROR "declared but not used" */ := t.(type) {} 103 | 104 | switch t /* ERROR "declared but not used" */ := t.(type) { 105 | case int: 106 | } 107 | 108 | switch t /* ERROR "declared but not used" */ := t.(type) { 109 | case int: 110 | case float32, complex64: 111 | t = nil 112 | } 113 | 114 | switch t := t.(type) { 115 | case int: 116 | case float32, complex64: 117 | _ = t 118 | } 119 | 120 | switch t := t.(type) { 121 | case int: 122 | case float32: 123 | case string: 124 | _ = func() string { 125 | return t 126 | } 127 | } 128 | 129 | switch t := t; t /* ERROR "declared but not used" */ := t.(type) {} 130 | 131 | var z1 /* ERROR "declared but not used" */ int 132 | var z2 int 133 | _ = func(a, b, c int) (u, v, w int) { 134 | z1 = a 135 | (z1) = b 136 | a = z2 137 | return 138 | } 139 | 140 | var s []int 141 | var i /* ERROR "declared but not used" */ , j int 142 | for i, j = range s { 143 | _ = j 144 | } 145 | 146 | for i, j /* ERROR "declared but not used" */ := range s { 147 | _ = func() int { 148 | return i 149 | } 150 | } 151 | return 152 | } 153 | 154 | // Invalid (unused) expressions must not lead to spurious "declared but not used errors" 155 | func _() { 156 | var a, b, c int 157 | var x, y int 158 | x, y = a /* ERROR assignment count mismatch */ , b, c 159 | _ = x 160 | _ = y 161 | } 162 | 163 | func _() { 164 | var x int 165 | return x /* ERROR no result values expected */ 166 | return math /* ERROR no result values expected */ .Sin(0) 167 | } 168 | 169 | func _() int { 170 | var x, y int 171 | return /* ERROR wrong number of return values */ x, y 172 | } 173 | 174 | // Short variable declarations must declare at least one new non-blank variable. 175 | func _() { 176 | _ := /* ERROR no new variables */ 0 177 | _, a := 0, 1 178 | _, a := /* ERROR no new variables */ 0, 1 179 | _, a, b := 0, 1, 2 180 | _, _, _ := /* ERROR no new variables */ 0, 1, 2 181 | 182 | _ = a 183 | _ = b 184 | } 185 | 186 | // TODO(gri) consolidate other var decl checks in this file -------------------------------------------------------------------------------- /types/eval_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file contains tests for Eval. 6 | 7 | package types_test 8 | 9 | import ( 10 | "go/ast" 11 | "go/importer" 12 | "go/parser" 13 | "go/token" 14 | "internal/testenv" 15 | "strings" 16 | "testing" 17 | 18 | . "go/types" 19 | ) 20 | 21 | func testEval(t *testing.T, fset *token.FileSet, pkg *Package, pos token.Pos, expr string, typ Type, typStr, valStr string) { 22 | gotTv, err := Eval(fset, pkg, pos, expr) 23 | if err != nil { 24 | t.Errorf("Eval(%q) failed: %s", expr, err) 25 | return 26 | } 27 | if gotTv.Type == nil { 28 | t.Errorf("Eval(%q) got nil type but no error", expr) 29 | return 30 | } 31 | 32 | // compare types 33 | if typ != nil { 34 | // we have a type, check identity 35 | if !Identical(gotTv.Type, typ) { 36 | t.Errorf("Eval(%q) got type %s, want %s", expr, gotTv.Type, typ) 37 | return 38 | } 39 | } else { 40 | // we have a string, compare type string 41 | gotStr := gotTv.Type.String() 42 | if gotStr != typStr { 43 | t.Errorf("Eval(%q) got type %s, want %s", expr, gotStr, typStr) 44 | return 45 | } 46 | } 47 | 48 | // compare values 49 | gotStr := "" 50 | if gotTv.Value != nil { 51 | gotStr = gotTv.Value.ExactString() 52 | } 53 | if gotStr != valStr { 54 | t.Errorf("Eval(%q) got value %s, want %s", expr, gotStr, valStr) 55 | } 56 | } 57 | 58 | func TestEvalBasic(t *testing.T) { 59 | fset := token.NewFileSet() 60 | for _, typ := range Typ[Bool : String+1] { 61 | testEval(t, fset, nil, token.NoPos, typ.Name(), typ, "", "") 62 | } 63 | } 64 | 65 | func TestEvalComposite(t *testing.T) { 66 | fset := token.NewFileSet() 67 | for _, test := range independentTestTypes { 68 | testEval(t, fset, nil, token.NoPos, test.src, nil, test.str, "") 69 | } 70 | } 71 | 72 | func TestEvalArith(t *testing.T) { 73 | var tests = []string{ 74 | `true`, 75 | `false == false`, 76 | `12345678 + 87654321 == 99999999`, 77 | `10 * 20 == 200`, 78 | `(1<<1000)*2 >> 100 == 2<<900`, 79 | `"foo" + "bar" == "foobar"`, 80 | `"abc" <= "bcd"`, 81 | `len([10]struct{}{}) == 2*5`, 82 | } 83 | fset := token.NewFileSet() 84 | for _, test := range tests { 85 | testEval(t, fset, nil, token.NoPos, test, Typ[UntypedBool], "", "true") 86 | } 87 | } 88 | 89 | func TestEvalPos(t *testing.T) { 90 | testenv.MustHaveGoBuild(t) 91 | 92 | // The contents of /*-style comments are of the form 93 | // expr => value, type 94 | // where value may be the empty string. 95 | // Each expr is evaluated at the position of the comment 96 | // and the result is compared with the expected value 97 | // and type. 98 | var sources = []string{ 99 | ` 100 | package p 101 | import "fmt" 102 | import m "math" 103 | const c = 3.0 104 | type T []int 105 | func f(a int, s string) float64 { 106 | fmt.Println("calling f") 107 | _ = m.Pi // use package math 108 | const d int = c + 1 109 | var x int 110 | x = a + len(s) 111 | return float64(x) 112 | /* true => true, untyped bool */ 113 | /* fmt.Println => , func(a ...interface{}) (n int, err error) */ 114 | /* c => 3, untyped float */ 115 | /* T => , p.T */ 116 | /* a => , int */ 117 | /* s => , string */ 118 | /* d => 4, int */ 119 | /* x => , int */ 120 | /* d/c => 1, int */ 121 | /* c/2 => 3/2, untyped float */ 122 | /* m.Pi < m.E => false, untyped bool */ 123 | } 124 | `, 125 | ` 126 | package p 127 | /* c => 3, untyped float */ 128 | type T1 /* T1 => , p.T1 */ struct {} 129 | var v1 /* v1 => , int */ = 42 130 | func /* f1 => , func(v1 float64) */ f1(v1 float64) { 131 | /* f1 => , func(v1 float64) */ 132 | /* v1 => , float64 */ 133 | var c /* c => 3, untyped float */ = "foo" /* c => , string */ 134 | { 135 | var c struct { 136 | c /* c => , string */ int 137 | } 138 | /* c => , struct{c int} */ 139 | _ = c 140 | } 141 | _ = func(a, b, c int) /* c => , string */ { 142 | /* c => , int */ 143 | } 144 | _ = c 145 | type FT /* FT => , p.FT */ interface{} 146 | } 147 | `, 148 | ` 149 | package p 150 | /* T => , p.T */ 151 | `, 152 | } 153 | 154 | fset := token.NewFileSet() 155 | var files []*ast.File 156 | for i, src := range sources { 157 | file, err := parser.ParseFile(fset, "p", src, parser.ParseComments) 158 | if err != nil { 159 | t.Fatalf("could not parse file %d: %s", i, err) 160 | } 161 | files = append(files, file) 162 | } 163 | 164 | conf := Config{Importer: importer.Default()} 165 | pkg, err := conf.Check("p", fset, files, nil) 166 | if err != nil { 167 | t.Fatal(err) 168 | } 169 | 170 | for _, file := range files { 171 | for _, group := range file.Comments { 172 | for _, comment := range group.List { 173 | s := comment.Text 174 | if len(s) >= 4 && s[:2] == "/*" && s[len(s)-2:] == "*/" { 175 | str, typ := split(s[2:len(s)-2], ", ") 176 | str, val := split(str, "=>") 177 | testEval(t, fset, pkg, comment.Pos(), str, nil, typ, val) 178 | } 179 | } 180 | } 181 | } 182 | } 183 | 184 | // split splits string s at the first occurrence of s. 185 | func split(s, sep string) (string, string) { 186 | i := strings.Index(s, sep) 187 | return strings.TrimSpace(s[:i]), strings.TrimSpace(s[i+len(sep):]) 188 | } 189 | -------------------------------------------------------------------------------- /types/return.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements isTerminating. 6 | 7 | package types 8 | 9 | import ( 10 | "go/ast" 11 | "go/token" 12 | ) 13 | 14 | // isTerminating reports if s is a terminating statement. 15 | // If s is labeled, label is the label name; otherwise s 16 | // is "". 17 | func (check *Checker) isTerminating(s ast.Stmt, label string) bool { 18 | switch s := s.(type) { 19 | default: 20 | unreachable() 21 | 22 | case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.SendStmt, 23 | *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, *ast.DeferStmt, 24 | *ast.RangeStmt: 25 | // no chance 26 | 27 | case *ast.LabeledStmt: 28 | return check.isTerminating(s.Stmt, s.Label.Name) 29 | 30 | case *ast.ExprStmt: 31 | // the predeclared (possibly parenthesized) panic() function is terminating 32 | if call, _ := unparen(s.X).(*ast.CallExpr); call != nil { 33 | if id, _ := call.Fun.(*ast.Ident); id != nil { 34 | if _, obj := check.scope.LookupParent(id.Name, token.NoPos); obj != nil { 35 | if b, _ := obj.(*Builtin); b != nil && b.id == _Panic { 36 | return true 37 | } 38 | } 39 | } 40 | } 41 | 42 | case *ast.ReturnStmt: 43 | return true 44 | 45 | case *ast.BranchStmt: 46 | if s.Tok == token.GOTO || s.Tok == token.FALLTHROUGH { 47 | return true 48 | } 49 | 50 | case *ast.BlockStmt: 51 | return check.isTerminatingList(s.List, "") 52 | 53 | case *ast.IfStmt: 54 | if s.Else != nil && 55 | check.isTerminating(s.Body, "") && 56 | check.isTerminating(s.Else, "") { 57 | return true 58 | } 59 | 60 | case *ast.SwitchStmt: 61 | return check.isTerminatingSwitch(s.Body, label) 62 | 63 | case *ast.TypeSwitchStmt: 64 | return check.isTerminatingSwitch(s.Body, label) 65 | 66 | case *ast.SelectStmt: 67 | for _, s := range s.Body.List { 68 | cc := s.(*ast.CommClause) 69 | if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) { 70 | return false 71 | } 72 | 73 | } 74 | return true 75 | 76 | case *ast.ForStmt: 77 | if s.Cond == nil && !hasBreak(s.Body, label, true) { 78 | return true 79 | } 80 | } 81 | 82 | return false 83 | } 84 | 85 | func (check *Checker) isTerminatingList(list []ast.Stmt, label string) bool { 86 | // trailing empty statements are permitted - skip them 87 | for i := len(list) - 1; i >= 0; i-- { 88 | if _, ok := list[i].(*ast.EmptyStmt); !ok { 89 | return check.isTerminating(list[i], label) 90 | } 91 | } 92 | return false // all statements are empty 93 | } 94 | 95 | func (check *Checker) isTerminatingSwitch(body *ast.BlockStmt, label string) bool { 96 | hasDefault := false 97 | for _, s := range body.List { 98 | cc := s.(*ast.CaseClause) 99 | if cc.List == nil { 100 | hasDefault = true 101 | } 102 | if !check.isTerminatingList(cc.Body, "") || hasBreakList(cc.Body, label, true) { 103 | return false 104 | } 105 | } 106 | return hasDefault 107 | } 108 | 109 | // TODO(gri) For nested breakable statements, the current implementation of hasBreak 110 | // will traverse the same subtree repeatedly, once for each label. Replace 111 | // with a single-pass label/break matching phase. 112 | 113 | // hasBreak reports if s is or contains a break statement 114 | // referring to the label-ed statement or implicit-ly the 115 | // closest outer breakable statement. 116 | func hasBreak(s ast.Stmt, label string, implicit bool) bool { 117 | switch s := s.(type) { 118 | default: 119 | unreachable() 120 | 121 | case *ast.BadStmt, *ast.DeclStmt, *ast.EmptyStmt, *ast.ExprStmt, 122 | *ast.SendStmt, *ast.IncDecStmt, *ast.AssignStmt, *ast.GoStmt, 123 | *ast.DeferStmt, *ast.ReturnStmt: 124 | // no chance 125 | 126 | case *ast.LabeledStmt: 127 | return hasBreak(s.Stmt, label, implicit) 128 | 129 | case *ast.BranchStmt: 130 | if s.Tok == token.BREAK { 131 | if s.Label == nil { 132 | return implicit 133 | } 134 | if s.Label.Name == label { 135 | return true 136 | } 137 | } 138 | 139 | case *ast.BlockStmt: 140 | return hasBreakList(s.List, label, implicit) 141 | 142 | case *ast.IfStmt: 143 | if hasBreak(s.Body, label, implicit) || 144 | s.Else != nil && hasBreak(s.Else, label, implicit) { 145 | return true 146 | } 147 | 148 | case *ast.CaseClause: 149 | return hasBreakList(s.Body, label, implicit) 150 | 151 | case *ast.SwitchStmt: 152 | if label != "" && hasBreak(s.Body, label, false) { 153 | return true 154 | } 155 | 156 | case *ast.TypeSwitchStmt: 157 | if label != "" && hasBreak(s.Body, label, false) { 158 | return true 159 | } 160 | 161 | case *ast.CommClause: 162 | return hasBreakList(s.Body, label, implicit) 163 | 164 | case *ast.SelectStmt: 165 | if label != "" && hasBreak(s.Body, label, false) { 166 | return true 167 | } 168 | 169 | case *ast.ForStmt: 170 | if label != "" && hasBreak(s.Body, label, false) { 171 | return true 172 | } 173 | 174 | case *ast.RangeStmt: 175 | if label != "" && hasBreak(s.Body, label, false) { 176 | return true 177 | } 178 | } 179 | 180 | return false 181 | } 182 | 183 | func hasBreakList(list []ast.Stmt, label string, implicit bool) bool { 184 | for _, s := range list { 185 | if hasBreak(s, label, implicit) { 186 | return true 187 | } 188 | } 189 | return false 190 | } 191 | -------------------------------------------------------------------------------- /types/exprstring.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements printing of expressions. 6 | 7 | package types 8 | 9 | import ( 10 | "bytes" 11 | "go/ast" 12 | ) 13 | 14 | // ExprString returns the (possibly simplified) string representation for x. 15 | func ExprString(x ast.Expr) string { 16 | var buf bytes.Buffer 17 | WriteExpr(&buf, x) 18 | return buf.String() 19 | } 20 | 21 | // WriteExpr writes the (possibly simplified) string representation for x to buf. 22 | func WriteExpr(buf *bytes.Buffer, x ast.Expr) { 23 | // The AST preserves source-level parentheses so there is 24 | // no need to introduce them here to correct for different 25 | // operator precedences. (This assumes that the AST was 26 | // generated by a Go parser.) 27 | 28 | switch x := x.(type) { 29 | default: 30 | buf.WriteString("(bad expr)") // nil, ast.BadExpr, ast.KeyValueExpr 31 | 32 | case *ast.Ident: 33 | buf.WriteString(x.Name) 34 | 35 | case *ast.Ellipsis: 36 | buf.WriteString("...") 37 | if x.Elt != nil { 38 | WriteExpr(buf, x.Elt) 39 | } 40 | 41 | case *ast.BasicLit: 42 | buf.WriteString(x.Value) 43 | 44 | case *ast.FuncLit: 45 | buf.WriteByte('(') 46 | WriteExpr(buf, x.Type) 47 | buf.WriteString(" literal)") // simplified 48 | 49 | case *ast.CompositeLit: 50 | buf.WriteByte('(') 51 | WriteExpr(buf, x.Type) 52 | buf.WriteString(" literal)") // simplified 53 | 54 | case *ast.ParenExpr: 55 | buf.WriteByte('(') 56 | WriteExpr(buf, x.X) 57 | buf.WriteByte(')') 58 | 59 | case *ast.SelectorExpr: 60 | WriteExpr(buf, x.X) 61 | buf.WriteByte('.') 62 | buf.WriteString(x.Sel.Name) 63 | 64 | case *ast.IndexExpr: 65 | WriteExpr(buf, x.X) 66 | buf.WriteByte('[') 67 | WriteExpr(buf, x.Index) 68 | buf.WriteByte(']') 69 | 70 | case *ast.SliceExpr: 71 | WriteExpr(buf, x.X) 72 | buf.WriteByte('[') 73 | if x.Low != nil { 74 | WriteExpr(buf, x.Low) 75 | } 76 | buf.WriteByte(':') 77 | if x.High != nil { 78 | WriteExpr(buf, x.High) 79 | } 80 | if x.Slice3 { 81 | buf.WriteByte(':') 82 | if x.Max != nil { 83 | WriteExpr(buf, x.Max) 84 | } 85 | } 86 | buf.WriteByte(']') 87 | 88 | case *ast.TypeAssertExpr: 89 | WriteExpr(buf, x.X) 90 | buf.WriteString(".(") 91 | WriteExpr(buf, x.Type) 92 | buf.WriteByte(')') 93 | 94 | case *ast.CallExpr: 95 | WriteExpr(buf, x.Fun) 96 | buf.WriteByte('(') 97 | for i, arg := range x.Args { 98 | if i > 0 { 99 | buf.WriteString(", ") 100 | } 101 | WriteExpr(buf, arg) 102 | } 103 | if x.Ellipsis.IsValid() { 104 | buf.WriteString("...") 105 | } 106 | buf.WriteByte(')') 107 | 108 | case *ast.StarExpr: 109 | buf.WriteByte('*') 110 | WriteExpr(buf, x.X) 111 | 112 | case *ast.UnaryExpr: 113 | buf.WriteString(x.Op.String()) 114 | WriteExpr(buf, x.X) 115 | 116 | case *ast.BinaryExpr: 117 | WriteExpr(buf, x.X) 118 | buf.WriteByte(' ') 119 | buf.WriteString(x.Op.String()) 120 | buf.WriteByte(' ') 121 | WriteExpr(buf, x.Y) 122 | 123 | case *ast.ArrayType: 124 | buf.WriteByte('[') 125 | if x.Len != nil { 126 | WriteExpr(buf, x.Len) 127 | } 128 | buf.WriteByte(']') 129 | WriteExpr(buf, x.Elt) 130 | 131 | case *ast.StructType: 132 | buf.WriteString("struct{") 133 | writeFieldList(buf, x.Fields, "; ", false) 134 | buf.WriteByte('}') 135 | 136 | case *ast.FuncType: 137 | buf.WriteString("func") 138 | writeSigExpr(buf, x) 139 | 140 | case *ast.InterfaceType: 141 | buf.WriteString("interface{") 142 | writeFieldList(buf, x.Methods, "; ", true) 143 | buf.WriteByte('}') 144 | 145 | case *ast.MapType: 146 | buf.WriteString("map[") 147 | WriteExpr(buf, x.Key) 148 | buf.WriteByte(']') 149 | WriteExpr(buf, x.Value) 150 | 151 | case *ast.ChanType: 152 | var s string 153 | switch x.Dir { 154 | case ast.SEND: 155 | s = "chan<- " 156 | case ast.RECV: 157 | s = "<-chan " 158 | default: 159 | s = "chan " 160 | } 161 | buf.WriteString(s) 162 | WriteExpr(buf, x.Value) 163 | } 164 | } 165 | 166 | func writeSigExpr(buf *bytes.Buffer, sig *ast.FuncType) { 167 | buf.WriteByte('(') 168 | writeFieldList(buf, sig.Params, ", ", false) 169 | buf.WriteByte(')') 170 | 171 | res := sig.Results 172 | n := res.NumFields() 173 | if n == 0 { 174 | // no result 175 | return 176 | } 177 | 178 | buf.WriteByte(' ') 179 | if n == 1 && len(res.List[0].Names) == 0 { 180 | // single unnamed result 181 | WriteExpr(buf, res.List[0].Type) 182 | return 183 | } 184 | 185 | // multiple or named result(s) 186 | buf.WriteByte('(') 187 | writeFieldList(buf, res, ", ", false) 188 | buf.WriteByte(')') 189 | } 190 | 191 | func writeFieldList(buf *bytes.Buffer, fields *ast.FieldList, sep string, iface bool) { 192 | for i, f := range fields.List { 193 | if i > 0 { 194 | buf.WriteString(sep) 195 | } 196 | 197 | // field list names 198 | for i, name := range f.Names { 199 | if i > 0 { 200 | buf.WriteString(", ") 201 | } 202 | buf.WriteString(name.Name) 203 | } 204 | 205 | // types of interface methods consist of signatures only 206 | if sig, _ := f.Type.(*ast.FuncType); sig != nil && iface { 207 | writeSigExpr(buf, sig) 208 | continue 209 | } 210 | 211 | // named fields are separated with a blank from the field type 212 | if len(f.Names) > 0 { 213 | buf.WriteByte(' ') 214 | } 215 | 216 | WriteExpr(buf, f.Type) 217 | 218 | // ignore tag 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /types/testdata/expr2.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // comparisons 6 | 7 | package expr2 8 | 9 | func _bool() { 10 | const t = true == true 11 | const f = true == false 12 | _ = t /* ERROR "cannot compare" */ < f 13 | _ = 0 /* ERROR "cannot convert" */ == t 14 | var b bool 15 | var x, y float32 16 | b = x < y 17 | _ = b 18 | _ = struct{b bool}{x < y} 19 | } 20 | 21 | // corner cases 22 | var ( 23 | v0 = nil /* ERROR "cannot compare" */ == nil 24 | ) 25 | 26 | func arrays() { 27 | // basics 28 | var a, b [10]int 29 | _ = a == b 30 | _ = a != b 31 | _ = a /* ERROR < not defined */ < b 32 | _ = a == nil /* ERROR cannot convert */ 33 | 34 | type C [10]int 35 | var c C 36 | _ = a == c 37 | 38 | type D [10]int 39 | var d D 40 | _ = c /* ERROR mismatched types */ == d 41 | 42 | var e [10]func() int 43 | _ = e /* ERROR == not defined */ == e 44 | } 45 | 46 | func structs() { 47 | // basics 48 | var s, t struct { 49 | x int 50 | a [10]float32 51 | _ bool 52 | } 53 | _ = s == t 54 | _ = s != t 55 | _ = s /* ERROR < not defined */ < t 56 | _ = s == nil /* ERROR cannot convert */ 57 | 58 | type S struct { 59 | x int 60 | a [10]float32 61 | _ bool 62 | } 63 | type T struct { 64 | x int 65 | a [10]float32 66 | _ bool 67 | } 68 | var ss S 69 | var tt T 70 | _ = s == ss 71 | _ = ss /* ERROR mismatched types */ == tt 72 | 73 | var u struct { 74 | x int 75 | a [10]map[string]int 76 | } 77 | _ = u /* ERROR cannot compare */ == u 78 | } 79 | 80 | func pointers() { 81 | // nil 82 | _ = nil /* ERROR == not defined */ == nil 83 | _ = nil /* ERROR != not defined */ != nil 84 | _ = nil /* ERROR < not defined */ < nil 85 | _ = nil /* ERROR <= not defined */ <= nil 86 | _ = nil /* ERROR > not defined */ > nil 87 | _ = nil /* ERROR >= not defined */ >= nil 88 | 89 | // basics 90 | var p, q *int 91 | _ = p == q 92 | _ = p != q 93 | 94 | _ = p == nil 95 | _ = p != nil 96 | _ = nil == q 97 | _ = nil != q 98 | 99 | _ = p /* ERROR < not defined */ < q 100 | _ = p /* ERROR <= not defined */ <= q 101 | _ = p /* ERROR > not defined */ > q 102 | _ = p /* ERROR >= not defined */ >= q 103 | 104 | // various element types 105 | type ( 106 | S1 struct{} 107 | S2 struct{} 108 | P1 *S1 109 | P2 *S2 110 | ) 111 | var ( 112 | ps1 *S1 113 | ps2 *S2 114 | p1 P1 115 | p2 P2 116 | ) 117 | _ = ps1 == ps1 118 | _ = ps1 /* ERROR mismatched types */ == ps2 119 | _ = ps2 /* ERROR mismatched types */ == ps1 120 | 121 | _ = p1 == p1 122 | _ = p1 /* ERROR mismatched types */ == p2 123 | 124 | _ = p1 == ps1 125 | } 126 | 127 | func channels() { 128 | // basics 129 | var c, d chan int 130 | _ = c == d 131 | _ = c != d 132 | _ = c == nil 133 | _ = c /* ERROR < not defined */ < d 134 | 135 | // various element types (named types) 136 | type ( 137 | C1 chan int 138 | C1r <-chan int 139 | C1s chan<- int 140 | C2 chan float32 141 | ) 142 | var ( 143 | c1 C1 144 | c1r C1r 145 | c1s C1s 146 | c1a chan int 147 | c2 C2 148 | ) 149 | _ = c1 == c1 150 | _ = c1 /* ERROR mismatched types */ == c1r 151 | _ = c1 /* ERROR mismatched types */ == c1s 152 | _ = c1r /* ERROR mismatched types */ == c1s 153 | _ = c1 == c1a 154 | _ = c1a == c1 155 | _ = c1 /* ERROR mismatched types */ == c2 156 | _ = c1a /* ERROR mismatched types */ == c2 157 | 158 | // various element types (unnamed types) 159 | var ( 160 | d1 chan int 161 | d1r <-chan int 162 | d1s chan<- int 163 | d1a chan<- int 164 | d2 chan float32 165 | ) 166 | _ = d1 == d1 167 | _ = d1 == d1r 168 | _ = d1 == d1s 169 | _ = d1r /* ERROR mismatched types */ == d1s 170 | _ = d1 == d1a 171 | _ = d1a == d1 172 | _ = d1 /* ERROR mismatched types */ == d2 173 | _ = d1a /* ERROR mismatched types */ == d2 174 | } 175 | 176 | // for interfaces test 177 | type S1 struct{} 178 | type S11 struct{} 179 | type S2 struct{} 180 | func (*S1) m() int 181 | func (*S11) m() int 182 | func (*S11) n() 183 | func (*S2) m() float32 184 | 185 | func interfaces() { 186 | // basics 187 | var i, j interface{ m() int } 188 | _ = i == j 189 | _ = i != j 190 | _ = i == nil 191 | _ = i /* ERROR < not defined */ < j 192 | 193 | // various interfaces 194 | var ii interface { m() int; n() } 195 | var k interface { m() float32 } 196 | _ = i == ii 197 | _ = i /* ERROR mismatched types */ == k 198 | 199 | // interfaces vs values 200 | var s1 S1 201 | var s11 S11 202 | var s2 S2 203 | 204 | _ = i == 0 /* ERROR cannot convert */ 205 | _ = i /* ERROR mismatched types */ == s1 206 | _ = i == &s1 207 | _ = i == &s11 208 | 209 | _ = i /* ERROR mismatched types */ == s2 210 | _ = i /* ERROR mismatched types */ == &s2 211 | } 212 | 213 | func slices() { 214 | // basics 215 | var s []int 216 | _ = s == nil 217 | _ = s != nil 218 | _ = s /* ERROR < not defined */ < nil 219 | 220 | // slices are not otherwise comparable 221 | _ = s /* ERROR == not defined */ == s 222 | _ = s /* ERROR < not defined */ < s 223 | } 224 | 225 | func maps() { 226 | // basics 227 | var m map[string]int 228 | _ = m == nil 229 | _ = m != nil 230 | _ = m /* ERROR < not defined */ < nil 231 | 232 | // maps are not otherwise comparable 233 | _ = m /* ERROR == not defined */ == m 234 | _ = m /* ERROR < not defined */ < m 235 | } 236 | 237 | func funcs() { 238 | // basics 239 | var f func(int) float32 240 | _ = f == nil 241 | _ = f != nil 242 | _ = f /* ERROR < not defined */ < nil 243 | 244 | // funcs are not otherwise comparable 245 | _ = f /* ERROR == not defined */ == f 246 | _ = f /* ERROR < not defined */ < f 247 | } 248 | -------------------------------------------------------------------------------- /types/resolver_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package types_test 6 | 7 | import ( 8 | "fmt" 9 | "go/ast" 10 | "go/importer" 11 | "go/parser" 12 | "go/token" 13 | "internal/testenv" 14 | "sort" 15 | "testing" 16 | 17 | . "go/types" 18 | ) 19 | 20 | type resolveTestImporter struct { 21 | importer ImporterFrom 22 | imported map[string]bool 23 | } 24 | 25 | func (imp *resolveTestImporter) Import(string) (*Package, error) { 26 | panic("should not be called") 27 | } 28 | 29 | func (imp *resolveTestImporter) ImportFrom(path, srcDir string, mode ImportMode) (*Package, error) { 30 | if mode != 0 { 31 | panic("mode must be 0") 32 | } 33 | if imp.importer == nil { 34 | imp.importer = importer.Default().(ImporterFrom) 35 | imp.imported = make(map[string]bool) 36 | } 37 | pkg, err := imp.importer.ImportFrom(path, srcDir, mode) 38 | if err != nil { 39 | return nil, err 40 | } 41 | imp.imported[path] = true 42 | return pkg, nil 43 | } 44 | 45 | func TestResolveIdents(t *testing.T) { 46 | testenv.MustHaveGoBuild(t) 47 | 48 | sources := []string{ 49 | ` 50 | package p 51 | import "fmt" 52 | import "math" 53 | const pi = math.Pi 54 | func sin(x float64) float64 { 55 | return math.Sin(x) 56 | } 57 | var Println = fmt.Println 58 | `, 59 | ` 60 | package p 61 | import "fmt" 62 | type errorStringer struct { fmt.Stringer; error } 63 | func f() string { 64 | _ = "foo" 65 | return fmt.Sprintf("%d", g()) 66 | } 67 | func g() (x int) { return } 68 | `, 69 | ` 70 | package p 71 | import . "go/parser" 72 | import "sync" 73 | func h() Mode { return ImportsOnly } 74 | var _, x int = 1, 2 75 | func init() {} 76 | type T struct{ *sync.Mutex; a, b, c int} 77 | type I interface{ m() } 78 | var _ = T{a: 1, b: 2, c: 3} 79 | func (_ T) m() {} 80 | func (T) _() {} 81 | var i I 82 | var _ = i.m 83 | func _(s []int) { for i, x := range s { _, _ = i, x } } 84 | func _(x interface{}) { 85 | switch x := x.(type) { 86 | case int: 87 | _ = x 88 | } 89 | switch {} // implicit 'true' tag 90 | } 91 | `, 92 | ` 93 | package p 94 | type S struct{} 95 | func (T) _() {} 96 | func (T) _() {} 97 | `, 98 | ` 99 | package p 100 | func _() { 101 | L0: 102 | L1: 103 | goto L0 104 | for { 105 | goto L1 106 | } 107 | if true { 108 | goto L2 109 | } 110 | L2: 111 | } 112 | `, 113 | } 114 | 115 | pkgnames := []string{ 116 | "fmt", 117 | "math", 118 | } 119 | 120 | // parse package files 121 | fset := token.NewFileSet() 122 | var files []*ast.File 123 | for i, src := range sources { 124 | f, err := parser.ParseFile(fset, fmt.Sprintf("sources[%d]", i), src, parser.DeclarationErrors) 125 | if err != nil { 126 | t.Fatal(err) 127 | } 128 | files = append(files, f) 129 | } 130 | 131 | // resolve and type-check package AST 132 | importer := new(resolveTestImporter) 133 | conf := Config{Importer: importer} 134 | uses := make(map[*ast.Ident]Object) 135 | defs := make(map[*ast.Ident]Object) 136 | _, err := conf.Check("testResolveIdents", fset, files, &Info{Defs: defs, Uses: uses}) 137 | if err != nil { 138 | t.Fatal(err) 139 | } 140 | 141 | // check that all packages were imported 142 | for _, name := range pkgnames { 143 | if !importer.imported[name] { 144 | t.Errorf("package %s not imported", name) 145 | } 146 | } 147 | 148 | // check that qualified identifiers are resolved 149 | for _, f := range files { 150 | ast.Inspect(f, func(n ast.Node) bool { 151 | if s, ok := n.(*ast.SelectorExpr); ok { 152 | if x, ok := s.X.(*ast.Ident); ok { 153 | obj := uses[x] 154 | if obj == nil { 155 | t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name) 156 | return false 157 | } 158 | if _, ok := obj.(*PkgName); ok && uses[s.Sel] == nil { 159 | t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name) 160 | return false 161 | } 162 | return false 163 | } 164 | return false 165 | } 166 | return true 167 | }) 168 | } 169 | 170 | for id, obj := range uses { 171 | if obj == nil { 172 | t.Errorf("%s: Uses[%s] == nil", fset.Position(id.Pos()), id.Name) 173 | } 174 | } 175 | 176 | // check that each identifier in the source is found in uses or defs or both 177 | var both []string 178 | for _, f := range files { 179 | ast.Inspect(f, func(n ast.Node) bool { 180 | if x, ok := n.(*ast.Ident); ok { 181 | var objects int 182 | if _, found := uses[x]; found { 183 | objects |= 1 184 | delete(uses, x) 185 | } 186 | if _, found := defs[x]; found { 187 | objects |= 2 188 | delete(defs, x) 189 | } 190 | if objects == 0 { 191 | t.Errorf("%s: unresolved identifier %s", fset.Position(x.Pos()), x.Name) 192 | } else if objects == 3 { 193 | both = append(both, x.Name) 194 | } 195 | return false 196 | } 197 | return true 198 | }) 199 | } 200 | 201 | // check the expected set of idents that are simultaneously uses and defs 202 | sort.Strings(both) 203 | if got, want := fmt.Sprint(both), "[Mutex Stringer error]"; got != want { 204 | t.Errorf("simultaneous uses/defs = %s, want %s", got, want) 205 | } 206 | 207 | // any left-over identifiers didn't exist in the source 208 | for x := range uses { 209 | t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name) 210 | } 211 | for x := range defs { 212 | t.Errorf("%s: identifier %s not present in source", fset.Position(x.Pos()), x.Name) 213 | } 214 | 215 | // TODO(gri) add tests to check ImplicitObj callbacks 216 | } 217 | -------------------------------------------------------------------------------- /types/testdata/decls3.src: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // embedded types 6 | 7 | package decls3 8 | 9 | import "unsafe" 10 | import "fmt" 11 | 12 | // fields with the same name at the same level cancel each other out 13 | 14 | func _() { 15 | type ( 16 | T1 struct { X int } 17 | T2 struct { X int } 18 | T3 struct { T1; T2 } // X is embedded twice at the same level via T1->X, T2->X 19 | ) 20 | 21 | var t T3 22 | _ = t /* ERROR "ambiguous selector" */ .X 23 | } 24 | 25 | func _() { 26 | type ( 27 | T1 struct { X int } 28 | T2 struct { T1 } 29 | T3 struct { T1 } 30 | T4 struct { T2; T3 } // X is embedded twice at the same level via T2->T1->X, T3->T1->X 31 | ) 32 | 33 | var t T4 34 | _ = t /* ERROR "ambiguous selector" */ .X 35 | } 36 | 37 | func issue4355() { 38 | type ( 39 | T1 struct {X int} 40 | T2 struct {T1} 41 | T3 struct {T2} 42 | T4 struct {T2} 43 | T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X 44 | ) 45 | 46 | var t T5 47 | _ = t /* ERROR "ambiguous selector" */ .X 48 | } 49 | 50 | func _() { 51 | type State int 52 | type A struct{ State } 53 | type B struct{ fmt.State } 54 | type T struct{ A; B } 55 | 56 | var t T 57 | _ = t /* ERROR "ambiguous selector" */ .State 58 | } 59 | 60 | // Embedded fields can be predeclared types. 61 | 62 | func _() { 63 | type T0 struct{ 64 | int 65 | float32 66 | f int 67 | } 68 | var x T0 69 | _ = x.int 70 | _ = x.float32 71 | _ = x.f 72 | 73 | type T1 struct{ 74 | T0 75 | } 76 | var y T1 77 | _ = y.int 78 | _ = y.float32 79 | _ = y.f 80 | } 81 | 82 | // Restrictions on embedded field types. 83 | 84 | func _() { 85 | type I1 interface{} 86 | type I2 interface{} 87 | type P1 *int 88 | type P2 *int 89 | type UP unsafe.Pointer 90 | 91 | type T1 struct { 92 | I1 93 | * /* ERROR "cannot be a pointer to an interface" */ I2 94 | * /* ERROR "cannot be a pointer to an interface" */ error 95 | P1 /* ERROR "cannot be a pointer" */ 96 | * /* ERROR "cannot be a pointer" */ P2 97 | } 98 | 99 | // unsafe.Pointers are treated like regular pointers when embedded 100 | type T2 struct { 101 | unsafe /* ERROR "cannot be unsafe.Pointer" */ .Pointer 102 | */* ERROR "cannot be unsafe.Pointer" */ unsafe.Pointer 103 | UP /* ERROR "cannot be unsafe.Pointer" */ 104 | * /* ERROR "cannot be unsafe.Pointer" */ UP 105 | } 106 | } 107 | 108 | // Named types that are pointers. 109 | 110 | type S struct{ x int } 111 | func (*S) m() {} 112 | type P *S 113 | 114 | func _() { 115 | var s *S 116 | _ = s.x 117 | _ = s.m 118 | 119 | var p P 120 | _ = p.x 121 | _ = p /* ERROR "no field or method" */ .m 122 | _ = P /* ERROR "no field or method" */ .m 123 | } 124 | 125 | // Borrowed from the FieldByName test cases in reflect/all_test.go. 126 | 127 | type D1 struct { 128 | d int 129 | } 130 | type D2 struct { 131 | d int 132 | } 133 | 134 | type S0 struct { 135 | A, B, C int 136 | D1 137 | D2 138 | } 139 | 140 | type S1 struct { 141 | B int 142 | S0 143 | } 144 | 145 | type S2 struct { 146 | A int 147 | *S1 148 | } 149 | 150 | type S1x struct { 151 | S1 152 | } 153 | 154 | type S1y struct { 155 | S1 156 | } 157 | 158 | type S3 struct { 159 | S1x 160 | S2 161 | D, E int 162 | *S1y 163 | } 164 | 165 | type S4 struct { 166 | *S4 167 | A int 168 | } 169 | 170 | // The X in S6 and S7 annihilate, but they also block the X in S8.S9. 171 | type S5 struct { 172 | S6 173 | S7 174 | S8 175 | } 176 | 177 | type S6 struct { 178 | X int 179 | } 180 | 181 | type S7 S6 182 | 183 | type S8 struct { 184 | S9 185 | } 186 | 187 | type S9 struct { 188 | X int 189 | Y int 190 | } 191 | 192 | // The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. 193 | type S10 struct { 194 | S11 195 | S12 196 | S13 197 | } 198 | 199 | type S11 struct { 200 | S6 201 | } 202 | 203 | type S12 struct { 204 | S6 205 | } 206 | 207 | type S13 struct { 208 | S8 209 | } 210 | 211 | func _() { 212 | _ = struct /* ERROR "no field or method" */ {}{}.Foo 213 | _ = S0{}.A 214 | _ = S0 /* ERROR "no field or method" */ {}.D 215 | _ = S1{}.A 216 | _ = S1{}.B 217 | _ = S1{}.S0 218 | _ = S1{}.C 219 | _ = S2{}.A 220 | _ = S2{}.S1 221 | _ = S2{}.B 222 | _ = S2{}.C 223 | _ = S2 /* ERROR "no field or method" */ {}.D 224 | _ = S3 /* ERROR "ambiguous selector" */ {}.S1 225 | _ = S3{}.A 226 | _ = S3 /* ERROR "ambiguous selector" */ {}.B 227 | _ = S3{}.D 228 | _ = S3{}.E 229 | _ = S4{}.A 230 | _ = S4 /* ERROR "no field or method" */ {}.B 231 | _ = S5 /* ERROR "ambiguous selector" */ {}.X 232 | _ = S5{}.Y 233 | _ = S10 /* ERROR "ambiguous selector" */ {}.X 234 | _ = S10{}.Y 235 | } 236 | 237 | // Borrowed from the FieldByName benchmark in reflect/all_test.go. 238 | 239 | type R0 struct { 240 | *R1 241 | *R2 242 | *R3 243 | *R4 244 | } 245 | 246 | type R1 struct { 247 | *R5 248 | *R6 249 | *R7 250 | *R8 251 | } 252 | 253 | type R2 R1 254 | type R3 R1 255 | type R4 R1 256 | 257 | type R5 struct { 258 | *R9 259 | *R10 260 | *R11 261 | *R12 262 | } 263 | 264 | type R6 R5 265 | type R7 R5 266 | type R8 R5 267 | 268 | type R9 struct { 269 | *R13 270 | *R14 271 | *R15 272 | *R16 273 | } 274 | 275 | type R10 R9 276 | type R11 R9 277 | type R12 R9 278 | 279 | type R13 struct { 280 | *R17 281 | *R18 282 | *R19 283 | *R20 284 | } 285 | 286 | type R14 R13 287 | type R15 R13 288 | type R16 R13 289 | 290 | type R17 struct { 291 | *R21 292 | *R22 293 | *R23 294 | *R24 295 | } 296 | 297 | type R18 R17 298 | type R19 R17 299 | type R20 R17 300 | 301 | type R21 struct { 302 | X int 303 | } 304 | 305 | type R22 R21 306 | type R23 R21 307 | type R24 R21 308 | 309 | var _ = R0 /* ERROR "ambiguous selector" */ {}.X -------------------------------------------------------------------------------- /importer/gccgoimporter/importer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package gccgoimporter 6 | 7 | import ( 8 | "github.com/lukechampine/ply/types" 9 | "internal/testenv" 10 | "io/ioutil" 11 | "os" 12 | "os/exec" 13 | "path/filepath" 14 | "runtime" 15 | "testing" 16 | ) 17 | 18 | type importerTest struct { 19 | pkgpath, name, want, wantval string 20 | wantinits []string 21 | } 22 | 23 | func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]InitData, test *importerTest) { 24 | pkg, err := imp(make(map[string]*types.Package), test.pkgpath) 25 | if err != nil { 26 | t.Error(err) 27 | return 28 | } 29 | 30 | if test.name != "" { 31 | obj := pkg.Scope().Lookup(test.name) 32 | if obj == nil { 33 | t.Errorf("%s: object not found", test.name) 34 | return 35 | } 36 | 37 | got := types.ObjectString(obj, types.RelativeTo(pkg)) 38 | if got != test.want { 39 | t.Errorf("%s: got %q; want %q", test.name, got, test.want) 40 | } 41 | 42 | if test.wantval != "" { 43 | gotval := obj.(*types.Const).Val().String() 44 | if gotval != test.wantval { 45 | t.Errorf("%s: got val %q; want val %q", test.name, gotval, test.wantval) 46 | } 47 | } 48 | } 49 | 50 | if len(test.wantinits) > 0 { 51 | initdata := initmap[pkg] 52 | found := false 53 | // Check that the package's own init function has the package's priority 54 | for _, pkginit := range initdata.Inits { 55 | if pkginit.InitFunc == test.wantinits[0] { 56 | if initdata.Priority != pkginit.Priority { 57 | t.Errorf("%s: got self priority %d; want %d", test.pkgpath, pkginit.Priority, initdata.Priority) 58 | } 59 | found = true 60 | break 61 | } 62 | } 63 | 64 | if !found { 65 | t.Errorf("%s: could not find expected function %q", test.pkgpath, test.wantinits[0]) 66 | } 67 | 68 | // Each init function in the list other than the first one is a 69 | // dependency of the function immediately before it. Check that 70 | // the init functions appear in descending priority order. 71 | priority := initdata.Priority 72 | for _, wantdepinit := range test.wantinits[1:] { 73 | found = false 74 | for _, pkginit := range initdata.Inits { 75 | if pkginit.InitFunc == wantdepinit { 76 | if priority <= pkginit.Priority { 77 | t.Errorf("%s: got dep priority %d; want less than %d", test.pkgpath, pkginit.Priority, priority) 78 | } 79 | found = true 80 | priority = pkginit.Priority 81 | break 82 | } 83 | } 84 | 85 | if !found { 86 | t.Errorf("%s: could not find expected function %q", test.pkgpath, wantdepinit) 87 | } 88 | } 89 | } 90 | } 91 | 92 | var importerTests = [...]importerTest{ 93 | {pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"}, 94 | {pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1 + -1i)"}, 95 | {pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"}, 96 | {pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1 + -1i)"}, 97 | {pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1 + 1i)"}, 98 | {pkgpath: "conversions", name: "Bits", want: "const Bits Units", wantval: `"bits"`}, 99 | {pkgpath: "time", name: "Duration", want: "type Duration int64"}, 100 | {pkgpath: "time", name: "Nanosecond", want: "const Nanosecond Duration", wantval: "1"}, 101 | {pkgpath: "unicode", name: "IsUpper", want: "func IsUpper(r rune) bool"}, 102 | {pkgpath: "unicode", name: "MaxRune", want: "const MaxRune untyped rune", wantval: "1114111"}, 103 | {pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}}, 104 | } 105 | 106 | func TestGoxImporter(t *testing.T) { 107 | testenv.MustHaveGoBuild(t) 108 | 109 | initmap := make(map[*types.Package]InitData) 110 | imp := GetImporter([]string{"testdata"}, initmap) 111 | 112 | for _, test := range importerTests { 113 | runImporterTest(t, imp, initmap, &test) 114 | } 115 | } 116 | 117 | func TestObjImporter(t *testing.T) { 118 | testenv.MustHaveGoBuild(t) 119 | 120 | // This test relies on gccgo being around, which it most likely will be if we 121 | // were compiled with gccgo. 122 | if runtime.Compiler != "gccgo" { 123 | t.Skip("This test needs gccgo") 124 | return 125 | } 126 | 127 | tmpdir, err := ioutil.TempDir("", "") 128 | if err != nil { 129 | t.Fatal(err) 130 | } 131 | initmap := make(map[*types.Package]InitData) 132 | imp := GetImporter([]string{tmpdir}, initmap) 133 | 134 | artmpdir, err := ioutil.TempDir("", "") 135 | if err != nil { 136 | t.Fatal(err) 137 | } 138 | arinitmap := make(map[*types.Package]InitData) 139 | arimp := GetImporter([]string{artmpdir}, arinitmap) 140 | 141 | for _, test := range importerTests { 142 | gofile := filepath.Join("testdata", test.pkgpath+".go") 143 | ofile := filepath.Join(tmpdir, test.pkgpath+".o") 144 | afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a") 145 | 146 | cmd := exec.Command("gccgo", "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile) 147 | out, err := cmd.CombinedOutput() 148 | if err != nil { 149 | t.Logf("%s", out) 150 | t.Fatalf("gccgo %s failed: %s", gofile, err) 151 | } 152 | 153 | runImporterTest(t, imp, initmap, &test) 154 | 155 | cmd = exec.Command("ar", "cr", afile, ofile) 156 | out, err = cmd.CombinedOutput() 157 | if err != nil { 158 | t.Logf("%s", out) 159 | t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err) 160 | } 161 | 162 | runImporterTest(t, arimp, arinitmap, &test) 163 | 164 | if err = os.Remove(ofile); err != nil { 165 | t.Fatal(err) 166 | } 167 | if err = os.Remove(afile); err != nil { 168 | t.Fatal(err) 169 | } 170 | } 171 | 172 | if err = os.Remove(tmpdir); err != nil { 173 | t.Fatal(err) 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /importer/gccgoimporter/importer.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package gccgoimporter implements Import for gccgo-generated object files. 6 | package gccgoimporter 7 | 8 | import ( 9 | "bytes" 10 | "debug/elf" 11 | "fmt" 12 | "io" 13 | "os" 14 | "os/exec" 15 | "path/filepath" 16 | "strings" 17 | 18 | "github.com/lukechampine/ply/types" 19 | ) 20 | 21 | // A PackageInit describes an imported package that needs initialization. 22 | type PackageInit struct { 23 | Name string // short package name 24 | InitFunc string // name of init function 25 | Priority int // priority of init function, see InitData.Priority 26 | } 27 | 28 | // The gccgo-specific init data for a package. 29 | type InitData struct { 30 | // Initialization priority of this package relative to other packages. 31 | // This is based on the maximum depth of the package's dependency graph; 32 | // it is guaranteed to be greater than that of its dependencies. 33 | Priority int 34 | 35 | // The list of packages which this package depends on to be initialized, 36 | // including itself if needed. This is the subset of the transitive closure of 37 | // the package's dependencies that need initialization. 38 | Inits []PackageInit 39 | } 40 | 41 | // Locate the file from which to read export data. 42 | // This is intended to replicate the logic in gofrontend. 43 | func findExportFile(searchpaths []string, pkgpath string) (string, error) { 44 | for _, spath := range searchpaths { 45 | pkgfullpath := filepath.Join(spath, pkgpath) 46 | pkgdir, name := filepath.Split(pkgfullpath) 47 | 48 | for _, filepath := range [...]string{ 49 | pkgfullpath, 50 | pkgfullpath + ".gox", 51 | pkgdir + "lib" + name + ".so", 52 | pkgdir + "lib" + name + ".a", 53 | pkgfullpath + ".o", 54 | } { 55 | fi, err := os.Stat(filepath) 56 | if err == nil && !fi.IsDir() { 57 | return filepath, nil 58 | } 59 | } 60 | } 61 | 62 | return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":")) 63 | } 64 | 65 | const ( 66 | gccgov1Magic = "v1;\n" 67 | gccgov2Magic = "v2;\n" 68 | goimporterMagic = "\n$$ " 69 | archiveMagic = "! 0<<""[""[c1]]>c1 101 | var a2, b2 /* ERROR cycle */ = 0 /* ERROR mismatch */ /* ERROR mismatch */ > 0<<""[b2] 102 | var a3, b3 /* ERROR cycle */ = int /* ERROR mismatch */ /* ERROR mismatch */ (1<<""[b3]) 103 | 104 | // issue10260 105 | // Check that error messages explain reason for interface assignment failures. 106 | type ( 107 | I0 interface{} 108 | I1 interface{ foo() } 109 | I2 interface{ foo(x int) } 110 | T0 struct{} 111 | T1 struct{} 112 | T2 struct{} 113 | ) 114 | 115 | func (*T1) foo() {} 116 | func (*T2) foo(x int) {} 117 | 118 | func issue10260() { 119 | var ( 120 | i0 I0 121 | i1 I1 122 | i2 I2 123 | t0 *T0 124 | t1 *T1 125 | t2 *T2 126 | ) 127 | i1 = i0 /* ERROR cannot use .* missing method foo */ 128 | i1 = t0 /* ERROR cannot use .* missing method foo */ 129 | i1 = i2 /* ERROR cannot use .* wrong type for method foo */ 130 | i1 = t2 /* ERROR cannot use .* wrong type for method foo */ 131 | i2 = i1 /* ERROR cannot use .* wrong type for method foo */ 132 | i2 = t1 /* ERROR cannot use .* wrong type for method foo */ 133 | 134 | _ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ } 135 | _ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ } 136 | _ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ } 137 | _ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ } 138 | _ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ } 139 | _ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ } 140 | 141 | // a few more - less exhaustive now 142 | 143 | f := func(I1, I2){} 144 | f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo */) 145 | 146 | _ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ } 147 | _ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ } 148 | _ = []I1{i0 /* ERROR cannot use .* missing method foo */ } 149 | _ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ } 150 | _ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ } 151 | _ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ } 152 | 153 | make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */ 154 | make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */ 155 | } 156 | 157 | // Check that constants representable as integers are in integer form 158 | // before being used in operations that are only defined on integers. 159 | func issue14229() { 160 | // from the issue 161 | const _ = int64(-1<<63) % 1e6 162 | 163 | // related 164 | const ( 165 | a int = 3 166 | b = 4.0 167 | _ = a / b 168 | _ = a % b 169 | _ = b / a 170 | _ = b % a 171 | ) 172 | } 173 | 174 | // Check that in a n:1 variable declaration with type and initialization 175 | // expression the type is distributed to all variables of the lhs before 176 | // the initialization expression assignment is checked. 177 | func issue15755() { 178 | // from issue 179 | var i interface{} 180 | type b bool 181 | var x, y b = i.(b) 182 | _ = x == y 183 | 184 | // related: we should see an error since the result of f1 is ([]int, int) 185 | var u, v []int = f1 /* ERROR cannot use f1 */ () 186 | _ = u 187 | _ = v 188 | } 189 | -------------------------------------------------------------------------------- /types/scope.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements Scopes. 6 | 7 | package types 8 | 9 | import ( 10 | "bytes" 11 | "fmt" 12 | "go/token" 13 | "io" 14 | "sort" 15 | "strings" 16 | ) 17 | 18 | // TODO(gri) Provide scopes with a name or other mechanism so that 19 | // objects can use that information for better printing. 20 | 21 | // A Scope maintains a set of objects and links to its containing 22 | // (parent) and contained (children) scopes. Objects may be inserted 23 | // and looked up by name. The zero value for Scope is a ready-to-use 24 | // empty scope. 25 | type Scope struct { 26 | parent *Scope 27 | children []*Scope 28 | elems map[string]Object // lazily allocated 29 | pos, end token.Pos // scope extent; may be invalid 30 | comment string // for debugging only 31 | } 32 | 33 | // NewScope returns a new, empty scope contained in the given parent 34 | // scope, if any. The comment is for debugging only. 35 | func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope { 36 | s := &Scope{parent, nil, nil, pos, end, comment} 37 | // don't add children to Universe scope! 38 | if parent != nil && parent != Universe { 39 | parent.children = append(parent.children, s) 40 | } 41 | return s 42 | } 43 | 44 | // Parent returns the scope's containing (parent) scope. 45 | func (s *Scope) Parent() *Scope { return s.parent } 46 | 47 | // Len() returns the number of scope elements. 48 | func (s *Scope) Len() int { return len(s.elems) } 49 | 50 | // Names returns the scope's element names in sorted order. 51 | func (s *Scope) Names() []string { 52 | names := make([]string, len(s.elems)) 53 | i := 0 54 | for name := range s.elems { 55 | names[i] = name 56 | i++ 57 | } 58 | sort.Strings(names) 59 | return names 60 | } 61 | 62 | // NumChildren() returns the number of scopes nested in s. 63 | func (s *Scope) NumChildren() int { return len(s.children) } 64 | 65 | // Child returns the i'th child scope for 0 <= i < NumChildren(). 66 | func (s *Scope) Child(i int) *Scope { return s.children[i] } 67 | 68 | // Lookup returns the object in scope s with the given name if such an 69 | // object exists; otherwise the result is nil. 70 | func (s *Scope) Lookup(name string) Object { 71 | return s.elems[name] 72 | } 73 | 74 | // LookupParent follows the parent chain of scopes starting with s until 75 | // it finds a scope where Lookup(name) returns a non-nil object, and then 76 | // returns that scope and object. If a valid position pos is provided, 77 | // only objects that were declared at or before pos are considered. 78 | // If no such scope and object exists, the result is (nil, nil). 79 | // 80 | // Note that obj.Parent() may be different from the returned scope if the 81 | // object was inserted into the scope and already had a parent at that 82 | // time (see Insert, below). This can only happen for dot-imported objects 83 | // whose scope is the scope of the package that exported them. 84 | func (s *Scope) LookupParent(name string, pos token.Pos) (*Scope, Object) { 85 | for ; s != nil; s = s.parent { 86 | if obj := s.elems[name]; obj != nil && (!pos.IsValid() || obj.scopePos() <= pos) { 87 | return s, obj 88 | } 89 | } 90 | return nil, nil 91 | } 92 | 93 | // Insert attempts to insert an object obj into scope s. 94 | // If s already contains an alternative object alt with 95 | // the same name, Insert leaves s unchanged and returns alt. 96 | // Otherwise it inserts obj, sets the object's parent scope 97 | // if not already set, and returns nil. 98 | func (s *Scope) Insert(obj Object) Object { 99 | name := obj.Name() 100 | if alt := s.elems[name]; alt != nil { 101 | return alt 102 | } 103 | if s.elems == nil { 104 | s.elems = make(map[string]Object) 105 | } 106 | s.elems[name] = obj 107 | if obj.Parent() == nil { 108 | obj.setParent(s) 109 | } 110 | return nil 111 | } 112 | 113 | // Pos and End describe the scope's source code extent [pos, end). 114 | // The results are guaranteed to be valid only if the type-checked 115 | // AST has complete position information. The extent is undefined 116 | // for Universe and package scopes. 117 | func (s *Scope) Pos() token.Pos { return s.pos } 118 | func (s *Scope) End() token.Pos { return s.end } 119 | 120 | // Contains returns true if pos is within the scope's extent. 121 | // The result is guaranteed to be valid only if the type-checked 122 | // AST has complete position information. 123 | func (s *Scope) Contains(pos token.Pos) bool { 124 | return s.pos <= pos && pos < s.end 125 | } 126 | 127 | // Innermost returns the innermost (child) scope containing 128 | // pos. If pos is not within any scope, the result is nil. 129 | // The result is also nil for the Universe scope. 130 | // The result is guaranteed to be valid only if the type-checked 131 | // AST has complete position information. 132 | func (s *Scope) Innermost(pos token.Pos) *Scope { 133 | // Package scopes do not have extents since they may be 134 | // discontiguous, so iterate over the package's files. 135 | if s.parent == Universe { 136 | for _, s := range s.children { 137 | if inner := s.Innermost(pos); inner != nil { 138 | return inner 139 | } 140 | } 141 | } 142 | 143 | if s.Contains(pos) { 144 | for _, s := range s.children { 145 | if s.Contains(pos) { 146 | return s.Innermost(pos) 147 | } 148 | } 149 | return s 150 | } 151 | return nil 152 | } 153 | 154 | // WriteTo writes a string representation of the scope to w, 155 | // with the scope elements sorted by name. 156 | // The level of indentation is controlled by n >= 0, with 157 | // n == 0 for no indentation. 158 | // If recurse is set, it also writes nested (children) scopes. 159 | func (s *Scope) WriteTo(w io.Writer, n int, recurse bool) { 160 | const ind = ". " 161 | indn := strings.Repeat(ind, n) 162 | 163 | fmt.Fprintf(w, "%s%s scope %p {", indn, s.comment, s) 164 | if len(s.elems) == 0 { 165 | fmt.Fprintf(w, "}\n") 166 | return 167 | } 168 | 169 | fmt.Fprintln(w) 170 | indn1 := indn + ind 171 | for _, name := range s.Names() { 172 | fmt.Fprintf(w, "%s%s\n", indn1, s.elems[name]) 173 | } 174 | 175 | if recurse { 176 | for _, s := range s.children { 177 | fmt.Fprintln(w) 178 | s.WriteTo(w, n+1, recurse) 179 | } 180 | } 181 | 182 | fmt.Fprintf(w, "%s}", indn) 183 | } 184 | 185 | // String returns a string representation of the scope, for debugging. 186 | func (s *Scope) String() string { 187 | var buf bytes.Buffer 188 | s.WriteTo(&buf, 0, false) 189 | return buf.String() 190 | } 191 | -------------------------------------------------------------------------------- /types/sizes.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements Sizes. 6 | 7 | package types 8 | 9 | // Sizes defines the sizing functions for package unsafe. 10 | type Sizes interface { 11 | // Alignof returns the alignment of a variable of type T. 12 | // Alignof must implement the alignment guarantees required by the spec. 13 | Alignof(T Type) int64 14 | 15 | // Offsetsof returns the offsets of the given struct fields, in bytes. 16 | // Offsetsof must implement the offset guarantees required by the spec. 17 | Offsetsof(fields []*Var) []int64 18 | 19 | // Sizeof returns the size of a variable of type T. 20 | // Sizeof must implement the size guarantees required by the spec. 21 | Sizeof(T Type) int64 22 | } 23 | 24 | // StdSizes is a convenience type for creating commonly used Sizes. 25 | // It makes the following simplifying assumptions: 26 | // 27 | // - The size of explicitly sized basic types (int16, etc.) is the 28 | // specified size. 29 | // - The size of strings and interfaces is 2*WordSize. 30 | // - The size of slices is 3*WordSize. 31 | // - The size of an array of n elements corresponds to the size of 32 | // a struct of n consecutive fields of the array's element type. 33 | // - The size of a struct is the offset of the last field plus that 34 | // field's size. As with all element types, if the struct is used 35 | // in an array its size must first be aligned to a multiple of the 36 | // struct's alignment. 37 | // - All other types have size WordSize. 38 | // - Arrays and structs are aligned per spec definition; all other 39 | // types are naturally aligned with a maximum alignment MaxAlign. 40 | // 41 | // *StdSizes implements Sizes. 42 | // 43 | type StdSizes struct { 44 | WordSize int64 // word size in bytes - must be >= 4 (32bits) 45 | MaxAlign int64 // maximum alignment in bytes - must be >= 1 46 | } 47 | 48 | func (s *StdSizes) Alignof(T Type) int64 { 49 | // For arrays and structs, alignment is defined in terms 50 | // of alignment of the elements and fields, respectively. 51 | switch t := T.Underlying().(type) { 52 | case *Array: 53 | // spec: "For a variable x of array type: unsafe.Alignof(x) 54 | // is the same as unsafe.Alignof(x[0]), but at least 1." 55 | return s.Alignof(t.elem) 56 | case *Struct: 57 | // spec: "For a variable x of struct type: unsafe.Alignof(x) 58 | // is the largest of the values unsafe.Alignof(x.f) for each 59 | // field f of x, but at least 1." 60 | max := int64(1) 61 | for _, f := range t.fields { 62 | if a := s.Alignof(f.typ); a > max { 63 | max = a 64 | } 65 | } 66 | return max 67 | } 68 | a := s.Sizeof(T) // may be 0 69 | // spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1." 70 | if a < 1 { 71 | return 1 72 | } 73 | if a > s.MaxAlign { 74 | return s.MaxAlign 75 | } 76 | return a 77 | } 78 | 79 | func (s *StdSizes) Offsetsof(fields []*Var) []int64 { 80 | offsets := make([]int64, len(fields)) 81 | var o int64 82 | for i, f := range fields { 83 | a := s.Alignof(f.typ) 84 | o = align(o, a) 85 | offsets[i] = o 86 | o += s.Sizeof(f.typ) 87 | } 88 | return offsets 89 | } 90 | 91 | var basicSizes = [...]byte{ 92 | Bool: 1, 93 | Int8: 1, 94 | Int16: 2, 95 | Int32: 4, 96 | Int64: 8, 97 | Uint8: 1, 98 | Uint16: 2, 99 | Uint32: 4, 100 | Uint64: 8, 101 | Float32: 4, 102 | Float64: 8, 103 | Complex64: 8, 104 | Complex128: 16, 105 | } 106 | 107 | func (s *StdSizes) Sizeof(T Type) int64 { 108 | switch t := T.Underlying().(type) { 109 | case *Basic: 110 | assert(isTyped(T)) 111 | k := t.kind 112 | if int(k) < len(basicSizes) { 113 | if s := basicSizes[k]; s > 0 { 114 | return int64(s) 115 | } 116 | } 117 | if k == String { 118 | return s.WordSize * 2 119 | } 120 | case *Array: 121 | n := t.len 122 | if n == 0 { 123 | return 0 124 | } 125 | a := s.Alignof(t.elem) 126 | z := s.Sizeof(t.elem) 127 | return align(z, a)*(n-1) + z 128 | case *Slice: 129 | return s.WordSize * 3 130 | case *Struct: 131 | n := t.NumFields() 132 | if n == 0 { 133 | return 0 134 | } 135 | setOffsets(t, s) 136 | return t.offsets[n-1] + s.Sizeof(t.fields[n-1].typ) 137 | case *Interface: 138 | return s.WordSize * 2 139 | } 140 | return s.WordSize // catch-all 141 | } 142 | 143 | // stdSizes is used if Config.Sizes == nil. 144 | var stdSizes = StdSizes{8, 8} 145 | 146 | func (conf *Config) alignof(T Type) int64 { 147 | if s := conf.Sizes; s != nil { 148 | if a := s.Alignof(T); a >= 1 { 149 | return a 150 | } 151 | panic("Config.Sizes.Alignof returned an alignment < 1") 152 | } 153 | return stdSizes.Alignof(T) 154 | } 155 | 156 | func (conf *Config) offsetsof(T *Struct) []int64 { 157 | var offsets []int64 158 | if T.NumFields() > 0 { 159 | // compute offsets on demand 160 | if s := conf.Sizes; s != nil { 161 | calculated := setOffsets(T, s) 162 | offsets = T.offsets 163 | if calculated { 164 | // sanity checks 165 | if len(offsets) != T.NumFields() { 166 | panic("Config.Sizes.Offsetsof returned the wrong number of offsets") 167 | } 168 | for _, o := range offsets { 169 | if o < 0 { 170 | panic("Config.Sizes.Offsetsof returned an offset < 0") 171 | } 172 | } 173 | } 174 | } else { 175 | setOffsets(T, &stdSizes) 176 | offsets = T.offsets 177 | } 178 | } 179 | return offsets 180 | } 181 | 182 | // offsetof returns the offset of the field specified via 183 | // the index sequence relative to typ. All embedded fields 184 | // must be structs (rather than pointer to structs). 185 | func (conf *Config) offsetof(typ Type, index []int) int64 { 186 | var o int64 187 | for _, i := range index { 188 | s := typ.Underlying().(*Struct) 189 | o += conf.offsetsof(s)[i] 190 | typ = s.fields[i].typ 191 | } 192 | return o 193 | } 194 | 195 | func (conf *Config) sizeof(T Type) int64 { 196 | if s := conf.Sizes; s != nil { 197 | if z := s.Sizeof(T); z >= 0 { 198 | return z 199 | } 200 | panic("Config.Sizes.Sizeof returned a size < 0") 201 | } 202 | return stdSizes.Sizeof(T) 203 | } 204 | 205 | // align returns the smallest y >= x such that y % a == 0. 206 | func align(x, a int64) int64 { 207 | y := x + a - 1 208 | return y - y%a 209 | } 210 | 211 | // setOffsets sets the offsets of s for the given sizes if necessary. 212 | // The result is true if the offsets were not set before; otherwise it 213 | // is false. 214 | func setOffsets(s *Struct, sizes Sizes) bool { 215 | var calculated bool 216 | s.offsetsOnce.Do(func() { 217 | calculated = true 218 | s.offsets = sizes.Offsetsof(s.fields) 219 | }) 220 | return calculated 221 | } 222 | -------------------------------------------------------------------------------- /types/universe.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file sets up the universe scope and the unsafe package. 6 | 7 | package types 8 | 9 | import ( 10 | "go/constant" 11 | "go/token" 12 | "strings" 13 | ) 14 | 15 | var ( 16 | Universe *Scope 17 | Unsafe *Package 18 | universeIota *Const 19 | universeByte *Basic // uint8 alias, but has name "byte" 20 | universeRune *Basic // int32 alias, but has name "rune" 21 | ) 22 | 23 | var Typ = []*Basic{ 24 | Invalid: {Invalid, 0, "invalid type"}, 25 | 26 | Bool: {Bool, IsBoolean, "bool"}, 27 | Int: {Int, IsInteger, "int"}, 28 | Int8: {Int8, IsInteger, "int8"}, 29 | Int16: {Int16, IsInteger, "int16"}, 30 | Int32: {Int32, IsInteger, "int32"}, 31 | Int64: {Int64, IsInteger, "int64"}, 32 | Uint: {Uint, IsInteger | IsUnsigned, "uint"}, 33 | Uint8: {Uint8, IsInteger | IsUnsigned, "uint8"}, 34 | Uint16: {Uint16, IsInteger | IsUnsigned, "uint16"}, 35 | Uint32: {Uint32, IsInteger | IsUnsigned, "uint32"}, 36 | Uint64: {Uint64, IsInteger | IsUnsigned, "uint64"}, 37 | Uintptr: {Uintptr, IsInteger | IsUnsigned, "uintptr"}, 38 | Float32: {Float32, IsFloat, "float32"}, 39 | Float64: {Float64, IsFloat, "float64"}, 40 | Complex64: {Complex64, IsComplex, "complex64"}, 41 | Complex128: {Complex128, IsComplex, "complex128"}, 42 | String: {String, IsString, "string"}, 43 | UnsafePointer: {UnsafePointer, 0, "Pointer"}, 44 | 45 | UntypedBool: {UntypedBool, IsBoolean | IsUntyped, "untyped bool"}, 46 | UntypedInt: {UntypedInt, IsInteger | IsUntyped, "untyped int"}, 47 | UntypedRune: {UntypedRune, IsInteger | IsUntyped, "untyped rune"}, 48 | UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, "untyped float"}, 49 | UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, "untyped complex"}, 50 | UntypedString: {UntypedString, IsString | IsUntyped, "untyped string"}, 51 | UntypedNil: {UntypedNil, IsUntyped, "untyped nil"}, 52 | } 53 | 54 | var aliases = [...]*Basic{ 55 | {Byte, IsInteger | IsUnsigned, "byte"}, 56 | {Rune, IsInteger, "rune"}, 57 | } 58 | 59 | func defPredeclaredTypes() { 60 | for _, t := range Typ { 61 | def(NewTypeName(token.NoPos, nil, t.name, t)) 62 | } 63 | for _, t := range aliases { 64 | def(NewTypeName(token.NoPos, nil, t.name, t)) 65 | } 66 | 67 | // Error has a nil package in its qualified name since it is in no package 68 | res := NewVar(token.NoPos, nil, "", Typ[String]) 69 | sig := &Signature{results: NewTuple(res)} 70 | err := NewFunc(token.NoPos, nil, "Error", sig) 71 | typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()} 72 | sig.recv = NewVar(token.NoPos, nil, "", typ) 73 | def(NewTypeName(token.NoPos, nil, "error", typ)) 74 | } 75 | 76 | var predeclaredConsts = [...]struct { 77 | name string 78 | kind BasicKind 79 | val constant.Value 80 | }{ 81 | {"true", UntypedBool, constant.MakeBool(true)}, 82 | {"false", UntypedBool, constant.MakeBool(false)}, 83 | {"iota", UntypedInt, constant.MakeInt64(0)}, 84 | } 85 | 86 | func defPredeclaredConsts() { 87 | for _, c := range predeclaredConsts { 88 | def(NewConst(token.NoPos, nil, c.name, Typ[c.kind], c.val)) 89 | } 90 | } 91 | 92 | func defPredeclaredNil() { 93 | def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}}) 94 | } 95 | 96 | // A builtinId is the id of a builtin function. 97 | type builtinId int 98 | 99 | const ( 100 | // universe scope 101 | _Append builtinId = iota 102 | _Cap 103 | _Close 104 | _Complex 105 | _Copy 106 | _Delete 107 | _Imag 108 | _Len 109 | _Make 110 | _New 111 | _Panic 112 | _Print 113 | _Println 114 | _Real 115 | _Recover 116 | 117 | // package unsafe 118 | _Alignof 119 | _Offsetof 120 | _Sizeof 121 | 122 | // testing support 123 | _Assert 124 | _Trace 125 | ) 126 | 127 | var predeclaredFuncs = [...]struct { 128 | name string 129 | nargs int 130 | variadic bool 131 | kind exprKind 132 | }{ 133 | _Append: {"append", 1, true, expression}, 134 | _Cap: {"cap", 1, false, expression}, 135 | _Close: {"close", 1, false, statement}, 136 | _Complex: {"complex", 2, false, expression}, 137 | _Copy: {"copy", 2, false, statement}, 138 | _Delete: {"delete", 2, false, statement}, 139 | _Imag: {"imag", 1, false, expression}, 140 | _Len: {"len", 1, false, expression}, 141 | _Make: {"make", 1, true, expression}, 142 | _New: {"new", 1, false, expression}, 143 | _Panic: {"panic", 1, false, statement}, 144 | _Print: {"print", 0, true, statement}, 145 | _Println: {"println", 0, true, statement}, 146 | _Real: {"real", 1, false, expression}, 147 | _Recover: {"recover", 0, false, statement}, 148 | 149 | _Alignof: {"Alignof", 1, false, expression}, 150 | _Offsetof: {"Offsetof", 1, false, expression}, 151 | _Sizeof: {"Sizeof", 1, false, expression}, 152 | 153 | _Assert: {"assert", 1, false, statement}, 154 | _Trace: {"trace", 0, true, statement}, 155 | } 156 | 157 | func defPredeclaredFuncs() { 158 | for i := range predeclaredFuncs { 159 | id := builtinId(i) 160 | if id == _Assert || id == _Trace { 161 | continue // only define these in testing environment 162 | } 163 | def(newBuiltin(id)) 164 | } 165 | } 166 | 167 | // DefPredeclaredTestFuncs defines the assert and trace built-ins. 168 | // These built-ins are intended for debugging and testing of this 169 | // package only. 170 | func DefPredeclaredTestFuncs() { 171 | if Universe.Lookup("assert") != nil { 172 | return // already defined 173 | } 174 | def(newBuiltin(_Assert)) 175 | def(newBuiltin(_Trace)) 176 | } 177 | 178 | func init() { 179 | Universe = NewScope(nil, token.NoPos, token.NoPos, "universe") 180 | Unsafe = NewPackage("unsafe", "unsafe") 181 | Unsafe.complete = true 182 | 183 | defPredeclaredTypes() 184 | defPredeclaredConsts() 185 | defPredeclaredNil() 186 | defPredeclaredFuncs() 187 | defPredeclaredPlyFuncs() 188 | 189 | universeIota = Universe.Lookup("iota").(*Const) 190 | universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic) 191 | universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic) 192 | } 193 | 194 | // Objects with names containing blanks are internal and not entered into 195 | // a scope. Objects with exported names are inserted in the unsafe package 196 | // scope; other objects are inserted in the universe scope. 197 | // 198 | func def(obj Object) { 199 | name := obj.Name() 200 | if strings.Contains(name, " ") { 201 | return // nothing to do 202 | } 203 | // fix Obj link for named types 204 | if typ, ok := obj.Type().(*Named); ok { 205 | typ.obj = obj.(*TypeName) 206 | } 207 | // exported identifiers go into package unsafe 208 | scope := Universe 209 | if obj.Exported() { 210 | scope = Unsafe.scope 211 | // set Pkg field 212 | switch obj := obj.(type) { 213 | case *TypeName: 214 | obj.pkg = Unsafe 215 | case *Builtin: 216 | obj.pkg = Unsafe 217 | case *Ply: 218 | obj.pkg = Unsafe 219 | default: 220 | unreachable() 221 | } 222 | } 223 | if scope.Insert(obj) != nil { 224 | panic("internal error: double declaration") 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /types/issues_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This file implements tests for various issues. 6 | 7 | package types_test 8 | 9 | import ( 10 | "fmt" 11 | "go/ast" 12 | "go/importer" 13 | "go/parser" 14 | "internal/testenv" 15 | "sort" 16 | "strings" 17 | "testing" 18 | 19 | . "go/types" 20 | ) 21 | 22 | func TestIssue5770(t *testing.T) { 23 | src := `package p; type S struct{T}` 24 | f, err := parser.ParseFile(fset, "", src, 0) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | 29 | conf := Config{Importer: importer.Default()} 30 | _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash 31 | want := "undeclared name: T" 32 | if err == nil || !strings.Contains(err.Error(), want) { 33 | t.Errorf("got: %v; want: %s", err, want) 34 | } 35 | } 36 | 37 | func TestIssue5849(t *testing.T) { 38 | src := ` 39 | package p 40 | var ( 41 | s uint 42 | _ = uint8(8) 43 | _ = uint16(16) << s 44 | _ = uint32(32 << s) 45 | _ = uint64(64 << s + s) 46 | _ = (interface{})("foo") 47 | _ = (interface{})(nil) 48 | )` 49 | f, err := parser.ParseFile(fset, "", src, 0) 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | 54 | var conf Config 55 | types := make(map[ast.Expr]TypeAndValue) 56 | _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types}) 57 | if err != nil { 58 | t.Fatal(err) 59 | } 60 | 61 | for x, tv := range types { 62 | var want Type 63 | switch x := x.(type) { 64 | case *ast.BasicLit: 65 | switch x.Value { 66 | case `8`: 67 | want = Typ[Uint8] 68 | case `16`: 69 | want = Typ[Uint16] 70 | case `32`: 71 | want = Typ[Uint32] 72 | case `64`: 73 | want = Typ[Uint] // because of "+ s", s is of type uint 74 | case `"foo"`: 75 | want = Typ[String] 76 | } 77 | case *ast.Ident: 78 | if x.Name == "nil" { 79 | want = Typ[UntypedNil] 80 | } 81 | } 82 | if want != nil && !Identical(tv.Type, want) { 83 | t.Errorf("got %s; want %s", tv.Type, want) 84 | } 85 | } 86 | } 87 | 88 | func TestIssue6413(t *testing.T) { 89 | src := ` 90 | package p 91 | func f() int { 92 | defer f() 93 | go f() 94 | return 0 95 | } 96 | ` 97 | f, err := parser.ParseFile(fset, "", src, 0) 98 | if err != nil { 99 | t.Fatal(err) 100 | } 101 | 102 | var conf Config 103 | types := make(map[ast.Expr]TypeAndValue) 104 | _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types}) 105 | if err != nil { 106 | t.Fatal(err) 107 | } 108 | 109 | want := Typ[Int] 110 | n := 0 111 | for x, tv := range types { 112 | if _, ok := x.(*ast.CallExpr); ok { 113 | if tv.Type != want { 114 | t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want) 115 | } 116 | n++ 117 | } 118 | } 119 | 120 | if n != 2 { 121 | t.Errorf("got %d CallExprs; want 2", n) 122 | } 123 | } 124 | 125 | func TestIssue7245(t *testing.T) { 126 | src := ` 127 | package p 128 | func (T) m() (res bool) { return } 129 | type T struct{} // receiver type after method declaration 130 | ` 131 | f, err := parser.ParseFile(fset, "", src, 0) 132 | if err != nil { 133 | t.Fatal(err) 134 | } 135 | 136 | var conf Config 137 | defs := make(map[*ast.Ident]Object) 138 | _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs}) 139 | if err != nil { 140 | t.Fatal(err) 141 | } 142 | 143 | m := f.Decls[0].(*ast.FuncDecl) 144 | res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0) 145 | res2 := defs[m.Type.Results.List[0].Names[0]].(*Var) 146 | 147 | if res1 != res2 { 148 | t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2) 149 | } 150 | } 151 | 152 | // This tests that uses of existing vars on the LHS of an assignment 153 | // are Uses, not Defs; and also that the (illegal) use of a non-var on 154 | // the LHS of an assignment is a Use nonetheless. 155 | func TestIssue7827(t *testing.T) { 156 | const src = ` 157 | package p 158 | func _() { 159 | const w = 1 // defs w 160 | x, y := 2, 3 // defs x, y 161 | w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w 162 | _, _, _ = x, y, z // uses x, y, z 163 | } 164 | ` 165 | const want = `L3 defs func p._() 166 | L4 defs const w untyped int 167 | L5 defs var x int 168 | L5 defs var y int 169 | L6 defs var z int 170 | L6 uses const w untyped int 171 | L6 uses var x int 172 | L7 uses var x int 173 | L7 uses var y int 174 | L7 uses var z int` 175 | 176 | f, err := parser.ParseFile(fset, "", src, 0) 177 | if err != nil { 178 | t.Fatal(err) 179 | } 180 | 181 | // don't abort at the first error 182 | conf := Config{Error: func(err error) { t.Log(err) }} 183 | defs := make(map[*ast.Ident]Object) 184 | uses := make(map[*ast.Ident]Object) 185 | _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses}) 186 | if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") { 187 | t.Errorf("Check: unexpected error: %s", s) 188 | } 189 | 190 | var facts []string 191 | for id, obj := range defs { 192 | if obj != nil { 193 | fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj) 194 | facts = append(facts, fact) 195 | } 196 | } 197 | for id, obj := range uses { 198 | fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj) 199 | facts = append(facts, fact) 200 | } 201 | sort.Strings(facts) 202 | 203 | got := strings.Join(facts, "\n") 204 | if got != want { 205 | t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want) 206 | } 207 | } 208 | 209 | // This tests that the package associated with the types.Object.Pkg method 210 | // is the type's package independent of the order in which the imports are 211 | // listed in the sources src1, src2 below. 212 | // The actual issue is in go/internal/gcimporter which has a corresponding 213 | // test; we leave this test here to verify correct behavior at the go/types 214 | // level. 215 | func TestIssue13898(t *testing.T) { 216 | testenv.MustHaveGoBuild(t) 217 | 218 | const src0 = ` 219 | package main 220 | 221 | import "go/types" 222 | 223 | func main() { 224 | var info types.Info 225 | for _, obj := range info.Uses { 226 | _ = obj.Pkg() 227 | } 228 | } 229 | ` 230 | // like src0, but also imports go/importer 231 | const src1 = ` 232 | package main 233 | 234 | import ( 235 | "go/types" 236 | _ "go/importer" 237 | ) 238 | 239 | func main() { 240 | var info types.Info 241 | for _, obj := range info.Uses { 242 | _ = obj.Pkg() 243 | } 244 | } 245 | ` 246 | // like src1 but with different import order 247 | // (used to fail with this issue) 248 | const src2 = ` 249 | package main 250 | 251 | import ( 252 | _ "go/importer" 253 | "go/types" 254 | ) 255 | 256 | func main() { 257 | var info types.Info 258 | for _, obj := range info.Uses { 259 | _ = obj.Pkg() 260 | } 261 | } 262 | ` 263 | f := func(test, src string) { 264 | f, err := parser.ParseFile(fset, "", src, 0) 265 | if err != nil { 266 | t.Fatal(err) 267 | } 268 | cfg := Config{Importer: importer.Default()} 269 | info := Info{Uses: make(map[*ast.Ident]Object)} 270 | _, err = cfg.Check("main", fset, []*ast.File{f}, &info) 271 | if err != nil { 272 | t.Fatal(err) 273 | } 274 | 275 | var pkg *Package 276 | count := 0 277 | for id, obj := range info.Uses { 278 | if id.Name == "Pkg" { 279 | pkg = obj.Pkg() 280 | count++ 281 | } 282 | } 283 | if count != 1 { 284 | t.Fatalf("%s: got %d entries named Pkg; want 1", test, count) 285 | } 286 | if pkg.Name() != "types" { 287 | t.Fatalf("%s: got %v; want package types", test, pkg) 288 | } 289 | } 290 | 291 | f("src0", src0) 292 | f("src1", src1) 293 | f("src2", src2) 294 | } 295 | --------------------------------------------------------------------------------