Skip to content

Commit 4a548de

Browse files
authored
proper errors for subscript overloads (#24068)
The magic `mArrGet`/`mArrPut` subscript overloads always match, so if a subscript doesn't match any other subscript overloads and isn't a regular language-handled subscript, it creates a fake overload mismatch error in `semArrGet` that doesn't have any information (gives stuff like "first mismatch at index: 0" for every single mismatch). Instead of generating the fake mismatches, we only generate the fake mismatch for `mArrGet`/`mArrPut`, and process every overload except them as a real call and get the errors from there.
1 parent d77ea07 commit 4a548de

File tree

7 files changed

+128
-52
lines changed

7 files changed

+128
-52
lines changed

compiler/semcall.nim

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -458,23 +458,6 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
458458
result.add("\n" & errExpectedPosition & "\n" & candidates)
459459
localError(c.config, n.info, result)
460460

461-
proc bracketNotFoundError(c: PContext; n: PNode) =
462-
var errors: CandidateErrors = @[]
463-
var o: TOverloadIter = default(TOverloadIter)
464-
let headSymbol = n[0]
465-
var symx = initOverloadIter(o, c, headSymbol)
466-
while symx != nil:
467-
if symx.kind in routineKinds:
468-
errors.add(CandidateError(sym: symx,
469-
firstMismatch: MismatchInfo(),
470-
diagnostics: @[],
471-
enabled: false))
472-
symx = nextOverloadIter(o, c, headSymbol)
473-
if errors.len == 0:
474-
localError(c.config, n.info, "could not resolve: " & $n)
475-
else:
476-
notFoundError(c, n, errors)
477-
478461
proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
479462
result = ""
480463
if c.compilesContextId > 0:
@@ -603,6 +586,39 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
603586
getProcHeader(c.config, alt.calleeSym),
604587
args])
605588

589+
proc bracketNotFoundError(c: PContext; n: PNode; flags: TExprFlags) =
590+
var errors: CandidateErrors = @[]
591+
let headSymbol = n[0]
592+
block:
593+
# we build a closed symchoice of all `[]` overloads for their errors,
594+
# except add a custom error for the magics which always match
595+
var choice = newNodeIT(nkClosedSymChoice, headSymbol.info, newTypeS(tyNone, c))
596+
var o: TOverloadIter = default(TOverloadIter)
597+
var symx = initOverloadIter(o, c, headSymbol)
598+
while symx != nil:
599+
if symx.kind in routineKinds:
600+
if symx.magic in {mArrGet, mArrPut}:
601+
errors.add(CandidateError(sym: symx,
602+
firstMismatch: MismatchInfo(),
603+
diagnostics: @[],
604+
enabled: false))
605+
else:
606+
choice.add newSymNode(symx, headSymbol.info)
607+
symx = nextOverloadIter(o, c, headSymbol)
608+
n[0] = choice
609+
# copied from semOverloadedCallAnalyzeEffects, might be overkill:
610+
const baseFilter = {skProc, skFunc, skMethod, skConverter, skMacro, skTemplate}
611+
let filter =
612+
if flags*{efInTypeof, efWantIterator, efWantIterable} != {}:
613+
baseFilter + {skIterator}
614+
else: baseFilter
615+
# this will add the errors:
616+
var r = resolveOverloads(c, n, n, filter, flags, errors, true)
617+
if errors.len == 0:
618+
localError(c.config, n.info, "could not resolve: " & $n)
619+
else:
620+
notFoundError(c, n, errors)
621+
606622
proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) =
607623
let a = if a.kind == nkHiddenDeref: a[0] else: a
608624
if a.kind == nkHiddenCallConv and a[0].kind == nkSym:

compiler/semexprs.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1993,7 +1993,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
19931993
result = buildOverloadedSubscripts(n[0], getIdent(c.cache, "[]="))
19941994
result.add(n[1])
19951995
if mode == noOverloadedSubscript:
1996-
bracketNotFoundError(c, result)
1996+
bracketNotFoundError(c, result, {})
19971997
return errorNode(c, n)
19981998
else:
19991999
result = semExprNoType(c, result)

compiler/semmagic.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
6868
if result.isNil:
6969
let x = copyTree(n)
7070
x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
71-
bracketNotFoundError(c, x)
71+
bracketNotFoundError(c, x, flags)
7272
#localError(c.config, n.info, "could not resolve: " & $n)
7373
result = errorNode(c, n)
7474

