Skip to content

Commit ff005ad

Browse files
authored
fix segfault in generic param mismatch error, skip typedesc (#24140)
refs #24010, refs #24125 (comment) The generic mismatch errors added in #24010 made it possible for `nArg` to be `nil` in the error reporting since it checked the call argument list, not the generic parameter list for the mismatching argument node, which causes a segfault. This is fixed by checking the generic parameter list immediately on any generic mismatch error. Also the `typedesc` type is skipped for the value of the generic params since it's redundant and the generic parameter constraints don't have it.
1 parent 6cc50ec commit ff005ad

File tree

5 files changed

+44
-20
lines changed

5 files changed

+44
-20
lines changed

compiler/semcall.nim

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,18 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
246246
candidates.add(getProcHeader(c.config, err.sym, prefer))
247247
candidates.addDeclaredLocMaybe(c.config, err.sym)
248248
candidates.add("\n")
249-
let nArg = if err.firstMismatch.arg < n.len: n[err.firstMismatch.arg] else: nil
249+
const genericParamMismatches = {kGenericParamTypeMismatch, kExtraGenericParam, kMissingGenericParam}
250+
let isGenericMismatch = err.firstMismatch.kind in genericParamMismatches
251+
var argList = n
252+
if isGenericMismatch and n[0].kind == nkBracketExpr:
253+
argList = n[0]
254+
let nArg =
255+
if err.firstMismatch.arg < argList.len:
256+
argList[err.firstMismatch.arg]
257+
else:
258+
nil
250259
let nameParam = if err.firstMismatch.formal != nil: err.firstMismatch.formal.name.s else: ""
251260
if n.len > 1:
252-
const genericParamMismatches = {kGenericParamTypeMismatch, kExtraGenericParam, kMissingGenericParam}
253261
if verboseTypeMismatch notin c.config.legacyFeatures:
254262
case err.firstMismatch.kind
255263
of kUnknownNamedParam:
@@ -309,7 +317,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
309317
var wanted = err.firstMismatch.formal.typ
310318
if wanted.kind == tyGenericParam and wanted.genericParamHasConstraints:
311319
wanted = wanted.genericConstraint
312-
let got = arg.typ
320+
let got = arg.typ.skipTypes({tyTypeDesc})
313321
doAssert err.firstMismatch.formal != nil
314322
doAssert wanted != nil
315323
doAssert got != nil
@@ -350,34 +358,27 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
350358
of kMissingGenericParam:
351359
candidates.add("\n missing generic parameter: " & nameParam)
352360
of kTypeMismatch, kGenericParamTypeMismatch, kVarNeeded:
353-
var arg: PNode = nArg
354-
let genericMismatch = err.firstMismatch.kind == kGenericParamTypeMismatch
355-
if genericMismatch:
356-
let pos = err.firstMismatch.arg
357-
doAssert n[0].kind == nkBracketExpr and pos < n[0].len
358-
arg = n[0][pos]
359-
else:
360-
arg = nArg
361-
doAssert arg != nil
361+
doAssert nArg != nil
362362
var wanted = err.firstMismatch.formal.typ
363-
if genericMismatch and wanted.kind == tyGenericParam and
363+
if isGenericMismatch and wanted.kind == tyGenericParam and
364364
wanted.genericParamHasConstraints:
365365
wanted = wanted.genericConstraint
366366
doAssert err.firstMismatch.formal != nil
367367
candidates.add("\n required type for " & nameParam & ": ")
368368
candidates.addTypeDeclVerboseMaybe(c.config, wanted)
369369
candidates.add "\n but expression '"
370370
if err.firstMismatch.kind == kVarNeeded:
371-
candidates.add renderNotLValue(arg)
371+
candidates.add renderNotLValue(nArg)
372372
candidates.add "' is immutable, not 'var'"
373373
else:
374-
candidates.add renderTree(arg)
374+
candidates.add renderTree(nArg)
375375
candidates.add "' is of type: "
376-
let got = arg.typ
376+
var got = nArg.typ
377+
if isGenericMismatch: got = got.skipTypes({tyTypeDesc})
377378
candidates.addTypeDeclVerboseMaybe(c.config, got)
378-
if arg.kind in nkSymChoices:
379+
if nArg.kind in nkSymChoices:
379380
candidates.add "\n"
380-
candidates.add ambiguousIdentifierMsg(arg, indent = 2)
381+
candidates.add ambiguousIdentifierMsg(nArg, indent = 2)
381382
doAssert wanted != nil
382383
if got != nil:
383384
if got.kind == tyProc and wanted.kind == tyProc:
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
discard """
2+
matrix: "-d:testsConciseTypeMismatch"
3+
"""
4+
5+
template v[T](c: SomeOrdinal): T = T(c)
6+
discard v[int, char]('A') #[tt.Error
7+
^ type mismatch
8+
Expression: v[int, char]('A')
9+
[1] 'A': char
10+
11+
Expected one of (first mismatch at [position]):
12+
[2] template v[T](c: SomeOrdinal): T
13+
generic parameter mismatch, expected SomeOrdinal but got 'char' of type: char]#
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
template v[T](c: SomeOrdinal): T = T(c)
2+
discard v[int, char]('A') #[tt.Error
3+
^ type mismatch: got <char>
4+
but expected one of:
5+
template v[T](c: SomeOrdinal): T
6+
first type mismatch at position: 2 in generic parameters
7+
required type for SomeOrdinal: SomeOrdinal
8+
but expression 'char' is of type: char
9+
10+
expression: v[int, char]('A')]#

tests/errmsgs/twrong_explicit_typeargs.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Expression: newImage[string](320, 200)
99
1010
Expected one of (first mismatch at [position]):
1111
[1] proc newImage[T: int32 | int64](w, h: int): ref Image[T]
12-
generic parameter mismatch, expected int32 or int64 but got 'string' of type: typedesc[string]
12+
generic parameter mismatch, expected int32 or int64 but got 'string' of type: string
1313
'''
1414
"""
1515

tests/errmsgs/twrong_explicit_typeargs_legacy.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ but expected one of:
66
proc newImage[T: int32 | int64](w, h: int): ref Image[T]
77
first type mismatch at position: 1 in generic parameters
88
required type for T: int32 or int64
9-
but expression 'string' is of type: typedesc[string]
9+
but expression 'string' is of type: string
1010
1111
expression: newImage[string](320, 200)
1212
'''

0 commit comments

Comments
 (0)