Skip to content

Commit

Permalink
sem: fix error propagation for tuple construction
Browse files Browse the repository at this point in the history
Summary
=======

* fix errors in anonymous tuple constructions not being propagated
* fix the error for colon expressions in anonymous tuple constructions
  being "invalid expression" instead of "named expression not allowed
  here"

Details
=======

* properly propagate errors from element expressions
* don't analyze `nkExprColonExpr` as a normal expression
* don't modify input AST
* skip tuple type constructor analysis if any of the element
  expressions is erroneous
  • Loading branch information
zerbina committed Aug 7, 2024
1 parent 39660ca commit 2ee57b3
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 22 deletions.
54 changes: 32 additions & 22 deletions compiler/sem/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3148,39 +3148,49 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
"expected nkTupleConstr, got: " & $n.kind)

let
tupExp = n # we don't modify n, but compute the type:
tupExp = shallowCopy(n)
typ = newTypeS(tyTuple, c) # leave typ.n nil!
for i in 0..<tupExp.len:
tupExp[i] = semExprWithType(c, tupExp[i], {}) # xxx: claim of not modifying
# n is dubious
addSonSkipIntLit(typ, tupExp[i].typ, c.idgen)

var hasError = false

for i, it in n.pairs:
var etyp: PType
if it.kind == nkExprColonExpr:
# can happen for ``(a, b: c)``. Analyze the expression for the sake of
# error correction (check/nimsuggest)
let elem = copyNodeWithKids(it)
elem[1] = semExprWithType(c, it[1], {})
etyp = elem[1].typ

tupExp[i] = c.config.newError(elem):
PAstDiag(kind: adSemNamedExprNotAllowed)
else:
tupExp[i] = semExprWithType(c, it, {})
etyp = tupExp[i].typ

hasError = hasError or tupExp[i].isError
addSonSkipIntLit(typ, etyp, c.idgen)

tupExp.typ = typ

var
isTupleType: bool
hasError = false
if hasError:
# don't analyze any further
return c.config.wrapError(tupExp)

if tupExp.len > 0: # don't interpret () as type
isTupleType = tupExp[0].typ.kind == tyTypeDesc
let isTupleType = tupExp[0].typ.kind == tyTypeDesc
# check if either everything or nothing is tyTypeDesc
for i in 1..<tupExp.len:
if tupExp[i].kind == nkExprColonExpr:
hasError = true
# xxx: not sure if this modification is safe
tupExp[i] = c.config.newError(tupExp[i],
PAstDiag(kind: adSemNamedExprNotAllowed))
elif isTupleType != (tupExp[i].typ.kind == tyTypeDesc):
if isTupleType != (tupExp[i].typ.kind == tyTypeDesc):
# xxx: maybe capture the field instead of the info?
return c.config.newError(n,
PAstDiag(kind: adSemCannotMixTypesAndValuesInTuple,
wrongFldInfo: tupExp[i].info))

if hasError:
result = c.config.wrapError(tupExp)
elif isTupleType: # reinterpret `(int, string)` as type expressions
result = n
result.typ = makeTypeDesc(c, semTypeNode(c, n, nil).skipTypes({tyTypeDesc}))
else:
result = tupExp
if isTupleType: # reinterpret `(int, string)` as a type expression
tupExp.typ = makeTypeDesc(c, semTypeNode(c, tupExp, nil))

result = tupExp

proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
## analyse tuple construction based on position of fields or return errors
Expand Down
7 changes: 7 additions & 0 deletions tests/errmsgs/tmixed_tuple.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
discard """
errormsg: "named expression not allowed here"
line: 7
"""

var x = 0
discard (x, a: x)

0 comments on commit 2ee57b3

Please sign in to comment.