From ecf9efa3977f95aed5229ab79cd6ac4799a32a4c Mon Sep 17 00:00:00 2001 From: metagn Date: Thu, 30 Mar 2023 16:34:42 +0300 Subject: [PATCH] document general use of `_`, error message, fixes (#21584) * document general use of `_`, error message, fixes fixes #20687, fixes #21435 Documentation and changelog updated to clarify new universal behavior of `_`. Also new error message for attempting to use `_`, new tests, and fixes with overloadable symbols and implicit generics. * add test for #21435 --- changelogs/changelog_2_0_0.md | 36 +++++++++++++------ compiler/lookups.nim | 27 ++++++++------ compiler/semtypes.nim | 13 ++++--- doc/manual.md | 13 +++++++ tests/proc/tunderscoreparam.nim | 13 +++++++ .../tforloop_tuple_multiple_underscore.nim | 4 +-- tests/stmt/tforloop_tuple_underscore.nim | 2 +- tests/stmt/tforloop_underscore.nim | 2 +- tests/stmt/tgenericsunderscore.nim | 4 +++ tests/stmt/tmiscunderscore.nim | 15 ++++++++ tests/template/tunderscore1.nim | 2 +- 11 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 tests/stmt/tgenericsunderscore.nim create mode 100644 tests/stmt/tmiscunderscore.nim diff --git a/changelogs/changelog_2_0_0.md b/changelogs/changelog_2_0_0.md index 19d97b7690..a82ce149bf 100644 --- a/changelogs/changelog_2_0_0.md +++ b/changelogs/changelog_2_0_0.md @@ -135,26 +135,42 @@ - The experimental strictFuncs feature now disallows a store to the heap via a `ref` or `ptr` indirection. -- Underscores (`_`) as routine parameters are now ignored and cannot be used in the routine body. - The following code now does not compile: +- The underscore identifier (`_`) is now generally not added to scope when + used as the name of a definition. While this was already the case for + variables, it is now also the case for routine parameters, generic + parameters, routine declarations, type declarations, etc. This means that the following code now does not compile: ```nim proc foo(_: int): int = _ + 1 echo foo(1) + + proc foo[_](t: typedesc[_]): seq[_] = @[default(_)] + echo foo[int]() + + proc _() = echo "_" + _() + + type _ = int + let x: _ = 3 ``` - Instead, the following code now compiles: + Whereas the following code now compiles: ```nim proc foo(_, _: int): int = 123 echo foo(1, 2) - ``` -- Underscores (`_`) as generic parameters are not supported and cannot be used. - Generics that use `_` as parameters will no longer compile requires you to replace `_` with something else: - - ```nim - proc foo[_](t: typedesc[_]): string = "BAR" # Can not compile - proc foo[T](t: typedesc[T]): string = "BAR" # Can compile + + proc foo[_, _](): int = 123 + echo foo[int, bool]() + + proc foo[T, U](_: typedesc[T], _: typedesc[U]): (T, U) = (default(T), default(U)) + echo foo(int, bool) + + proc _() = echo "one" + proc _() = echo "two" + + type _ = int + type _ = float ``` - - Added the `--legacy:verboseTypeMismatch` switch to get legacy type mismatch error messages. diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 3f028a52f1..fc84b90513 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -396,11 +396,12 @@ proc addOverloadableSymAt*(c: PContext; scope: PScope, fn: PSym) = if fn.kind notin OverloadableSyms: internalError(c.config, fn.info, "addOverloadableSymAt") return - let check = strTableGet(scope.symbols, fn.name) - if check != nil and check.kind notin OverloadableSyms: - wrongRedefinition(c, fn.info, fn.name.s, check.info) - else: - scope.addSym(fn) + if fn.name.s != "_": + let check = strTableGet(scope.symbols, fn.name) + if check != nil and check.kind notin OverloadableSyms: + wrongRedefinition(c, fn.info, fn.name.s, check.info) + else: + scope.addSym(fn) proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) = ## adds an overloadable symbol on the scope and the interface if appropriate @@ -546,12 +547,16 @@ proc errorUseQualifier*(c: PContext; info:TLineInfo; choices: PNode) = errorUseQualifier(c, info, candidates, prefix) proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string, extra = "") = - var err = "undeclared identifier: '" & name & "'" & extra - if c.recursiveDep.len > 0: - err.add "\nThis might be caused by a recursive module dependency:\n" - err.add c.recursiveDep - # prevent excessive errors for 'nim check' - c.recursiveDep = "" + var err: string + if name == "_": + err = "the special identifier '_' is ignored in declarations and cannot be used" + else: + err = "undeclared identifier: '" & name & "'" & extra + if c.recursiveDep.len > 0: + err.add "\nThis might be caused by a recursive module dependency:\n" + err.add c.recursiveDep + # prevent excessive errors for 'nim check' + c.recursiveDep = "" localError(c.config, info, errGenerated, err) proc errorUndeclaredIdentifierHint*(c: PContext; n: PNode, ident: PIdent): PSym = diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 2f485d65bb..fbba4f36f2 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1359,6 +1359,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, for j in 0..