const lowering: respect scope, prohibit non-const `const` assignment
Modifies the handling of the 3-argument "lowered const" so `const x = y`
participates in scope resolution again (#56613); we treat (const x y) as an
assignment form, producing the "unsupported `const` declaration on local
variable" error if the usual scope rules would not make x global.
At the top level, these should succeed:
const x = 1
begin
const x = 1
end
let
const global x = 1
end
Each of the following should fail:
# ERROR: syntax: unsupported `const` declaration on local variable around REPL[1]:2
let
const x = 1
end
# ERROR: syntax: unsupported `const` declaration on local variable around REPL[1]:2
function f()
const x = 1
end
This also amkes the use of `const global` inside a function body produce the
original, specific error message rather than a generic "World age increment not
at top level" error (#57334):
# ERROR: syntax: `global const` declaration not allowed inside function around REPL[1]:2
function f()
global const x = 1
end
Issue #57334 revealed we silently accept `const` expressions writing to
variables. These now fail with a new error message:
a = [1, 2]
# ERROR: syntax: cannot declare "a[1]" `const` around REPL[1]:2
const a[1] = 3
The bulk of these changes track const-ness through the functions called by
expand-assignment, since each of the three types of LHS is affect differently:
- ordinary variables become `const`, producing error if not global
- `X{T} = ...` forces X to be `const`, rather than the defaulting to being
implicitly const only if in global scope.
- `f() = ...` ignores `const`.