• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Tests of resolver errors.
2#
3# The initial environment contains the predeclared names "M"
4# (module-specific) and "U" (universal). This distinction
5# should be unobservable to the Starlark program.
6
7# use of declared global
8x = 1
9_ = x
10
11---
12# premature use of global is not a static error;
13# see github.com/google/skylark/issues/116.
14_ = x
15x = 1
16
17---
18# use of undefined global
19_ = x ### "undefined: x"
20
21---
22# redeclaration of global
23x = 1
24x = 2 ### "cannot reassign global x declared at .*resolve.star:23:1"
25
26---
27# Redeclaration of predeclared names is allowed.
28#
29# This rule permits tool maintainers to add members to the predeclared
30# environment without breaking existing programs.
31
32# module-specific predeclared name
33M = 1 # ok
34M = 2 ### "cannot reassign global M declared at .*/resolve.star"
35
36# universal predeclared name
37U = 1 # ok
38U = 1 ### "cannot reassign global U declared at .*/resolve.star"
39
40---
41# A global declaration shadows all references to a predeclared;
42# see github.com/google/skylark/issues/116.
43
44a = U # ok: U is a reference to the global defined on the next line.
45U = 1
46
47---
48# reference to predeclared name
49M()
50
51---
52# locals may be referenced before they are defined
53
54def f():
55   M(x) # dynamic error
56   x = 1
57
58---
59# Various forms of assignment:
60
61def f(x): # parameter
62    M(x)
63    M(y) ### "undefined: y"
64
65(a, b) = 1, 2
66M(a)
67M(b)
68M(c) ### "undefined: c"
69
70[p, q] = 1, 2
71M(p)
72M(q)
73M(r) ### "undefined: r"
74
75---
76# a comprehension introduces a separate lexical block
77
78_ = [x for x in "abc"]
79M(x) ### "undefined: x"
80
81---
82# Functions may have forward refs.
83def f():
84   g()
85   h() ### "undefined: h"
86   def inner():
87     i()
88     i = lambda: 0
89
90def g():
91  f()
92
93---
94# It is not permitted to rebind a global using a += assignment.
95
96x = [1]
97x.extend([2]) # ok
98x += [3] ### `cannot reassign global x`
99
100def f():
101   x += [4] # x is local to f
102
103y = 1
104y += 2 ### `cannot reassign global y`
105z += 3 # ok (but fails dynamically because z is undefined)
106
107---
108def f(a):
109  if 1==1:
110    b = 1
111  c = 1
112  M(a) # ok: param
113  M(b) # ok: maybe bound local
114  M(c) # ok: bound local
115  M(d) # NB: we don't do a use-before-def check on local vars!
116  M(e) # ok: global
117  M(f) # ok: global
118  d = 1
119
120e = 1
121
122---
123# This program should resolve successfully but fail dynamically.
124x = 1
125
126def f():
127  M(x) # dynamic error: reference to undefined local
128  x = 2
129
130f()
131
132---
133load("module", "name") # ok
134
135def f():
136  load("foo", "bar") ### "load statement within a function"
137
138load("foo",
139     "",     ### "load: empty identifier"
140     "_a",   ### "load: names with leading underscores are not exported: _a"
141     b="",   ### "load: empty identifier"
142     c="_d", ### "load: names with leading underscores are not exported: _d"
143     _e="f") # ok
144
145---
146# option:globalreassign
147if M:
148    load("foo", "bar") ### "load statement within a conditional"
149
150---
151# option:globalreassign
152for x in M:
153    load("foo", "bar") ### "load statement within a loop"
154
155---
156# option:recursion option:globalreassign
157while M:
158    load("foo", "bar") ### "load statement within a loop"
159
160---
161# return statements must be within a function
162
163return ### "return statement not within a function"
164
165---
166# if-statements and for-loops at top-level are forbidden
167# (without globalreassign option)
168
169for x in "abc": ### "for loop not within a function"
170  pass
171
172if x: ### "if statement not within a function"
173  pass
174
175---
176# option:globalreassign
177
178for x in "abc": # ok
179  pass
180
181if x: # ok
182  pass
183
184---
185# while loops are forbidden (without -recursion option)
186
187def f():
188  while U: ### "dialect does not support while loops"
189    pass
190
191---
192# option:recursion
193
194def f():
195  while U: # ok
196    pass
197
198while U: ### "while loop not within a function"
199  pass
200
201---
202# option:globalreassign option:recursion
203
204while U: # ok
205  pass
206
207---
208# The parser allows any expression on the LHS of an assignment.
209
2101 = 0 ### "can't assign to literal"
2111+2 = 0 ### "can't assign to binaryexpr"
212f() = 0 ### "can't assign to callexpr"
213
214[a, b] = 0
215[c, d] += 0 ### "can't use list expression in augmented assignment"
216(e, f) += 0 ### "can't use tuple expression in augmented assignment"
217
218[] = 0 # ok
219() = 0 # ok
220
221---
222# break and continue statements must appear within a loop
223
224break ### "break not in a loop"
225
226continue ### "continue not in a loop"
227
228pass
229
230---
231# Positional arguments (and required parameters)
232# must appear before named arguments (and optional parameters).
233
234M(x=1, 2) ### `positional argument may not follow named`
235
236def f(x=1, y): pass ### `required parameter may not follow optional`
237---
238# No parameters may follow **kwargs in a declaration.
239
240def f(**kwargs, x): ### `parameter may not follow \*\*kwargs`
241  pass
242
243def g(**kwargs, *args): ### `\* parameter may not follow \*\*kwargs`
244  pass
245
246def h(**kwargs1, **kwargs2): ### `multiple \*\* parameters not allowed`
247  pass
248
249---
250# Only keyword-only params and **kwargs may follow *args in a declaration.
251
252def f(*args, x): # ok
253  pass
254
255def g(*args1, *args2): ### `multiple \* parameters not allowed`
256  pass
257
258def h(*, ### `bare \* must be followed by keyword-only parameters`
259      *): ### `multiple \* parameters not allowed`
260  pass
261
262def i(*args, *): ### `multiple \* parameters not allowed`
263  pass
264
265def j(*,      ### `bare \* must be followed by keyword-only parameters`
266      *args): ### `multiple \* parameters not allowed`
267  pass
268
269def k(*, **kwargs): ### `bare \* must be followed by keyword-only parameters`
270  pass
271
272def l(*): ### `bare \* must be followed by keyword-only parameters`
273  pass
274
275def m(*args, a=1, **kwargs): # ok
276  pass
277
278def n(*, a=1, **kwargs): # ok
279  pass
280
281---
282# No arguments may follow **kwargs in a call.
283def f(*args, **kwargs):
284  pass
285
286f(**{}, 1) ### `argument may not follow \*\*kwargs`
287f(**{}, x=1) ### `argument may not follow \*\*kwargs`
288f(**{}, *[]) ### `\*args may not follow \*\*kwargs`
289f(**{}, **{}) ### `multiple \*\*kwargs not allowed`
290
291---
292# Only **kwargs may follow *args in a call.
293def f(*args, **kwargs):
294  pass
295
296f(*[], 1) ### `positional argument may not follow \*args`
297f(*[], a=1) ### `keyword argument may not follow \*args`
298f(*[], *[]) ### `multiple \*args not allowed`
299f(*[], **{}) # ok
300
301---
302# Parameter names must be unique.
303
304def f(a, b, a): pass ### "duplicate parameter: a"
305def g(args, b, *args): pass ### "duplicate parameter: args"
306def h(kwargs, a, **kwargs): pass ### "duplicate parameter: kwargs"
307def i(*x, **x): pass ### "duplicate parameter: x"
308
309---
310# Floating-point support is now standard.
311a = float("3.141")
312b = 1 / 2
313c = 3.141
314
315---
316# option:globalreassign
317# Legacy Bazel (and Python) semantics: def must precede use even for globals.
318
319_ = x ### `undefined: x`
320x = 1
321
322---
323# option:globalreassign
324# Legacy Bazel (and Python) semantics: reassignment of globals is allowed.
325x = 1
326x = 2 # ok
327
328---
329# option:globalreassign
330# Redeclaration of predeclared names is allowed.
331
332# module-specific predeclared name
333M = 1 # ok
334M = 2 # ok (legacy)
335
336# universal predeclared name
337U = 1 # ok
338U = 1 # ok (legacy)
339
340---
341# https://github.com/bazelbuild/starlark/starlark/issues/21
342def f(**kwargs): pass
343f(a=1, a=1) ### `keyword argument a repeated`
344
345
346---
347# spelling
348
349print = U
350
351hello = 1
352print(hollo) ### `undefined: hollo \(did you mean hello\?\)`
353
354def f(abc):
355   print(abd) ### `undefined: abd \(did you mean abc\?\)`
356   print(goodbye) ### `undefined: goodbye$`
357
358---
359load("module", "x") # ok
360x = 1 ### `cannot reassign local x`
361load("module", "x") ### `cannot reassign top-level x`
362
363---
364# option:loadbindsglobally
365load("module", "x") # ok
366x = 1 ### `cannot reassign global x`
367load("module", "x") ### `cannot reassign global x`
368
369---
370# option:globalreassign
371load("module", "x") # ok
372x = 1 # ok
373load("module", "x") # ok
374
375---
376# option:globalreassign option:loadbindsglobally
377load("module", "x") # ok
378x = 1
379load("module", "x") # ok
380
381---
382_ = x # forward ref to file-local
383load("module", "x") # ok
384