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