]> Cypherpunks.ru repositories - gostls13.git/blob - src/go/types/issues_test.go
[dev.ssa] Merge remote-tracking branch 'origin/master' into dev.ssa
[gostls13.git] / src / go / 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         "sort"
15         "strings"
16         "testing"
17
18         . "go/types"
19 )
20
21 func TestIssue5770(t *testing.T) {
22         src := `package p; type S struct{T}`
23         f, err := parser.ParseFile(fset, "", src, 0)
24         if err != nil {
25                 t.Fatal(err)
26         }
27
28         conf := Config{Importer: importer.Default()}
29         _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, nil) // do not crash
30         want := "undeclared name: T"
31         if err == nil || !strings.Contains(err.Error(), want) {
32                 t.Errorf("got: %v; want: %s", err, want)
33         }
34 }
35
36 func TestIssue5849(t *testing.T) {
37         src := `
38 package p
39 var (
40         s uint
41         _ = uint8(8)
42         _ = uint16(16) << s
43         _ = uint32(32 << s)
44         _ = uint64(64 << s + s)
45         _ = (interface{})("foo")
46         _ = (interface{})(nil)
47 )`
48         f, err := parser.ParseFile(fset, "", src, 0)
49         if err != nil {
50                 t.Fatal(err)
51         }
52
53         var conf Config
54         types := make(map[ast.Expr]TypeAndValue)
55         _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
56         if err != nil {
57                 t.Fatal(err)
58         }
59
60         for x, tv := range types {
61                 var want Type
62                 switch x := x.(type) {
63                 case *ast.BasicLit:
64                         switch x.Value {
65                         case `8`:
66                                 want = Typ[Uint8]
67                         case `16`:
68                                 want = Typ[Uint16]
69                         case `32`:
70                                 want = Typ[Uint32]
71                         case `64`:
72                                 want = Typ[Uint] // because of "+ s", s is of type uint
73                         case `"foo"`:
74                                 want = Typ[String]
75                         }
76                 case *ast.Ident:
77                         if x.Name == "nil" {
78                                 want = Typ[UntypedNil]
79                         }
80                 }
81                 if want != nil && !Identical(tv.Type, want) {
82                         t.Errorf("got %s; want %s", tv.Type, want)
83                 }
84         }
85 }
86
87 func TestIssue6413(t *testing.T) {
88         src := `
89 package p
90 func f() int {
91         defer f()
92         go f()
93         return 0
94 }
95 `
96         f, err := parser.ParseFile(fset, "", src, 0)
97         if err != nil {
98                 t.Fatal(err)
99         }
100
101         var conf Config
102         types := make(map[ast.Expr]TypeAndValue)
103         _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Types: types})
104         if err != nil {
105                 t.Fatal(err)
106         }
107
108         want := Typ[Int]
109         n := 0
110         for x, tv := range types {
111                 if _, ok := x.(*ast.CallExpr); ok {
112                         if tv.Type != want {
113                                 t.Errorf("%s: got %s; want %s", fset.Position(x.Pos()), tv.Type, want)
114                         }
115                         n++
116                 }
117         }
118
119         if n != 2 {
120                 t.Errorf("got %d CallExprs; want 2", n)
121         }
122 }
123
124 func TestIssue7245(t *testing.T) {
125         src := `
126 package p
127 func (T) m() (res bool) { return }
128 type T struct{} // receiver type after method declaration
129 `
130         f, err := parser.ParseFile(fset, "", src, 0)
131         if err != nil {
132                 t.Fatal(err)
133         }
134
135         var conf Config
136         defs := make(map[*ast.Ident]Object)
137         _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs})
138         if err != nil {
139                 t.Fatal(err)
140         }
141
142         m := f.Decls[0].(*ast.FuncDecl)
143         res1 := defs[m.Name].(*Func).Type().(*Signature).Results().At(0)
144         res2 := defs[m.Type.Results.List[0].Names[0]].(*Var)
145
146         if res1 != res2 {
147                 t.Errorf("got %s (%p) != %s (%p)", res1, res2, res1, res2)
148         }
149 }
150
151 // This tests that uses of existing vars on the LHS of an assignment
152 // are Uses, not Defs; and also that the (illegal) use of a non-var on
153 // the LHS of an assignment is a Use nonetheless.
154 func TestIssue7827(t *testing.T) {
155         const src = `
156 package p
157 func _() {
158         const w = 1        // defs w
159         x, y := 2, 3       // defs x, y
160         w, x, z := 4, 5, 6 // uses w, x, defs z; error: cannot assign to w
161         _, _, _ = x, y, z  // uses x, y, z
162 }
163 `
164         const want = `L3 defs func p._()
165 L4 defs const w untyped int
166 L5 defs var x int
167 L5 defs var y int
168 L6 defs var z int
169 L6 uses const w untyped int
170 L6 uses var x int
171 L7 uses var x int
172 L7 uses var y int
173 L7 uses var z int`
174
175         f, err := parser.ParseFile(fset, "", src, 0)
176         if err != nil {
177                 t.Fatal(err)
178         }
179
180         // don't abort at the first error
181         conf := Config{Error: func(err error) { t.Log(err) }}
182         defs := make(map[*ast.Ident]Object)
183         uses := make(map[*ast.Ident]Object)
184         _, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &Info{Defs: defs, Uses: uses})
185         if s := fmt.Sprint(err); !strings.HasSuffix(s, "cannot assign to w") {
186                 t.Errorf("Check: unexpected error: %s", s)
187         }
188
189         var facts []string
190         for id, obj := range defs {
191                 if obj != nil {
192                         fact := fmt.Sprintf("L%d defs %s", fset.Position(id.Pos()).Line, obj)
193                         facts = append(facts, fact)
194                 }
195         }
196         for id, obj := range uses {
197                 fact := fmt.Sprintf("L%d uses %s", fset.Position(id.Pos()).Line, obj)
198                 facts = append(facts, fact)
199         }
200         sort.Strings(facts)
201
202         got := strings.Join(facts, "\n")
203         if got != want {
204                 t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
205         }
206 }