diff options
author | metagn <metagngn@gmail.com> | 2024-09-19 08:19:07 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-19 07:19:07 +0200 |
commit | ff005ad7dc8b4f3a36a1eb0e18ebd4cc5e062883 (patch) | |
tree | 7920309ebbbb5a0acab46d6c3e40731920c599e0 | |
parent | 6cc50ec3163c79b120bf17e32810946bad6b3893 (diff) | |
download | Nim-ff005ad7dc8b4f3a36a1eb0e18ebd4cc5e062883.tar.gz |
fix segfault in generic param mismatch error, skip typedesc (#24140)
refs #24010, refs https://github.com/nim-lang/Nim/issues/24125#issuecomment-2358377076 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.
-rw-r--r-- | compiler/semcall.nim | 37 | ||||
-rw-r--r-- | tests/errmsgs/tgenericmismatchsegfault.nim | 13 | ||||
-rw-r--r-- | tests/errmsgs/tgenericmismatchsegfault_legacy.nim | 10 | ||||
-rw-r--r-- | tests/errmsgs/twrong_explicit_typeargs.nim | 2 | ||||
-rw-r--r-- | tests/errmsgs/twrong_explicit_typeargs_legacy.nim | 2 |
5 files changed, 44 insertions, 20 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 9111e3807..13f2273a9 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -246,10 +246,18 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors): candidates.add(getProcHeader(c.config, err.sym, prefer)) candidates.addDeclaredLocMaybe(c.config, err.sym) candidates.add("\n") - let nArg = if err.firstMismatch.arg < n.len: n[err.firstMismatch.arg] else: nil + const genericParamMismatches = {kGenericParamTypeMismatch, kExtraGenericParam, kMissingGenericParam} + let isGenericMismatch = err.firstMismatch.kind in genericParamMismatches + var argList = n + if isGenericMismatch and n[0].kind == nkBracketExpr: + argList = n[0] + let nArg = + if err.firstMismatch.arg < argList.len: + argList[err.firstMismatch.arg] + else: + nil let nameParam = if err.firstMismatch.formal != nil: err.firstMismatch.formal.name.s else: "" if n.len > 1: - const genericParamMismatches = {kGenericParamTypeMismatch, kExtraGenericParam, kMissingGenericParam} if verboseTypeMismatch notin c.config.legacyFeatures: case err.firstMismatch.kind of kUnknownNamedParam: @@ -309,7 +317,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors): var wanted = err.firstMismatch.formal.typ if wanted.kind == tyGenericParam and wanted.genericParamHasConstraints: wanted = wanted.genericConstraint - let got = arg.typ + let got = arg.typ.skipTypes({tyTypeDesc}) doAssert err.firstMismatch.formal != nil doAssert wanted != nil doAssert got != nil @@ -350,17 +358,9 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors): of kMissingGenericParam: candidates.add("\n missing generic parameter: " & nameParam) of kTypeMismatch, kGenericParamTypeMismatch, kVarNeeded: - var arg: PNode = nArg - let genericMismatch = err.firstMismatch.kind == kGenericParamTypeMismatch - if genericMismatch: - let pos = err.firstMismatch.arg - doAssert n[0].kind == nkBracketExpr and pos < n[0].len - arg = n[0][pos] - else: - arg = nArg - doAssert arg != nil + doAssert nArg != nil var wanted = err.firstMismatch.formal.typ - if genericMismatch and wanted.kind == tyGenericParam and + if isGenericMismatch and wanted.kind == tyGenericParam and wanted.genericParamHasConstraints: wanted = wanted.genericConstraint doAssert err.firstMismatch.formal != nil @@ -368,16 +368,17 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors): candidates.addTypeDeclVerboseMaybe(c.config, wanted) candidates.add "\n but expression '" if err.firstMismatch.kind == kVarNeeded: - candidates.add renderNotLValue(arg) + candidates.add renderNotLValue(nArg) candidates.add "' is immutable, not 'var'" else: - candidates.add renderTree(arg) + candidates.add renderTree(nArg) candidates.add "' is of type: " - let got = arg.typ + var got = nArg.typ + if isGenericMismatch: got = got.skipTypes({tyTypeDesc}) candidates.addTypeDeclVerboseMaybe(c.config, got) - if arg.kind in nkSymChoices: + if nArg.kind in nkSymChoices: candidates.add "\n" - candidates.add ambiguousIdentifierMsg(arg, indent = 2) + candidates.add ambiguousIdentifierMsg(nArg, indent = 2) doAssert wanted != nil if got != nil: if got.kind == tyProc and wanted.kind == tyProc: diff --git a/tests/errmsgs/tgenericmismatchsegfault.nim b/tests/errmsgs/tgenericmismatchsegfault.nim new file mode 100644 index 000000000..dbb783cb3 --- /dev/null +++ b/tests/errmsgs/tgenericmismatchsegfault.nim @@ -0,0 +1,13 @@ +discard """ + matrix: "-d:testsConciseTypeMismatch" +""" + +template v[T](c: SomeOrdinal): T = T(c) +discard v[int, char]('A') #[tt.Error + ^ type mismatch +Expression: v[int, char]('A') + [1] 'A': char + +Expected one of (first mismatch at [position]): +[2] template v[T](c: SomeOrdinal): T + generic parameter mismatch, expected SomeOrdinal but got 'char' of type: char]# diff --git a/tests/errmsgs/tgenericmismatchsegfault_legacy.nim b/tests/errmsgs/tgenericmismatchsegfault_legacy.nim new file mode 100644 index 000000000..1532611b9 --- /dev/null +++ b/tests/errmsgs/tgenericmismatchsegfault_legacy.nim @@ -0,0 +1,10 @@ +template v[T](c: SomeOrdinal): T = T(c) +discard v[int, char]('A') #[tt.Error + ^ type mismatch: got <char> +but expected one of: +template v[T](c: SomeOrdinal): T + first type mismatch at position: 2 in generic parameters + required type for SomeOrdinal: SomeOrdinal + but expression 'char' is of type: char + +expression: v[int, char]('A')]# diff --git a/tests/errmsgs/twrong_explicit_typeargs.nim b/tests/errmsgs/twrong_explicit_typeargs.nim index 705eec52b..5236e5f4f 100644 --- a/tests/errmsgs/twrong_explicit_typeargs.nim +++ b/tests/errmsgs/twrong_explicit_typeargs.nim @@ -9,7 +9,7 @@ Expression: newImage[string](320, 200) Expected one of (first mismatch at [position]): [1] proc newImage[T: int32 | int64](w, h: int): ref Image[T] - generic parameter mismatch, expected int32 or int64 but got 'string' of type: typedesc[string] + generic parameter mismatch, expected int32 or int64 but got 'string' of type: string ''' """ diff --git a/tests/errmsgs/twrong_explicit_typeargs_legacy.nim b/tests/errmsgs/twrong_explicit_typeargs_legacy.nim index fb81412dc..cfa528c54 100644 --- a/tests/errmsgs/twrong_explicit_typeargs_legacy.nim +++ b/tests/errmsgs/twrong_explicit_typeargs_legacy.nim @@ -6,7 +6,7 @@ but expected one of: proc newImage[T: int32 | int64](w, h: int): ref Image[T] first type mismatch at position: 1 in generic parameters required type for T: int32 or int64 - but expression 'string' is of type: typedesc[string] + but expression 'string' is of type: string expression: newImage[string](320, 200) ''' |