From 4ded6a0b5223bbcaa5f707e2e9a0eda1d93d0ac7 Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 12 Jun 2023 07:22:50 +0300 Subject: [PATCH] make binary `not` not parse complex expressions on right side (#22078) * binary `not` only parses simple expressions fixes #16324 * switch to primary --- compiler/parser.nim | 8 ++++---- doc/grammar.txt | 6 +++--- tests/notnil/tparse.nim | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 tests/notnil/tparse.nim diff --git a/compiler/parser.nim b/compiler/parser.nim index 734474dbf18cb..1b8fd70a60ac8 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 e498dd2b2469f..458eeb54a67a3 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 0000000000000..5c938ff04f62d --- /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.}