tests/errmsgs/t10735.nim

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,62 @@ discard """
22
cmd: "nim check $file"
33
errormsg: "illformed AST: case buf[pos]"
44
nimout: '''
5-
t10735.nim(43, 5) Error: 'let' symbol requires an initialization
6-
t10735.nim(44, 10) Error: undeclared identifier: 'pos'
7-
t10735.nim(44, 10) Error: expression 'pos' has no type (or is ambiguous)
8-
t10735.nim(44, 10) Error: expression 'pos' has no type (or is ambiguous)
9-
t10735.nim(44, 9) Error: type mismatch: got <cstring, >
5+
t10735.nim(65, 5) Error: 'let' symbol requires an initialization
6+
t10735.nim(66, 10) Error: undeclared identifier: 'pos'
7+
t10735.nim(66, 10) Error: expression 'pos' has no type (or is ambiguous)
8+
t10735.nim(66, 10) Error: expression 'pos' has no type (or is ambiguous)
9+
t10735.nim(66, 9) Error: type mismatch: got <cstring, >
1010
but expected one of:
1111
proc `[]`(s: string; i: BackwardsIndex): char
12-
first type mismatch at position: 0
12+
first type mismatch at position: 1
13+
required type for s: string
14+
but expression 'buf' is of type: cstring
1315
proc `[]`(s: var string; i: BackwardsIndex): var char
14-
first type mismatch at position: 0
16+
first type mismatch at position: 1
17+
required type for s: var string
18+
but expression 'buf' is of type: cstring
1519
proc `[]`[I: Ordinal; T](a: T; i: I): T
1620
first type mismatch at position: 0
1721
proc `[]`[Idx, T; U, V: Ordinal](a: array[Idx, T]; x: HSlice[U, V]): seq[T]
18-
first type mismatch at position: 0
22+
first type mismatch at position: 1
23+
required type for a: array[Idx, T]
24+
but expression 'buf' is of type: cstring
1925
proc `[]`[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T
20-
first type mismatch at position: 0
26+
first type mismatch at position: 1
27+
required type for a: array[Idx, T]
28+
but expression 'buf' is of type: cstring
2129
proc `[]`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T
22-
first type mismatch at position: 0
30+
first type mismatch at position: 1
31+
required type for a: var array[Idx, T]
32+
but expression 'buf' is of type: cstring
2333
proc `[]`[T, U: Ordinal](s: string; x: HSlice[T, U]): string
24-
first type mismatch at position: 0
34+
first type mismatch at position: 1
35+
required type for s: string
36+
but expression 'buf' is of type: cstring
2537
proc `[]`[T; U, V: Ordinal](s: openArray[T]; x: HSlice[U, V]): seq[T]
26-
first type mismatch at position: 0
38+
first type mismatch at position: 1
39+
required type for s: openArray[T]
40+
but expression 'buf' is of type: cstring
2741
proc `[]`[T](s: openArray[T]; i: BackwardsIndex): T
28-
first type mismatch at position: 0
42+
first type mismatch at position: 1
43+
required type for s: openArray[T]
44+
but expression 'buf' is of type: cstring
2945
proc `[]`[T](s: var openArray[T]; i: BackwardsIndex): var T
30-
first type mismatch at position: 0
46+
first type mismatch at position: 1
47+
required type for s: var openArray[T]
48+
but expression 'buf' is of type: cstring
3149
template `[]`(a: WideCStringObj; idx: int): Utf16Char
32-
first type mismatch at position: 0
50+
first type mismatch at position: 1
51+
required type for a: WideCStringObj
52+
but expression 'buf' is of type: cstring
3353
template `[]`(s: string; i: int): char
34-
first type mismatch at position: 0
54+
first type mismatch at position: 1
55+
required type for s: string
56+
but expression 'buf' is of type: cstring
3557
36-
expression: `[]`(buf, pos)
37-
t10735.nim(44, 9) Error: expression '' has no type (or is ambiguous)
38-
t10735.nim(46, 3) Error: illformed AST: case buf[pos]
58+
expression: buf[pos]
59+
t10735.nim(66, 9) Error: expression '' has no type (or is ambiguous)
60+
t10735.nim(68, 3) Error: illformed AST: case buf[pos]
3961
'''
4062
joinable: false
4163
"""

