whatcanGOwrong
This commit is contained in:
Vendored
+383
@@ -0,0 +1,383 @@
|
||||
# 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:toplevelcontrol
|
||||
if M:
|
||||
load("foo", "bar") ### "load statement within a conditional"
|
||||
|
||||
---
|
||||
# option:toplevelcontrol
|
||||
for x in M:
|
||||
load("foo", "bar") ### "load statement within a loop"
|
||||
|
||||
---
|
||||
# option:toplevelcontrol option:while
|
||||
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:toplevelcontrol
|
||||
|
||||
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:while
|
||||
|
||||
def f():
|
||||
while U: # ok
|
||||
pass
|
||||
|
||||
while U: ### "while loop not within a function"
|
||||
pass
|
||||
|
||||
---
|
||||
# option:toplevelcontrol option:while
|
||||
|
||||
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" is 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
|
||||
Reference in New Issue
Block a user