mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-29 10:01:39 +00:00
better errors for standalone explicit generic instantiations (#24276)
refs #8064, refs #24010
Error messages for standalone explicit generic instantiations are
revamped. Failing standalone explicit generic instantiations now only
error after overloading has finished and resolved to the default `[]`
magic (this means `[]` can now be overloaded for procs but this isn't
necessarily intentional, in #24010 it was documented that it isn't
possible). The error messages for failed instantiations are also no
longer a simple `cannot instantiate: foo` message, instead they now give
the same type mismatch error message as overloads with mismatching
explicit generic parameters.
This is now possible due to the changes in #24010 that delegate all
explicit generic proc instantiations to overload resolution. Old code
that worked around this is now removed. `maybeInstantiateGeneric` could
maybe also be removed in favor of just `explicitGenericSym`, the `result
== n` case is due to `explicitGenericInstError` which is only for niche
cases.
Also, to cause "ambiguous identifier" error messages when the explicit
instantiation is a symchoice and the expression context doesn't allow
symchoices, we semcheck the sym/symchoice created by
`explicitGenericSym` with the given expression flags.
#8064 isn't entirely fixed because the error message is still misleading
for the original case which does `values[1]`, as a consequence of
#12664.
(cherry picked from commit 0a058a6b8f)
This commit is contained in:
@@ -1724,27 +1724,15 @@ proc semDeref(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else: result = nil
|
||||
#GlobalError(n[0].info, errCircumNeedsPointer)
|
||||
|
||||
proc maybeInstantiateGeneric(c: PContext, n: PNode, s: PSym): PNode =
|
||||
## Instantiates generic if not lacking implicit generics,
|
||||
## otherwise returns n.
|
||||
let
|
||||
neededGenParams = s.ast[genericParamsPos].len
|
||||
heldGenParams = n.len - 1
|
||||
var implicitParams = 0
|
||||
for x in s.ast[genericParamsPos]:
|
||||
if tfImplicitTypeParam in x.typ.flags:
|
||||
inc implicitParams
|
||||
if heldGenParams != neededGenParams and implicitParams + heldGenParams == neededGenParams:
|
||||
# This is an implicit + explicit generic procedure without all args passed,
|
||||
# kicking back the sem'd symbol fixes #17212
|
||||
# Uncertain the hackiness of this solution.
|
||||
result = n
|
||||
else:
|
||||
result = explicitGenericInstantiation(c, n, s)
|
||||
if result == n:
|
||||
n[0] = copyTree(result[0])
|
||||
proc maybeInstantiateGeneric(c: PContext, n: PNode, s: PSym, doError: bool): PNode =
|
||||
## Attempts to instantiate generic proc symbol(s) with given parameters.
|
||||
## If instantiation causes errors; if `doError` is `true`, a type mismatch
|
||||
## error is given, otherwise `nil` is returned.
|
||||
result = explicitGenericInstantiation(c, n, s, doError)
|
||||
if result == n:
|
||||
n[0] = copyTree(result[0])
|
||||
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = false): PNode =
|
||||
## returns nil if not a built-in subscript operator; also called for the
|
||||
## checking of assignments
|
||||
result = nil
|
||||
@@ -1768,7 +1756,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.typ() = semStaticType(c, n[1], nil)
|
||||
return
|
||||
elif arr.n != nil:
|
||||
return semSubscript(c, arr.n, flags)
|
||||
return semSubscript(c, arr.n, flags, afterOverloading)
|
||||
else:
|
||||
arr = arr.base
|
||||
|
||||
@@ -1825,7 +1813,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
of skProc, skFunc, skMethod, skConverter, skIterator:
|
||||
# type parameters: partial generic specialization
|
||||
n[0] = semSymGenericInstantiation(c, n[0], s)
|
||||
result = maybeInstantiateGeneric(c, n, s)
|
||||
result = maybeInstantiateGeneric(c, n, s, doError = afterOverloading)
|
||||
if result != nil:
|
||||
# check newly created sym/symchoice
|
||||
result = semExpr(c, result, flags)
|
||||
of skMacro, skTemplate:
|
||||
if efInCall in flags:
|
||||
# We are processing macroOrTmpl[] in macroOrTmpl[](...) call.
|
||||
|
||||
Reference in New Issue
Block a user