mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-11 22:08:54 +00:00
open new scope for const values (#24084)
fixes #5395 Previously values of `const` statements used the same scope as the `const` statement itself, meaning variables could be declared inside them and referred to in other statements in the same block. Now each `const` value opens its own scope, so any variable declared in the value of a constant can only be accessed for that constant. We could change this to open a new scope for the `const` *section* rather than each constant, so the variables can be used in other constants, but I'm not sure if this is sound.
This commit is contained in:
10
changelog.md
10
changelog.md
@@ -41,6 +41,16 @@
|
||||
bar[int]() # before: (1.0, "abc"), now: type mismatch, missing generic parameter
|
||||
```
|
||||
|
||||
- `const` values now open a new scope for each constant, meaning symbols
|
||||
declared in them can no longer be used outside or in the value of
|
||||
other constants.
|
||||
|
||||
```nim
|
||||
const foo = (var a = 1; a)
|
||||
const bar = a # error
|
||||
let baz = a # error
|
||||
```
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Changes:"
|
||||
|
||||
@@ -985,6 +985,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
var typFlags: TTypeAllowedFlags = {}
|
||||
|
||||
# don't evaluate here since the type compatibility check below may add a converter
|
||||
openScope(c)
|
||||
var def = semExprWithType(c, a[^1], {efTypeAllowed}, typ)
|
||||
|
||||
if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
|
||||
@@ -1011,6 +1012,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
if c.matchedConcept != nil:
|
||||
typFlags.incl taConcept
|
||||
typeAllowedCheck(c, a.info, typ, skConst, typFlags)
|
||||
closeScope(c)
|
||||
|
||||
if a.kind == nkVarTuple:
|
||||
# generate new section from tuple unpacking and embed it into this one
|
||||
|
||||
@@ -3220,6 +3220,15 @@ A const section declares constants whose values are constant expressions:
|
||||
|
||||
Once declared, a constant's symbol can be used as a constant expression.
|
||||
|
||||
The value part of a constant declaration opens a new scope for each constant,
|
||||
so no symbols declared in the constant value are accessible outside of it.
|
||||
|
||||
```nim
|
||||
const foo = (var a = 1; a)
|
||||
const bar = a # error
|
||||
let baz = a # error
|
||||
```
|
||||
|
||||
See [Constants and Constant Expressions] for details.
|
||||
|
||||
Static statement/expression
|
||||
|
||||
5
tests/vm/tconstscope1.nim
Normal file
5
tests/vm/tconstscope1.nim
Normal file
@@ -0,0 +1,5 @@
|
||||
# issue #5395
|
||||
|
||||
const a = (var b = 3; b)
|
||||
echo b #[tt.Error
|
||||
^ undeclared identifier: 'b']#
|
||||
5
tests/vm/tconstscope2.nim
Normal file
5
tests/vm/tconstscope2.nim
Normal file
@@ -0,0 +1,5 @@
|
||||
const
|
||||
a = (var x = 3; x)
|
||||
# should we allow this?
|
||||
b = x #[tt.Error
|
||||
^ undeclared identifier: 'x']#
|
||||
Reference in New Issue
Block a user