diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 6cc4afd6e008..445ab908fcb3 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -2061,7 +2061,6 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = let lhs = n[0] let rhs = semExprWithType(c, n[1], {efTypeAllowed}, le) if lhs.kind == nkSym and lhs.sym.kind == skResult: - n.typ() = c.enforceVoidContext if c.p.owner.kind != skMacro and resultTypeIsInferrable(lhs.sym.typ): var rhsTyp = rhs.typ if rhsTyp.kind in tyUserTypeClasses and rhsTyp.isResolvedUserTypeClass: @@ -2092,10 +2091,12 @@ proc semReturn(c: PContext, n: PNode): PNode = if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or (not c.p.owner.typ.isNil and isClosureIterator(c.p.owner.typ)): if n[0].kind != nkEmpty: + var removeResultSymUsed = false if n[0].kind == nkAsgn and n[0][0].kind == nkSym and c.p.resultSym == n[0][0].sym: discard "return is already transformed" elif c.p.resultSym != nil: # transform ``return expr`` to ``result = expr; return`` + removeResultSymUsed = sfUsed notin c.p.resultSym.flags var a = newNodeI(nkAsgn, n[0].info) a.add newSymNode(c.p.resultSym) a.add n[0] @@ -2104,6 +2105,8 @@ proc semReturn(c: PContext, n: PNode): PNode = localError(c.config, n.info, errNoReturnTypeDeclared) return result[0] = semAsgn(c, n[0]) + if removeResultSymUsed: + c.p.resultSym.flags.excl sfUsed # optimize away ``result = result``: if result[0][1].kind == nkSym and result[0][1].sym == c.p.resultSym: result[0] = c.graph.emptyNode @@ -2116,7 +2119,10 @@ proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode = return n openScope(c) result = semExpr(c, n, expectedType = expectedType) - if c.p.resultSym != nil and not isEmptyType(result.typ): + if c.p.resultSym != nil and + not isEmptyType(result.typ) and + sfUsed notin c.p.resultSym.flags: + incl(c.p.resultSym.flags, sfUsed) if result.kind == nkNilLit: # or ImplicitlyDiscardable(result): # new semantic: 'result = x' triggers the void context diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 60778d25d687..d5b5a9c58956 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1897,7 +1897,6 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) = var s = newSym(skResult, getIdent(c.cache, "result"), c.idgen, getCurrOwner(c), n.info) s.typ = t - incl(s.flags, sfUsed) if owner == skMacro or t != nil: if n.len > resultPos and n[resultPos] != nil: diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim index 4d2ce3e5f612..3502d52774ab 100644 --- a/lib/packages/docutils/rst.nim +++ b/lib/packages/docutils/rst.nim @@ -2842,7 +2842,7 @@ proc readTableRow(p: var RstParser): ColSeq = proc getColContents(p: var RstParser, colLim: ColumnLimits): string = for i in colLim.first ..< colLim.last: result.add(p.tok[i].symbol) - result.strip + result = result.strip proc isValidDelimiterRow(p: var RstParser, colNum: int): bool = let row = readTableRow(p) diff --git a/tests/discard/tvoidcontext.nim b/tests/discard/tvoidcontext1.nim similarity index 100% rename from tests/discard/tvoidcontext.nim rename to tests/discard/tvoidcontext1.nim diff --git a/tests/discard/tvoidcontext2.nim b/tests/discard/tvoidcontext2.nim new file mode 100644 index 000000000000..a1f7c5eb9b8a --- /dev/null +++ b/tests/discard/tvoidcontext2.nim @@ -0,0 +1,13 @@ +discard """ + errormsg: '''expression '"invalid"' is of type 'string' and has to be used (or discarded)''' + line: 11 +""" + +proc foo(x: var string) = + x = "hello" + +proc bar(): string = + foo(result) + "invalid" + +echo bar() diff --git a/tests/discard/twrongvoidcontext.nim b/tests/discard/twrongvoidcontext.nim new file mode 100644 index 000000000000..b873d3d1ffc0 --- /dev/null +++ b/tests/discard/twrongvoidcontext.nim @@ -0,0 +1,12 @@ +discard """ + output: ''' +true +''' +""" + +# issue #16855 + +proc f(): int = + echo (result = 1; result > 0) + +doAssert f() == 1