tests/errmsgs/t22753.nim

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,50 @@ cmd: "nim check --hints:off $file"
33
errormsg: "type mismatch"
44
nimoutFull: true
55
nimout: '''
6-
t22753.nim(34, 13) Error: array expects two type parameters
7-
t22753.nim(35, 1) Error: expression 'x' has no type (or is ambiguous)
8-
t22753.nim(35, 1) Error: expression 'x' has no type (or is ambiguous)
9-
t22753.nim(35, 2) Error: type mismatch: got <>
6+
t22753.nim(51, 13) Error: array expects two type parameters
7+
t22753.nim(52, 1) Error: expression 'x' has no type (or is ambiguous)
8+
t22753.nim(52, 1) Error: expression 'x' has no type (or is ambiguous)
9+
t22753.nim(52, 2) Error: type mismatch: got <>
1010
but expected one of:
1111
proc `[]=`(s: var string; i: BackwardsIndex; x: char)
12-
first type mismatch at position: 0
12+
first type mismatch at position: 2
13+
required type for i: BackwardsIndex
14+
but expression '0' is of type: int literal(0)
1315
proc `[]=`[I: Ordinal; T, S](a: T; i: I; x: sink S)
1416
first type mismatch at position: 0
1517
proc `[]=`[Idx, T; U, V: Ordinal](a: var array[Idx, T]; x: HSlice[U, V];
1618
b: openArray[T])
17-
first type mismatch at position: 0
19+
first type mismatch at position: 2
20+
required type for x: HSlice[[]=.U, []=.V]
21+
but expression '0' is of type: int literal(0)
1822
proc `[]=`[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T)
19-
first type mismatch at position: 0
23+
first type mismatch at position: 2
24+
required type for i: BackwardsIndex
25+
but expression '0' is of type: int literal(0)
2026
proc `[]=`[T, U: Ordinal](s: var string; x: HSlice[T, U]; b: string)
21-
first type mismatch at position: 0
27+
first type mismatch at position: 2
28+
required type for x: HSlice[[]=.T, []=.U]
29+
but expression '0' is of type: int literal(0)
2230
proc `[]=`[T; U, V: Ordinal](s: var seq[T]; x: HSlice[U, V]; b: openArray[T])
23-
first type mismatch at position: 0
31+
first type mismatch at position: 2
32+
required type for x: HSlice[[]=.U, []=.V]
33+
but expression '0' is of type: int literal(0)
2434
proc `[]=`[T](s: var openArray[T]; i: BackwardsIndex; x: T)
25-
first type mismatch at position: 0
35+
first type mismatch at position: 2
36+
required type for i: BackwardsIndex
37+
but expression '0' is of type: int literal(0)
2638
template `[]=`(a: WideCStringObj; idx: int; val: Utf16Char)
27-
first type mismatch at position: 0
39+
first type mismatch at position: 3
40+
required type for val: Utf16Char
41+
but expression '9' is of type: int literal(9)
2842
template `[]=`(s: string; i: int; val: char)
29-
first type mismatch at position: 0
43+
first type mismatch at position: 3
44+
required type for val: char
45+
but expression '9' is of type: int literal(9)
3046
31-
expression: `[]=`(x, 0, 9)
47+
expression: x[0] = 9
3248
'''
3349
"""
50+
3451
var x: array[3] # bug #22753
35-
x[0] = 9
52+
x[0] = 9

tests/errmsgs/tsubscriptmismatch.nim

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
discard """
2+
matrix: "-d:testsConciseTypeMismatch"
3+
nimout: '''
4+
[1] proc `[]`[T; U, V: Ordinal](s: openArray[T]; x: HSlice[U, V]): seq[T]
5+
'''
6+
"""
7+
8+
type Foo = object
9+
let x = Foo()
10+
discard x[1] #[tt.Error
11+
^ type mismatch]#
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
discard """
2+
nimout: '''
3+
but expression 'x' is of type: Foo
4+
'''
5+
"""
6+
7+
type Foo = object
8+
let x = Foo()
9+
discard x[1] #[tt.Error
10+
^ type mismatch: got <Foo, int literal(1)>]#

0 commit comments

Comments
 (0)