...
Source file
src/go/types/version.go
1
2
3
4
5 package types
6
7 import (
8 "fmt"
9 "go/ast"
10 "go/token"
11 "go/version"
12 "internal/goversion"
13 "strings"
14 )
15
16
17
18
19 type goVersion string
20
21
22
23 func asGoVersion(v string) goVersion {
24 return goVersion(version.Lang(v))
25 }
26
27
28 func (v goVersion) isValid() bool {
29 return v != ""
30 }
31
32
33
34 func (x goVersion) cmp(y goVersion) int {
35 return version.Compare(string(x), string(y))
36 }
37
38 var (
39
40 go1_9 = asGoVersion("go1.9")
41 go1_13 = asGoVersion("go1.13")
42 go1_14 = asGoVersion("go1.14")
43 go1_17 = asGoVersion("go1.17")
44 go1_18 = asGoVersion("go1.18")
45 go1_20 = asGoVersion("go1.20")
46 go1_21 = asGoVersion("go1.21")
47 go1_22 = asGoVersion("go1.22")
48
49
50 go_current = asGoVersion(fmt.Sprintf("go1.%d", goversion.Version))
51 )
52
53
54
55 func (check *Checker) langCompat(lit *ast.BasicLit) {
56 s := lit.Value
57 if len(s) <= 2 || check.allowVersion(check.pkg, lit, go1_13) {
58 return
59 }
60
61 if strings.Contains(s, "_") {
62 check.versionErrorf(lit, go1_13, "underscores in numeric literals")
63 return
64 }
65 if s[0] != '0' {
66 return
67 }
68 radix := s[1]
69 if radix == 'b' || radix == 'B' {
70 check.versionErrorf(lit, go1_13, "binary literals")
71 return
72 }
73 if radix == 'o' || radix == 'O' {
74 check.versionErrorf(lit, go1_13, "0o/0O-style octal literals")
75 return
76 }
77 if lit.Kind != token.INT && (radix == 'x' || radix == 'X') {
78 check.versionErrorf(lit, go1_13, "hexadecimal floating-point literals")
79 }
80 }
81
82
83 func (check *Checker) allowVersion(pkg *Package, at positioner, v goVersion) bool {
84
85
86 if pkg != check.pkg {
87 return true
88 }
89
90
91
92 var fileVersion goVersion
93 if pos := at.Pos(); pos.IsValid() {
94
95
96
97 fileVersion = asGoVersion(check.versions[check.fileFor(pos)])
98 }
99 return !fileVersion.isValid() || fileVersion.cmp(v) >= 0
100 }
101
102
103
104
105 func (check *Checker) verifyVersionf(at positioner, v goVersion, format string, args ...interface{}) bool {
106 if !check.allowVersion(check.pkg, at, v) {
107 check.versionErrorf(at, v, format, args...)
108 return false
109 }
110 return true
111 }
112
113
114
115
116
117
118
119
120 func (check *Checker) fileFor(pos token.Pos) *ast.File {
121 assert(pos.IsValid())
122
123 if len(check.files) == 0 {
124 return nil
125 }
126 for _, file := range check.files {
127 if file.FileStart <= pos && pos < file.FileEnd {
128 return file
129 }
130 }
131 panic(check.sprintf("file not found for pos = %d (%s)", int(pos), check.fset.Position(pos)))
132 }
133
View as plain text