Skip to content

Commit 0ddf173

Browse files
committed
fix(sem): errors in lambdas no longer crash
Summary --------- Errors in lambdas requiring inference (`proc(e: auto) echo e`), no longer crash the compiler. Instead errors within the lambda body are reported and lambda inference fails as it should. Details ------- `semInferredLambda` failed to wrap its output when there were errors. This would reach `transf` and result in a compiler crash by hitting an `unreachable` assertion. Now errors in the body are reported immediately (to provide context for inference failure) and AST output from the inference attempt is correctly wrapped such that inference appropriately fails.
1 parent 17f96a1 commit 0ddf173

File tree

2 files changed

+39
-21
lines changed

2 files changed

+39
-21
lines changed

compiler/sem/semstmts.nim

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,45 +2182,52 @@ proc semProcAnnotation(c: PContext, prc: PNode): PNode =
21822182
proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode {.nosinks.} =
21832183
## used for resolving 'auto' in lambdas based on their callsite
21842184
addInNimDebugUtils(c.config, "semInferredLambda", n, result)
2185-
var n = n
21862185
let original = n[namePos].sym
21872186
let s = original #copySym(original, false)
21882187
#incl(s.flags, sfFromGeneric)
21892188
#s.owner = original
21902189

2191-
n = instantiateTypesInBody(c, pt, n, original)
2192-
result = n
2190+
result = instantiateTypesInBody(c, pt, n, original)
21932191
s.ast = result
2194-
n[namePos].sym = s
2195-
n[genericParamsPos] = c.graph.emptyNode
2192+
result[namePos].sym = s
2193+
result[genericParamsPos] = c.graph.emptyNode
21962194
# for LL we need to avoid wrong aliasing
2197-
n[paramsPos] = newNodeI(nkFormalParams, n[paramsPos].info, n.typ.n.len)
2198-
for i, p in n.typ.n.pairs:
2199-
n[paramsPos][i] =
2195+
result[paramsPos] = newNodeI(nkFormalParams, result[paramsPos].info,
2196+
result.typ.n.len)
2197+
for i, p in result.typ.n.pairs:
2198+
result[paramsPos][i] =
22002199
case i
22012200
of 0: # return type
2202-
newNodeIT(nkType, n.info, n.typ[0])
2201+
newNodeIT(nkType, n.info, result.typ[0])
22032202
else: # copy instantiated parameters
2204-
n.typ.n[i]
2205-
s.typ = n.typ
2206-
let params = n.typ.n
2207-
for i in 1..<params.len:
2208-
if params[i].typ.kind in {tyTypeDesc, tyGenericParam,
2209-
tyFromExpr}+tyTypeClasses:
2210-
localReport(c.config, params[i].info, reportSym(
2211-
rsemCannotInferTypeOfParameter, params[i].sym))
2212-
#params[i].sym.owner = s
2203+
if p.typ.kind in {tyTypeDesc, tyGenericParam,
2204+
tyFromExpr}+tyTypeClasses:
2205+
localReport(c.config, p.info, reportSym(
2206+
rsemCannotInferTypeOfParameter, p.sym))
2207+
#params[i].sym.owner = s
2208+
result.typ.n[i]
2209+
s.typ = result.typ
22132210
openScope(c)
22142211
pushOwner(c, s)
2215-
addParams(c, params)
2212+
addParams(c, result.typ.n)
22162213
pushProcCon(c, s)
2217-
addResult(c, n, n.typ[0])
2218-
s.ast[bodyPos] = hloBody(c, semProcBody(c, n[bodyPos]))
2214+
addResult(c, result, result.typ[0])
2215+
result[bodyPos] = semProcBody(c, result[bodyPos])
2216+
if result[bodyPos].kind == nkError:
2217+
# output the error now otherwise we'll just get an inferred lambda failure
2218+
# without an explanation, ideally this should be explained/added context of
2219+
# the inferred lambda error itself.
2220+
c.config.localReport(result[bodyPos])
2221+
s.ast[bodyPos] = hloBody(c, result[bodyPos])
22192222
s.ast[bodyPos] = foldInAst(c.module, s.ast[bodyPos], c.idgen, c.graph)
22202223
trackProc(c, s, s.ast[bodyPos])
22212224
popProcCon(c)
22222225
popOwner(c)
22232226
closeScope(c)
2227+
# wrap in an error if there were issues along the way
2228+
for k in result.items:
2229+
if k.kind == nkError:
2230+
result = c.config.wrapError(result)
22242231
# alternative variant (not quite working):
22252232
# var prc = arg[0].sym
22262233
# let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
discard """
2+
description: "Fail lambda inference due to error without the body."
3+
errormsg: "undeclared identifier: 'i'"
4+
line: 11
5+
"""
6+
7+
# This is a regression test, ensure we report errors inside lambdas during
8+
# inference
9+
10+
var x: seq[proc(i: int)]
11+
x.add proc(e: auto) = echo i

0 commit comments

Comments
 (0)