From cf8fe16a48d79d149f6ce85e229d23c1513c2497 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sat, 15 Mar 2014 11:23:46 +0200 Subject: [PATCH] fix #715 again the regression was caused by the introduction of "generic" lambdas --- compiler/msgs.nim | 6 ++++++ compiler/semdata.nim | 2 +- compiler/semexprs.nim | 7 ++++++- compiler/semstmts.nim | 4 +++- tests/generics/tbadgenericlambda.nim | 7 +++++++ tests/generics/tgenericlambda.nim | 7 ++++++- 6 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 tests/generics/tbadgenericlambda.nim diff --git a/compiler/msgs.nim b/compiler/msgs.nim index c75876843..3e5a56e1e 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -106,6 +106,8 @@ type errThreadvarCannotInit, errWrongSymbolX, errIllegalCaptureX, errXCannotBeClosure, errXMustBeCompileTime, errCannotInferTypeOfTheLiteral, + errCannotInferReturnType, + errGenericLambdaNotAllowed, errUser, warnCannotOpenFile, warnOctalEscape, warnXIsNeverRead, warnXmightNotBeenInit, @@ -355,6 +357,10 @@ const errXCannotBeClosure: "'$1' cannot have 'closure' calling convention", errXMustBeCompileTime: "'$1' can only be used in compile-time context", errCannotInferTypeOfTheLiteral: "cannot infer the type of the $1", + errCannotInferReturnType: "cannot infer the return type of the proc", + errGenericLambdaNotAllowed: "A nested proc can have generic parameters only when " & + "it is used as an operand to another routine and the types " & + "of the generic paramers can be infered from the expected signature.", errUser: "$1", warnCannotOpenFile: "cannot open \'$1\' [CannotOpenFile]", warnOctalEscape: "octal escape sequences do not exist; leading zero is ignored [OctalEscape]", diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 84e017050..088b93fae 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -42,7 +42,7 @@ type TExprFlag* = enum efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType, - efAllowDestructor, efWantValue + efAllowDestructor, efWantValue, efOperand TExprFlags* = set[TExprFlag] PContext* = ref TContext diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 62a816a50..ba2847835 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -21,7 +21,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = # same as 'semExprWithType' but doesn't check for proc vars - result = semExpr(c, n, flags) + result = semExpr(c, n, flags + {efOperand}) if result.kind == nkEmpty: # do not produce another redundant error message: #raiseRecoverableError("") @@ -1218,6 +1218,7 @@ proc semReturn(c: PContext, n: PNode): PNode = proc semProcBody(c: PContext, n: PNode): PNode = openScope(c) + result = semExpr(c, n) if c.p.resultSym != nil and not isEmptyType(result.typ): # transform ``expr`` to ``result = expr``, but not if the expr is already @@ -1241,6 +1242,10 @@ proc semProcBody(c: PContext, n: PNode): PNode = result = semAsgn(c, a) else: discardCheck(c, result) + + if c.p.resultSym != nil and c.p.resultSym.typ.isMetaType: + localError(c.p.resultSym.info, errCannotInferReturnType) + closeScope(c) proc semYieldVarResult(c: PContext, n: PNode, restype: PType) = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index edce7c9bd..15bfaab10 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -944,13 +944,15 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s) #if efDetermineType notin flags: # XXX not good enough; see tnamedparamanonproc.nim - if n.sons[genericParamsPos].kind == nkEmpty: + if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags): pushProcCon(c, s) addResult(c, s.typ.sons[0], n.info, skProc) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) n.sons[bodyPos] = transformBody(c.module, semBody, s) addResultNode(c, n) popProcCon(c) + elif efOperand notin flags: + localError(n.info, errGenericLambdaNotAllowed) sideEffectsCheck(c, s) else: localError(n.info, errImplOfXexpected, s.name.s) diff --git a/tests/generics/tbadgenericlambda.nim b/tests/generics/tbadgenericlambda.nim new file mode 100644 index 000000000..5e406cacc --- /dev/null +++ b/tests/generics/tbadgenericlambda.nim @@ -0,0 +1,7 @@ +discard """ + msg: "nested proc can have generic parameters only when" + line: 6 +""" + +let x = proc (x, y): auto = x + y + diff --git a/tests/generics/tgenericlambda.nim b/tests/generics/tgenericlambda.nim index f7aafe1d9..eb6ada3e5 100644 --- a/tests/generics/tgenericlambda.nim +++ b/tests/generics/tgenericlambda.nim @@ -1,5 +1,5 @@ discard """ - output: "10\n10\n1\n2\n3" + output: "10\n10\n1\n2\n3\n15" """ proc test(x: proc (a, b: int): int) = @@ -16,3 +16,8 @@ proc foreach[T](s: seq[T], body: proc(x: T)) = foreach(@[1,2,3]) do (x): echo x +proc foo = + let x = proc (a, b: int): auto = a + b + echo x(5, 10) + +foo()