diff --git a/compiler/sem.nim b/compiler/sem.nim index 3392db7a9d..0739c6e162 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -321,7 +321,7 @@ proc hasCycle(n: PNode): bool = break excl n.flags, nfNone -proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode = +proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode; producedClosure: var bool): PNode = # recompute the types as 'eval' isn't guaranteed to construct types nor # that the types are sound: when true: @@ -333,7 +333,7 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode = if hasCycle(result): result = localErrorNode(c, eOrig, "the resulting AST is cyclic and cannot be processed further") else: - semmacrosanity.annotateType(result, expectedType, c.config) + semmacrosanity.annotateType(result, expectedType, c.config, producedClosure) else: result = semExprWithType(c, evaluated) #result = fitNode(c, e.typ, result) inlined with special case: @@ -370,7 +370,10 @@ proc tryConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode = if result == nil or result.kind == nkEmpty: result = nil else: - result = fixupTypeAfterEval(c, result, e) + var producedClosure = false + result = fixupTypeAfterEval(c, result, e, producedClosure) + if producedClosure: + result = nil except ERecoverableError: result = nil @@ -407,7 +410,10 @@ proc semConstExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode = # error correction: result = e else: - result = fixupTypeAfterEval(c, result, e) + var producedClosure = false + result = fixupTypeAfterEval(c, result, e, producedClosure) + if producedClosure: + result = nil proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode = if efNeedStatic in flags: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index c7a0994099..c1b49a19e9 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -951,11 +951,15 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = result = evalStaticExpr(c.module, c.idgen, c.graph, call, c.p.owner) if result.isNil: localError(c.config, n.info, errCannotInterpretNodeX % renderTree(call)) - else: result = fixupTypeAfterEval(c, result, n) + else: + var producedClosure = false + result = fixupTypeAfterEval(c, result, n, producedClosure) else: result = evalConstExpr(c.module, c.idgen, c.graph, call) if result.isNil: result = n - else: result = fixupTypeAfterEval(c, result, n) + else: + var producedClosure = false + result = fixupTypeAfterEval(c, result, n, producedClosure) else: result = n #if result != n: @@ -973,7 +977,8 @@ proc semStaticExpr(c: PContext, n: PNode; expectedType: PType = nil): PNode = localError(c.config, n.info, errCannotInterpretNodeX % renderTree(n)) result = c.graph.emptyNode else: - result = fixupTypeAfterEval(c, result, a) + var producedClosure = false + result = fixupTypeAfterEval(c, result, a, producedClosure) proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, flags: TExprFlags; expectedType: PType = nil): PNode = @@ -3070,10 +3075,10 @@ proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp proc isExplicitGenericCall(c: PContext, n: PNode): bool = ## checks if a call node `n` is a routine call with explicit generic params - ## + ## ## the callee node needs to be either an nkBracketExpr or a call to a ## symchoice of `[]` in which case it will be transformed into nkBracketExpr - ## + ## ## the LHS of the bracket expr has to either be a symchoice or resolve to ## a routine symbol template checkCallee(n: PNode) = diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim index cba6b4a46a..1675114c2b 100644 --- a/compiler/semmacrosanity.nim +++ b/compiler/semmacrosanity.nim @@ -86,7 +86,7 @@ proc ithField(t: PType, field: var FieldTracker): FieldInfo = base = b.baseClass result = ithField(t.n, field) -proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = +proc annotateType*(n: PNode, t: PType; conf: ConfigRef; producedClosure: var bool) = let x = t.skipTypes(abstractInst+{tyRange}) # Note: x can be unequal to t and we need to be careful to use 't' # to not to skip tyGenericInst @@ -102,7 +102,7 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = globalError conf, n.info, "invalid field at index " & $i else: internalAssert(conf, n[i].kind == nkExprColonExpr) - annotateType(n[i][1], field.sym.typ, conf) + annotateType(n[i][1], field.sym.typ, conf, producedClosure) if field.delete: # only codegen fields from active case branches incl(n[i].flags, nfPreventCg) @@ -111,9 +111,11 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = n.typ() = t for i in 0..= x.kidsLen: globalError conf, n.info, "invalid field at index " & $i - else: annotateType(n[i], x[i], conf) + else: annotateType(n[i], x[i], conf, producedClosure) elif x.kind == tyProc and x.callConv == ccClosure: n.typ() = t + if n.len > 1 and n[1].kind notin {nkEmpty, nkNilLit}: + producedClosure = true elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples if n.kind == nkTupleConstr: let @@ -125,11 +127,11 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = of nkStrKinds: for i in left..right: bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i]) - annotateType(bracketExpr[^1], x.elementType, conf) + annotateType(bracketExpr[^1], x.elementType, conf, producedClosure) of nkBracket: for i in left..right: bracketExpr.add n[0][i] - annotateType(bracketExpr[^1], x.elementType, conf) + annotateType(bracketExpr[^1], x.elementType, conf, producedClosure) else: globalError(conf, n.info, "Incorrectly generated tuple constr") n[] = bracketExpr[] @@ -140,7 +142,7 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = of nkBracket: if x.kind in {tyArray, tySequence, tyOpenArray}: n.typ() = t - for m in n: annotateType(m, x.elemType, conf) + for m in n: annotateType(m, x.elemType, conf, producedClosure) else: globalError(conf, n.info, "[] must have some form of array type") of nkCurly: @@ -148,10 +150,10 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) = n.typ() = t for m in n: if m.kind == nkRange: - annotateType(m[0], x.elemType, conf) - annotateType(m[1], x.elemType, conf) + annotateType(m[0], x.elemType, conf, producedClosure) + annotateType(m[1], x.elemType, conf, producedClosure) else: - annotateType(m, x.elemType, conf) + annotateType(m, x.elemType, conf, producedClosure) else: globalError(conf, n.info, "{} must have the set type") of nkFloatLit..nkFloat128Lit: diff --git a/compiler/vm.nim b/compiler/vm.nim index 1355dd1efd..2a97140d64 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -859,9 +859,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcLdObj: # a = b.c decodeBC(rkNode) - if rb >= regs.len or regs[rb].kind == rkNone or + if rb >= regs.len or regs[rb].kind == rkNone or (regs[rb].kind == rkNode and regs[rb].node == nil) or - (regs[rb].kind == rkNodeAddr and regs[rb].nodeAddr[] == nil): + (regs[rb].kind == rkNodeAddr and regs[rb].nodeAddr[] == nil): stackTrace(c, tos, pc, errNilAccess) else: let src = if regs[rb].kind == rkNode: regs[rb].node else: regs[rb].nodeAddr[] @@ -1472,7 +1472,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let node = regs[rb+i].regToNode node.info = c.debug[pc] if prc.typ[i].kind notin {tyTyped, tyUntyped}: - node.annotateType(prc.typ[i], c.config) + var producedClosure = false + node.annotateType(prc.typ[i], c.config, producedClosure) macroCall.add(node) var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache, c.templInstCounter, c.idgen)