Skip to content

Commit 76763f5

Browse files
authored
implemented strictCaseObjects (#20608)
* implemented strictCaseObjects * changelog update
1 parent 4aa67ad commit 76763f5

File tree

6 files changed

+80
-8
lines changed

6 files changed

+80
-8
lines changed

changelog.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# v1.8.x - yyyy-mm-dd
1+
# v2.0.0 - yyyy-mm-dd
22

33

44
## Changes affecting backward compatibility
5-
- `httpclient.contentLength` default to `-1` if the Content-Length header is not set in the response, it followed Apache HttpClient(Java), http(go) and .Net HttpWebResponse(C#) behavior. Previously raise `ValueError`.
5+
- `httpclient.contentLength` default to `-1` if the Content-Length header is not set in the response, it followed Apache HttpClient(Java), http(go) and .Net HttpWebResponse(C#) behavior. Previously it raised `ValueError`.
66

77
- `addr` is now available for all addressable locations,
88
`unsafeAddr` is now deprecated and an alias for `addr`.
@@ -216,6 +216,10 @@
216216
need to convert to `string`. On the JS backend, this is translated directly
217217
to a `switch` statement.
218218

219+
- Nim now supports `out` parameters and ["strict definitions"](https://nim-lang.github.io/Nim/manual_experimental.html#strict-definitions-and-nimout-parameters).
220+
- Nim now offers a [strict mode](https://nim-lang.github.io/Nim/manual_experimental.html#strict-case-objects) for `case objects`.
221+
222+
219223
## Compiler changes
220224

221225
- The `gc` switch has been renamed to `mm` ("memory management") in order to reflect the

compiler/guards.nim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,8 +1054,12 @@ proc buildProperFieldCheck(access, check: PNode; o: Operators): PNode =
10541054
assert check.getMagic == mNot
10551055
result = buildProperFieldCheck(access, check[1], o).neg(o)
10561056

1057-
proc checkFieldAccess*(m: TModel, n: PNode; conf: ConfigRef) =
1057+
proc checkFieldAccess*(m: TModel, n: PNode; conf: ConfigRef; produceError: bool) =
10581058
for i in 1..<n.len:
10591059
let check = buildProperFieldCheck(n[0], n[i], m.g.operators)
10601060
if check != nil and m.doesImply(check) != impYes:
1061-
message(conf, n.info, warnProveField, renderTree(n[0])); break
1061+
if produceError:
1062+
localError(conf, n.info, "field access outside of valid case branch: " & renderTree(n[0]))
1063+
else:
1064+
message(conf, n.info, warnProveField, renderTree(n[0]))
1065+
break

compiler/options.nim

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@ type
217217
strictEffects,
218218
unicodeOperators, # deadcode
219219
flexibleOptionalParams,
220-
strictDefs
220+
strictDefs,
221+
strictCaseObjects
221222

222223
LegacyFeature* = enum
223224
allowSemcheckedAstModification,

compiler/sempass2.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ proc trackCase(tracked: PEffects, n: PNode) =
665665
let stringCase = n[0].typ != nil and skipTypes(n[0].typ,
666666
abstractVarRange-{tyTypeDesc}).kind in {tyFloat..tyFloat128, tyString, tyCstring}
667667
let interesting = not stringCase and interestingCaseExpr(n[0]) and
668-
tracked.config.hasWarn(warnProveField)
668+
(tracked.config.hasWarn(warnProveField) or strictCaseObjects in tracked.c.features)
669669
var inter: TIntersection = @[]
670670
var toCover = 0
671671
for i in 1..<n.len:
@@ -1049,8 +1049,8 @@ proc track(tracked: PEffects, n: PNode) =
10491049
for i in 0..<n.len: track(tracked, n[i])
10501050
of nkCheckedFieldExpr:
10511051
track(tracked, n[0])
1052-
if tracked.config.hasWarn(warnProveField):
1053-
checkFieldAccess(tracked.guards, n, tracked.config)
1052+
if tracked.config.hasWarn(warnProveField) or strictCaseObjects in tracked.c.features:
1053+
checkFieldAccess(tracked.guards, n, tracked.config, strictCaseObjects in tracked.c.features)
10541054
of nkTryStmt: trackTryStmt(tracked, n)
10551055
of nkPragma: trackPragmaStmt(tracked, n)
10561056
of nkAsgn, nkFastAsgn, nkSinkAsgn:

doc/manual_experimental.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1941,3 +1941,39 @@ constructors that take inheritance into account.
19411941

19421942
**Note**: The implementation of "strict definitions" and "out parameters" is experimental but the concept
19431943
is solid and it is expected that eventually this mode becomes the default in later versions.
1944+
1945+
1946+
Strict case objects
1947+
===================
1948+
1949+
With `experimental: "strictCaseObjects"` *every* field access is checked to be valid at compile-time.
1950+
The field is within a `case` section of an `object`.
1951+
1952+
```nim
1953+
{.experimental: "strictCaseObjects".}
1954+
1955+
type
1956+
Foo = object
1957+
case b: bool
1958+
of false:
1959+
s: string
1960+
of true:
1961+
x: int
1962+
1963+
var x = Foo(b: true, x: 4)
1964+
case x.b
1965+
of true:
1966+
echo x.x # valid
1967+
of false:
1968+
echo "no"
1969+
1970+
case x.b
1971+
of false:
1972+
echo x.x # error: field access outside of valid case branch: x.x
1973+
of true:
1974+
echo "no"
1975+
1976+
```
1977+
1978+
**Note**: The implementation of "strict case objects" is experimental but the concept
1979+
is solid and it is expected that eventually this mode becomes the default in later versions.

tests/effects/tstrict_caseobjects.nim

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
discard """
2+
errormsg: "field access outside of valid case branch: x.x"
3+
line: 25
4+
"""
5+
6+
{.experimental: "strictCaseObjects".}
7+
8+
type
9+
Foo = object
10+
case b: bool
11+
of false:
12+
s: string
13+
of true:
14+
x: int
15+
16+
var x = Foo(b: true, x: 4)
17+
case x.b
18+
of true:
19+
echo x.x
20+
of false:
21+
echo "no"
22+
23+
case x.b
24+
of false:
25+
echo x.x
26+
of true:
27+
echo "no"

0 commit comments

Comments
 (0)