summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-09-06 12:25:51 +0300
committerGitHub <noreply@github.com>2024-09-06 11:25:51 +0200
commit4a548deb0886ba7ae7b21a0134ce5becfac7ea5e (patch)
tree14f6c8a6af6043749305ebba5852ba1688458cab /compiler
parentd77ea0783786e863804a1c51186d6811187215f7 (diff)
downloadNim-4a548deb0886ba7ae7b21a0134ce5becfac7ea5e.tar.gz
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.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semcall.nim50
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/semmagic.nim2
3 files changed, 35 insertions, 19 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 5fb61d537..06dd09b69 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -458,23 +458,6 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
       result.add("\n" & errExpectedPosition & "\n" & candidates)
     localError(c.config, n.info, result)
 
-proc bracketNotFoundError(c: PContext; n: PNode) =
-  var errors: CandidateErrors = @[]
-  var o: TOverloadIter = default(TOverloadIter)
-  let headSymbol = n[0]
-  var symx = initOverloadIter(o, c, headSymbol)
-  while symx != nil:
-    if symx.kind in routineKinds:
-      errors.add(CandidateError(sym: symx,
-                                firstMismatch: MismatchInfo(),
-                                diagnostics: @[],
-                                enabled: false))
-    symx = nextOverloadIter(o, c, headSymbol)
-  if errors.len == 0:
-    localError(c.config, n.info, "could not resolve: " & $n)
-  else:
-    notFoundError(c, n, errors)
-
 proc getMsgDiagnostic(c: PContext, flags: TExprFlags, n, f: PNode): string =
   result = ""
   if c.compilesContextId > 0:
@@ -603,6 +586,39 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
         getProcHeader(c.config, alt.calleeSym),
         args])
 
+proc bracketNotFoundError(c: PContext; n: PNode; flags: TExprFlags) =
+  var errors: CandidateErrors = @[]
+  let headSymbol = n[0]
+  block:
+    # we build a closed symchoice of all `[]` overloads for their errors,
+    # except add a custom error for the magics which always match
+    var choice = newNodeIT(nkClosedSymChoice, headSymbol.info, newTypeS(tyNone, c))
+    var o: TOverloadIter = default(TOverloadIter)
+    var symx = initOverloadIter(o, c, headSymbol)
+    while symx != nil:
+      if symx.kind in routineKinds:
+        if symx.magic in {mArrGet, mArrPut}:
+          errors.add(CandidateError(sym: symx,
+                                    firstMismatch: MismatchInfo(),
+                                    diagnostics: @[],
+                                    enabled: false))
+        else:
+          choice.add newSymNode(symx, headSymbol.info)
+      symx = nextOverloadIter(o, c, headSymbol)
+    n[0] = choice
+  # copied from semOverloadedCallAnalyzeEffects, might be overkill:
+  const baseFilter = {skProc, skFunc, skMethod, skConverter, skMacro, skTemplate}
+  let filter =
+    if flags*{efInTypeof, efWantIterator, efWantIterable} != {}:
+      baseFilter + {skIterator}
+    else: baseFilter
+  # this will add the errors:
+  var r = resolveOverloads(c, n, n, filter, flags, errors, true)
+  if errors.len == 0:
+    localError(c.config, n.info, "could not resolve: " & $n)
+  else:
+    notFoundError(c, n, errors)
+
 proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) =
   let a = if a.kind == nkHiddenDeref: a[0] else: a
   if a.kind == nkHiddenCallConv and a[0].kind == nkSym:
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 39121a671..9b255bdf4 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1993,7 +1993,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
       result = buildOverloadedSubscripts(n[0], getIdent(c.cache, "[]="))
       result.add(n[1])
       if mode == noOverloadedSubscript:
-        bracketNotFoundError(c, result)
+        bracketNotFoundError(c, result, {})
         return errorNode(c, n)
       else:
         result = semExprNoType(c, result)
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 1d97f1926..524c9a0ab 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -68,7 +68,7 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
   if result.isNil:
     let x = copyTree(n)
     x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
-    bracketNotFoundError(c, x)
+    bracketNotFoundError(c, x, flags)
     #localError(c.config, n.info, "could not resolve: " & $n)
     result = errorNode(c, n)
 
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381