summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-06-12 07:22:50 +0300
committerGitHub <noreply@github.com>2023-06-12 06:22:50 +0200
commite0ad71a912361d994b1d7b052d0153f7f5528a63 (patch)
treea9db339caee4998910e53fa72a1cd1b8e96b1fe6
parent7b1c448744f9b29a41d205f102fb2b4e7f735d88 (diff)
downloadNim-e0ad71a912361d994b1d7b052d0153f7f5528a63.tar.gz
make binary `not` not parse complex expressions on right side (#22078)
* binary `not` only parses simple expressions

fixes #16324

* switch to primary
-rw-r--r--compiler/parser.nim8
-rw-r--r--doc/grammar.txt6
-rw-r--r--tests/notnil/tparse.nim18
3 files changed, 25 insertions, 7 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 734474dbf..1b8fd70a6 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -1396,7 +1396,7 @@ proc binaryNot(p: var Parser; a: PNode): PNode =
     let notOpr = newIdentNodeP(p.tok.ident, p)
     getTok(p)
     optInd(p, notOpr)
-    let b = parseExpr(p)
+    let b = primary(p, pmTypeDesc)
     result = newNodeP(nkInfix, p)
     result.add notOpr
     result.add a
@@ -1407,8 +1407,8 @@ proc binaryNot(p: var Parser; a: PNode): PNode =
 proc parseTypeDesc(p: var Parser, fullExpr = false): PNode =
   #| rawTypeDesc = (tupleType | routineType | 'enum' | 'object' |
   #|                 ('var' | 'out' | 'ref' | 'ptr' | 'distinct') typeDesc?)
-  #|                 ('not' expr)?
-  #| typeDescExpr = (routineType / simpleExpr) ('not' expr)?
+  #|                 ('not' primary)?
+  #| typeDescExpr = (routineType / simpleExpr) ('not' primary)?
   #| typeDesc = rawTypeDesc / typeDescExpr
   newlineWasSplitting(p)
   if fullExpr:
@@ -1445,7 +1445,7 @@ proc parseTypeDefValue(p: var Parser): PNode =
   #| typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
   #|                  ('ref' | 'ptr' | 'distinct') (tupleDecl | objectDecl))
   #|                / (simpleExpr (exprEqExpr ^+ comma postExprBlocks?)?))
-  #|                ('not' expr)?
+  #|                ('not' primary)?
   case p.tok.tokType
   of tkTuple: result = parseTuple(p, true)
   of tkRef: result = parseTypeDescKAux(p, nkRefTy, pmTypeDef)
diff --git a/doc/grammar.txt b/doc/grammar.txt
index e498dd2b2..458eeb54a 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -104,13 +104,13 @@ primary = simplePrimary (commandStart expr (doBlock extraPostExprBlock*)?)?
         / prefixOperator primary
 rawTypeDesc = (tupleType | routineType | 'enum' | 'object' |
                 ('var' | 'out' | 'ref' | 'ptr' | 'distinct') typeDesc?)
-                ('not' expr)?
-typeDescExpr = (routineType / simpleExpr) ('not' expr)?
+                ('not' primary)?
+typeDescExpr = (routineType / simpleExpr) ('not' primary)?
 typeDesc = rawTypeDesc / typeDescExpr
 typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
                  ('ref' | 'ptr' | 'distinct') (tupleDecl | objectDecl))
                / (simpleExpr (exprEqExpr ^+ comma postExprBlocks?)?))
-               ('not' expr)?
+               ('not' primary)?
 extraPostExprBlock = ( IND{=} doBlock
                      | IND{=} 'of' exprList ':' stmt
                      | IND{=} 'elif' expr ':' stmt
diff --git a/tests/notnil/tparse.nim b/tests/notnil/tparse.nim
new file mode 100644
index 000000000..5c938ff04
--- /dev/null
+++ b/tests/notnil/tparse.nim
@@ -0,0 +1,18 @@
+# issue #16324
+
+{.push experimental: "notnil".}
+
+block:
+  type Foo = ref object
+    value: int
+    
+  proc newFoo1(): Foo not nil =               # This compiles
+    return Foo(value: 1)
+    
+  proc newFoo2(): Foo not nil {.inline.} =    # This does not
+    return Foo(value: 1)
+
+  doAssert newFoo1().value == 1
+  doAssert newFoo2().value == 1
+
+{.pop.}