diff --git a/compiler/sem/sem.nim b/compiler/sem/sem.nim index 489e518f35..4d8daf5259 100644 --- a/compiler/sem/sem.nim +++ b/compiler/sem/sem.nim @@ -682,7 +682,9 @@ proc semRealConstExpr(c: PContext, n: PNode): PNode = addInNimDebugUtils(c.config, "semRealConstExpr", n, result) assert not n.isError + pushExecCon(c, {}) result = semExprWithType(c, n) + popExecCon(c) if result.kind != nkError: result = evalConstExpr(c, result) diff --git a/compiler/sem/semexprs.nim b/compiler/sem/semexprs.nim index 272dce40fd..dcc7973011 100644 --- a/compiler/sem/semexprs.nim +++ b/compiler/sem/semexprs.nim @@ -531,28 +531,28 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode = addInNimDebugUtils(c.config, "semIs", n, result, flags) if n.len != 3: - result = c.config.newError(n, PAstDiag(kind: adSemIsOperatorTakes2Args)) - return + # the check is necessary because `is` can be analyzed pre-sigmatch + return c.config.newError(n, PAstDiag(kind: adSemIsOperatorTakes2Args)) let boolType = getSysType(c.graph, n.info, tyBool) - n.typ = boolType - var liftLhs = true - - n[1] = semExprWithType(c, n[1], flags + {efWantIterator}) + var + liftLhs = true + lhs = semExprWithType(c, n[1], flags + {efWantIterator}) + rhs: PNode case n[2].kind of nkStrLiterals: - n[2] = semExpr(c, n[2]) + rhs = semExpr(c, n[2]) of nkError: discard # below we'll wrap the result in an error else: let t2 = semTypeNode(c, n[2], nil) - n[2] = newNodeIT(nkType, n[2].info, t2) + rhs = newNodeIT(nkType, n[2].info, t2) if t2.kind == tyStatic: - let evaluated = tryConstExpr(c, n[1]) + let evaluated = tryConstExpr(c, lhs) if evaluated != nil: c.fixupStaticType(evaluated) - n[1] = evaluated + lhs = evaluated else: result = newIntNode(nkIntLit, 0) result.typ = boolType @@ -564,17 +564,17 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode = # not allow regular values to be matched against the type: liftLhs = false - var lhsType = n[1].typ - if n[1].isError or n[2].isError: - result = wrapError(c.config, n) - elif lhsType.kind == tyTypeDesc and (lhsType.base.kind == tyNone or - (c.inGenericContext > 0 and lhsType.base.containsGenericType)): - # BUGFIX: don't evaluate this too early: ``T is void`` - result = n + result = shallowCopy(n) + result.typ = boolType + result[0] = n[0] + result[1] = lhs + result[2] = rhs + if result[1].isError or result[2].isError: + result = wrapError(c.config, result) else: - if lhsType.kind != tyTypeDesc and liftLhs: - n[1] = makeTypeSymNode(c, lhsType, n[1].info) - result = isOpImpl(c, n, flags) + if lhs.typ.kind != tyTypeDesc and liftLhs: + result[1] = makeTypeSymNode(c, lhs.typ, n[1].info) + result = isOpImpl(c, result, flags) proc semOpAux(c: PContext, n: PNode): bool = ## Returns whether n contains errors @@ -2945,7 +2945,7 @@ proc semWhen(c: PContext, n: PNode, flags: TExprFlags): PNode = case it.kind of nkElifBranch, nkElifExpr: checkSonsLen(it, 2, c.config) - let e = forceBool(c, semConstExpr(c, it[0])) + let e = forceBool(c, semRealConstExpr(c, it[0])) if e.kind == nkError: # error in the condition expression; wrap and return result = copyNodeWithKids(n) diff --git a/tests/error_propagation/tin_expression_in_when.nim b/tests/error_propagation/tin_expression_in_when.nim new file mode 100644 index 0000000000..6e0080e8ee --- /dev/null +++ b/tests/error_propagation/tin_expression_in_when.nim @@ -0,0 +1,7 @@ +discard """ + errormsg: "undeclared identifier: 'missing'" +""" + +var x = missing +when x is int: + discard