You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
384 lines
7.6 KiB
384 lines
7.6 KiB
# Tests of resolver errors.
|
|
#
|
|
# The initial environment contains the predeclared names "M"
|
|
# (module-specific) and "U" (universal). This distinction
|
|
# should be unobservable to the Starlark program.
|
|
|
|
# use of declared global
|
|
x = 1
|
|
_ = x
|
|
|
|
---
|
|
# premature use of global is not a static error;
|
|
# see github.com/google/skylark/issues/116.
|
|
_ = x
|
|
x = 1
|
|
|
|
---
|
|
# use of undefined global
|
|
_ = x ### "undefined: x"
|
|
|
|
---
|
|
# redeclaration of global
|
|
x = 1
|
|
x = 2 ### "cannot reassign global x declared at .*resolve.star:23:1"
|
|
|
|
---
|
|
# Redeclaration of predeclared names is allowed.
|
|
#
|
|
# This rule permits tool maintainers to add members to the predeclared
|
|
# environment without breaking existing programs.
|
|
|
|
# module-specific predeclared name
|
|
M = 1 # ok
|
|
M = 2 ### "cannot reassign global M declared at .*/resolve.star"
|
|
|
|
# universal predeclared name
|
|
U = 1 # ok
|
|
U = 1 ### "cannot reassign global U declared at .*/resolve.star"
|
|
|
|
---
|
|
# A global declaration shadows all references to a predeclared;
|
|
# see github.com/google/skylark/issues/116.
|
|
|
|
a = U # ok: U is a reference to the global defined on the next line.
|
|
U = 1
|
|
|
|
---
|
|
# reference to predeclared name
|
|
M()
|
|
|
|
---
|
|
# locals may be referenced before they are defined
|
|
|
|
def f():
|
|
M(x) # dynamic error
|
|
x = 1
|
|
|
|
---
|
|
# Various forms of assignment:
|
|
|
|
def f(x): # parameter
|
|
M(x)
|
|
M(y) ### "undefined: y"
|
|
|
|
(a, b) = 1, 2
|
|
M(a)
|
|
M(b)
|
|
M(c) ### "undefined: c"
|
|
|
|
[p, q] = 1, 2
|
|
M(p)
|
|
M(q)
|
|
M(r) ### "undefined: r"
|
|
|
|
---
|
|
# a comprehension introduces a separate lexical block
|
|
|
|
_ = [x for x in "abc"]
|
|
M(x) ### "undefined: x"
|
|
|
|
---
|
|
# Functions may have forward refs.
|
|
def f():
|
|
g()
|
|
h() ### "undefined: h"
|
|
def inner():
|
|
i()
|
|
i = lambda: 0
|
|
|
|
def g():
|
|
f()
|
|
|
|
---
|
|
# It is not permitted to rebind a global using a += assignment.
|
|
|
|
x = [1]
|
|
x.extend([2]) # ok
|
|
x += [3] ### `cannot reassign global x`
|
|
|
|
def f():
|
|
x += [4] # x is local to f
|
|
|
|
y = 1
|
|
y += 2 ### `cannot reassign global y`
|
|
z += 3 # ok (but fails dynamically because z is undefined)
|
|
|
|
---
|
|
def f(a):
|
|
if 1==1:
|
|
b = 1
|
|
c = 1
|
|
M(a) # ok: param
|
|
M(b) # ok: maybe bound local
|
|
M(c) # ok: bound local
|
|
M(d) # NB: we don't do a use-before-def check on local vars!
|
|
M(e) # ok: global
|
|
M(f) # ok: global
|
|
d = 1
|
|
|
|
e = 1
|
|
|
|
---
|
|
# This program should resolve successfully but fail dynamically.
|
|
x = 1
|
|
|
|
def f():
|
|
M(x) # dynamic error: reference to undefined local
|
|
x = 2
|
|
|
|
f()
|
|
|
|
---
|
|
load("module", "name") # ok
|
|
|
|
def f():
|
|
load("foo", "bar") ### "load statement within a function"
|
|
|
|
load("foo",
|
|
"", ### "load: empty identifier"
|
|
"_a", ### "load: names with leading underscores are not exported: _a"
|
|
b="", ### "load: empty identifier"
|
|
c="_d", ### "load: names with leading underscores are not exported: _d"
|
|
_e="f") # ok
|
|
|
|
---
|
|
# option:globalreassign
|
|
if M:
|
|
load("foo", "bar") ### "load statement within a conditional"
|
|
|
|
---
|
|
# option:globalreassign
|
|
for x in M:
|
|
load("foo", "bar") ### "load statement within a loop"
|
|
|
|
---
|
|
# option:recursion option:globalreassign
|
|
while M:
|
|
load("foo", "bar") ### "load statement within a loop"
|
|
|
|
---
|
|
# return statements must be within a function
|
|
|
|
return ### "return statement not within a function"
|
|
|
|
---
|
|
# if-statements and for-loops at top-level are forbidden
|
|
# (without globalreassign option)
|
|
|
|
for x in "abc": ### "for loop not within a function"
|
|
pass
|
|
|
|
if x: ### "if statement not within a function"
|
|
pass
|
|
|
|
---
|
|
# option:globalreassign
|
|
|
|
for x in "abc": # ok
|
|
pass
|
|
|
|
if x: # ok
|
|
pass
|
|
|
|
---
|
|
# while loops are forbidden (without -recursion option)
|
|
|
|
def f():
|
|
while U: ### "dialect does not support while loops"
|
|
pass
|
|
|
|
---
|
|
# option:recursion
|
|
|
|
def f():
|
|
while U: # ok
|
|
pass
|
|
|
|
while U: ### "while loop not within a function"
|
|
pass
|
|
|
|
---
|
|
# option:globalreassign option:recursion
|
|
|
|
while U: # ok
|
|
pass
|
|
|
|
---
|
|
# The parser allows any expression on the LHS of an assignment.
|
|
|
|
1 = 0 ### "can't assign to literal"
|
|
1+2 = 0 ### "can't assign to binaryexpr"
|
|
f() = 0 ### "can't assign to callexpr"
|
|
|
|
[a, b] = 0
|
|
[c, d] += 0 ### "can't use list expression in augmented assignment"
|
|
(e, f) += 0 ### "can't use tuple expression in augmented assignment"
|
|
|
|
[] = 0 # ok
|
|
() = 0 # ok
|
|
|
|
---
|
|
# break and continue statements must appear within a loop
|
|
|
|
break ### "break not in a loop"
|
|
|
|
continue ### "continue not in a loop"
|
|
|
|
pass
|
|
|
|
---
|
|
# Positional arguments (and required parameters)
|
|
# must appear before named arguments (and optional parameters).
|
|
|
|
M(x=1, 2) ### `positional argument may not follow named`
|
|
|
|
def f(x=1, y): pass ### `required parameter may not follow optional`
|
|
---
|
|
# No parameters may follow **kwargs in a declaration.
|
|
|
|
def f(**kwargs, x): ### `parameter may not follow \*\*kwargs`
|
|
pass
|
|
|
|
def g(**kwargs, *args): ### `\* parameter may not follow \*\*kwargs`
|
|
pass
|
|
|
|
def h(**kwargs1, **kwargs2): ### `multiple \*\* parameters not allowed`
|
|
pass
|
|
|
|
---
|
|
# Only keyword-only params and **kwargs may follow *args in a declaration.
|
|
|
|
def f(*args, x): # ok
|
|
pass
|
|
|
|
def g(*args1, *args2): ### `multiple \* parameters not allowed`
|
|
pass
|
|
|
|
def h(*, ### `bare \* must be followed by keyword-only parameters`
|
|
*): ### `multiple \* parameters not allowed`
|
|
pass
|
|
|
|
def i(*args, *): ### `multiple \* parameters not allowed`
|
|
pass
|
|
|
|
def j(*, ### `bare \* must be followed by keyword-only parameters`
|
|
*args): ### `multiple \* parameters not allowed`
|
|
pass
|
|
|
|
def k(*, **kwargs): ### `bare \* must be followed by keyword-only parameters`
|
|
pass
|
|
|
|
def l(*): ### `bare \* must be followed by keyword-only parameters`
|
|
pass
|
|
|
|
def m(*args, a=1, **kwargs): # ok
|
|
pass
|
|
|
|
def n(*, a=1, **kwargs): # ok
|
|
pass
|
|
|
|
---
|
|
# No arguments may follow **kwargs in a call.
|
|
def f(*args, **kwargs):
|
|
pass
|
|
|
|
f(**{}, 1) ### `argument may not follow \*\*kwargs`
|
|
f(**{}, x=1) ### `argument may not follow \*\*kwargs`
|
|
f(**{}, *[]) ### `\*args may not follow \*\*kwargs`
|
|
f(**{}, **{}) ### `multiple \*\*kwargs not allowed`
|
|
|
|
---
|
|
# Only **kwargs may follow *args in a call.
|
|
def f(*args, **kwargs):
|
|
pass
|
|
|
|
f(*[], 1) ### `positional argument may not follow \*args`
|
|
f(*[], a=1) ### `keyword argument may not follow \*args`
|
|
f(*[], *[]) ### `multiple \*args not allowed`
|
|
f(*[], **{}) # ok
|
|
|
|
---
|
|
# Parameter names must be unique.
|
|
|
|
def f(a, b, a): pass ### "duplicate parameter: a"
|
|
def g(args, b, *args): pass ### "duplicate parameter: args"
|
|
def h(kwargs, a, **kwargs): pass ### "duplicate parameter: kwargs"
|
|
def i(*x, **x): pass ### "duplicate parameter: x"
|
|
|
|
---
|
|
# Floating-point support is now standard.
|
|
a = float("3.141")
|
|
b = 1 / 2
|
|
c = 3.141
|
|
|
|
---
|
|
# option:globalreassign
|
|
# Legacy Bazel (and Python) semantics: def must precede use even for globals.
|
|
|
|
_ = x ### `undefined: x`
|
|
x = 1
|
|
|
|
---
|
|
# option:globalreassign
|
|
# Legacy Bazel (and Python) semantics: reassignment of globals is allowed.
|
|
x = 1
|
|
x = 2 # ok
|
|
|
|
---
|
|
# option:globalreassign
|
|
# Redeclaration of predeclared names is allowed.
|
|
|
|
# module-specific predeclared name
|
|
M = 1 # ok
|
|
M = 2 # ok (legacy)
|
|
|
|
# universal predeclared name
|
|
U = 1 # ok
|
|
U = 1 # ok (legacy)
|
|
|
|
---
|
|
# https://github.com/bazelbuild/starlark/starlark/issues/21
|
|
def f(**kwargs): pass
|
|
f(a=1, a=1) ### `keyword argument a repeated`
|
|
|
|
|
|
---
|
|
# spelling
|
|
|
|
print = U
|
|
|
|
hello = 1
|
|
print(hollo) ### `undefined: hollo \(did you mean hello\?\)`
|
|
|
|
def f(abc):
|
|
print(abd) ### `undefined: abd \(did you mean abc\?\)`
|
|
print(goodbye) ### `undefined: goodbye$`
|
|
|
|
---
|
|
load("module", "x") # ok
|
|
x = 1 ### `cannot reassign local x`
|
|
load("module", "x") ### `cannot reassign top-level x`
|
|
|
|
---
|
|
# option:loadbindsglobally
|
|
load("module", "x") # ok
|
|
x = 1 ### `cannot reassign global x`
|
|
load("module", "x") ### `cannot reassign global x`
|
|
|
|
---
|
|
# option:globalreassign
|
|
load("module", "x") # ok
|
|
x = 1 # ok
|
|
load("module", "x") # ok
|
|
|
|
---
|
|
# option:globalreassign option:loadbindsglobally
|
|
load("module", "x") # ok
|
|
x = 1
|
|
load("module", "x") # ok
|
|
|
|
---
|
|
_ = x # forward ref to file-local
|
|
load("module", "x") # ok
|