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