clarify the meaning of the 'auto' metatype; 'auto' is now bind-multiple; fixes #3224

This commit is contained in:
Araq
2015-09-14 20:25:52 +02:00
parent f79ec6cdf5
commit 0aa908c86c
7 changed files with 91 additions and 55 deletions

View File

@@ -718,12 +718,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if paramType == nil: return # (e.g. proc return type)
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
let finalTypId = if typId != nil: typId
else: getIdent(paramName & ":type")
if genericParams == nil:
# This happens with anonymous proc types appearing in signatures
# XXX: we need to lift these earlier
return
let finalTypId = if typId != nil: typId
else: getIdent(paramName & ":type")
# is this a bindOnce type class already present in the param list?
for i in countup(0, genericParams.len - 1):
if genericParams.sons[i].sym.name.id == finalTypId.id:
@@ -757,7 +757,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
case paramType.kind:
of tyAnything:
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
of tyStatic:
# proc(a: expr{string}, b: expr{nkLambda})
@@ -868,6 +868,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyExpr:
if procKind notin {skMacro, skTemplate}:
result = addImplicitGeneric(newTypeS(tyAnything, c))
#result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
of tyGenericParam:
markUsed(info, paramType.sym)
@@ -977,7 +978,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
# compiler only checks for 'nil':
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
# 'auto' as a return type does not imply a generic:
if r.kind != tyExpr:
if r.kind == tyAnything:
# 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
# compiler is hardly aware of 'auto':
r = newTypeS(tyExpr, c)
elif r.kind != tyExpr:
if r.sym == nil or sfAnon notin r.sym.flags:
let lifted = liftParamType(c, kind, genericParams, r, "result",
n.sons[0].info)
@@ -1346,8 +1351,11 @@ proc processMagicType(c: PContext, m: PSym) =
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
of mNil: setMagicType(m, tyNil, ptrSize)
of mExpr:
setMagicType(m, tyExpr, 0)
if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
if m.name.s == "auto":
setMagicType(m, tyAnything, 0)
else:
setMagicType(m, tyExpr, 0)
if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
of mStmt:
setMagicType(m, tyStmt, 0)
if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt

View File

@@ -116,7 +116,7 @@ type class matches
``array`` any array type
``set`` any set type
``seq`` any seq type
``auto`` any type
``any`` any type
================== ===================================================
Furthermore, every generic type automatically creates a type class of the same
@@ -163,15 +163,6 @@ module to illustrate this:
Alternatively, the ``distinct`` type modifier can be applied to the type class
to allow each param matching the type class to bind to a different type.
If a proc param doesn't have a type specified, Nim will use the
``distinct auto`` type class (also known as ``any``). Note this behavior is
deprecated for procs; templates, however, support them:
.. code-block:: nim
# allow any combination of param types
proc concat(a, b): string = $a & $b # deprecated
proc concat(a, b: any): string = $a & $b # preferred
Procs written with the implicitly generic style will often need to refer to the
type parameters of the matched generic type. They can be easily accessed using
the dot syntax:

View File

@@ -1228,3 +1228,27 @@ However, a ``void`` type cannot be inferred in generic code:
The ``void`` type is only valid for parameters and return types; other symbols
cannot have the type ``void``.
Auto type
---------
The ``auto`` type can only be used for return types and parameters. For return
types it causes the compiler to infer the type from the routine body:
.. code-block:: nim
proc returnsInt(): auto = 1984
For parameters it currently creates implicitly generic routines:
.. code-block:: nim
proc foo(a, b: auto) = discard
Is the same as:
.. code-block:: nim
proc foo[T1, T2](a: T1, b: T2) = discard
However later versions of the language might change this to mean "infer the
parameters' types from the body". Then the above ``foo`` would be rejected as
the parameters' types can not be infered from an empty ``discard`` statement.

View File

@@ -78,7 +78,7 @@ type
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
void* {.magic: "VoidType".} ## meta type to denote the absence of any type
auto* = expr ## meta type for automatic type determination
auto* {.magic: Expr.} ## meta type for automatic type determination
any* = distinct auto ## meta type for any supported type
untyped* {.magic: Expr.} ## meta type to denote an expression that
## is not resolved (for templates)
@@ -104,7 +104,7 @@ type
SomeNumber* = SomeInteger|SomeReal
## type class matching all number types
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
## Special compile-time procedure that checks whether `x` is
## defined.
## `x` is an external symbol introduced through the compiler's
@@ -125,7 +125,7 @@ when defined(nimalias):
TNumber: SomeNumber,
TOrdinal: SomeOrdinal].}
proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
proc declared*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
## Special compile-time procedure that checks whether `x` is
## declared. `x` has to be an identifier or a qualified identifier.
## This can be used to check whether a library provides a certain
@@ -140,11 +140,11 @@ when defined(useNimRtl):
{.deadCodeElim: on.}
proc definedInScope*(x: expr): bool {.
magic: "DefinedInScope", noSideEffect, deprecated.}
magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
proc declaredInScope*(x: expr): bool {.
magic: "DefinedInScope", noSideEffect.}
magic: "DefinedInScope", noSideEffect, compileTime.}
## Special compile-time procedure that checks whether `x` is
## declared in the current scope. `x` has to be an identifier.
@@ -160,7 +160,7 @@ proc unsafeAddr*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
## Cannot be overloaded.
discard
proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect.} =
proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} =
## Builtin 'type' operator for accessing the type of an expression.
## Cannot be overloaded.
discard
@@ -3392,7 +3392,7 @@ when hasAlloc:
x[j+i] = item[j]
inc(j)
proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect, compileTime.} =
## Special compile-time procedure that checks whether `x` can be compiled
## without any semantic error.
## This can be used to check whether a type supports some operation:
@@ -3456,7 +3456,7 @@ when hasAlloc and not defined(nimscript) and not defined(JS):
include "system/deepcopy"
proc procCall*(x: expr) {.magic: "ProcCall".} =
proc procCall*(x: expr) {.magic: "ProcCall", compileTime.} =
## special magic to prohibit dynamic binding for `method`:idx: calls.
## This is similar to `super`:idx: in ordinary OO languages.
##

View File

@@ -7,7 +7,7 @@ type
proc getTypeName(t: typedesc): string = t.name
proc foo(T: typedesc[float], a: expr): string =
proc foo(T: typedesc[float], a: auto): string =
result = "float " & $(a.len > 5)
proc foo(T: typedesc[TFoo], a: int): string =

View File

@@ -0,0 +1,20 @@
discard """
output: '''10
10.0
1.0hiho'''
"""
# bug #3224
proc f(x: auto): auto =
result = $(x+10)
proc f(x, y: auto): auto =
result = $(x+y)
echo f(0) # prints 10
echo f(0.0) # prints 10.0
proc `+`(a, b: string): string = a & b
echo f(0.7, 0.3), f("hi", "ho")

View File

@@ -3,7 +3,7 @@ News
====
..
2015-05-05 Version 0.11.4 released
2015-09-14 Version 0.11.4 released
==================================
Changes affecting backwards compatibility
@@ -58,7 +58,7 @@ News
of all the DLLs the standard library needs. This means that the following
DLLs are now split into 32 and 64 versions:
* ``prce.dll``: Split into ``prce32.dll`` and ``prce64.dll``.
* ``pcre.dll``: Split into ``pcre32.dll`` and ``pcre64.dll``.
* ``pdcurses.dll``: Split into ``pdcurses32.dll`` and ``pdcurses64.dll``.
* ``sqlite3.dll``: Split into ``sqlite3_32.dll`` and ``sqlite3_64.dll``.
* ``ssleay32.dll``: Split into ``ssleay32.dll`` and ``ssleay64.dll``.
@@ -75,6 +75,13 @@ News
with Unix's ``#!``.
- An implicit return type for an iterator is now deprecated. Use ``auto`` if
you want more type inference.
- The type ``auto`` is now a "multi-bind" metatype, so the following compiles:
.. code-block:: nim
proc f(x, y: auto): auto =
result = $x & y
echo f(0, "abc")
Library Additions
@@ -116,24 +123,20 @@ News
- ``when nimvm`` can now be used for compiletime versions of some code
sections. Click `here <docs/manual.html#when-nimvm-statement>`_ for details.
- Usage of the type ``NimNode`` in a proc now implicitly annotates the proc
with ``.compileTime``. This means generics work much better
for ``NimNode``.
with ``.compileTime``. This means generics work much better for ``NimNode``.
Bugfixes
--------
- Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with
it(Child), where Child = object of Base"
- Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with it(Child), where Child = object of Base"
(`#2662 <https://github.com/Araq/Nim/issues/2662>`_)
- Fixed "repr() misses base object field in 2nd level derived object"
(`#2749 <https://github.com/Araq/Nim/issues/2749>`_)
- Fixed "nimsuggest doesn't work more than once on the non-main file"
(`#2694 <https://github.com/Araq/Nim/issues/2694>`_)
- Fixed "JS Codegen. Passing arguments by var in certain cases leads to invali
d JS."
- Fixed "JS Codegen. Passing arguments by var in certain cases leads to invalid JS."
(`#2798 <https://github.com/Araq/Nim/issues/2798>`_)
- Fixed ""check" proc in unittest.nim prevents the propagation of changes to v
ar parameters."
- Fixed ""check" proc in unittest.nim prevents the propagation of changes to var parameters."
(`#964 <https://github.com/Araq/Nim/issues/964>`_)
- Fixed "Excessive letters in integer literals are not an error"
(`#2523 <https://github.com/Araq/Nim/issues/2523>`_)
@@ -147,8 +150,7 @@ ar parameters."
(`#2687 <https://github.com/Araq/Nim/issues/2687>`_)
- Fixed "Compile error using object in const array"
(`#2774 <https://github.com/Araq/Nim/issues/2774>`_)
- Fixed "httpclient async requests with method httpPOST isn't sending Content-
Length header"
- Fixed "httpclient async requests with method httpPOST isn't sending Content-Length header"
(`#2884 <https://github.com/Araq/Nim/issues/2884>`_)
- Fixed "Streams module not working with JS backend"
(`#2148 <https://github.com/Araq/Nim/issues/2148>`_)
@@ -179,8 +181,7 @@ Length header"
(`#2974 <https://github.com/Araq/Nim/issues/2974>`_)
- Fixed "repr is broken"
(`#2992 <https://github.com/Araq/Nim/issues/2992>`_)
- Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a defau
lt"
- Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default"
(`#2976 <https://github.com/Araq/Nim/issues/2976>`_)
- Fixed "Compilation broken on windows"
(`#2996 <https://github.com/Araq/Nim/issues/2996>`_)
@@ -190,8 +191,7 @@ lt"
(`#2672 <https://github.com/Araq/Nim/issues/2672>`_)
- Fixed "Uncatched exception in async procedure on raise statement"
(`#3014 <https://github.com/Araq/Nim/issues/3014>`_)
- Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #18
98)"
- Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #1898)"
(`#3005 <https://github.com/Araq/Nim/issues/3005>`_)
- Fixed "IndexError when rebuilding Nim on iteration 2"
(`#3018 <https://github.com/Araq/Nim/issues/3018>`_)
@@ -239,8 +239,7 @@ lt"
(`#3054 <https://github.com/Araq/Nim/issues/3054>`_)
- Fixed "Wrong sharing of static_t instantations"
(`#3112 <https://github.com/Araq/Nim/issues/3112>`_)
- Fixed "Automatically generated proc conflicts with user-defined proc when .e
xportc.'ed"
- Fixed "Automatically generated proc conflicts with user-defined proc when .exportc.'ed"
(`#3134 <https://github.com/Araq/Nim/issues/3134>`_)
- Fixed "getTypeInfo call crashes nim"
(`#3099 <https://github.com/Araq/Nim/issues/3099>`_)
@@ -260,15 +259,13 @@ xportc.'ed"
(`#3149 <https://github.com/Araq/Nim/issues/3149>`_)
- Fixed "Inference of `static[T]` in sequences"
(`#3144 <https://github.com/Araq/Nim/issues/3144>`_)
- Fixed "Argument named "closure" to proc inside template interfere with closu
re pragma"
- Fixed "Argument named "closure" to proc inside template interfere with closure pragma"
(`#3171 <https://github.com/Araq/Nim/issues/3171>`_)
- Fixed "Internal error with aliasing inside template"
(`#3158 <https://github.com/Araq/Nim/issues/3158>`_)
- Fixed "Cardinality of sets prints unexpected value"
(`#3135 <https://github.com/Araq/Nim/issues/3135>`_)
- Fixed "Nim crashes on const assignment from function returning var ref objec
t"
- Fixed "Nim crashes on const assignment from function returning var ref object"
(`#3103 <https://github.com/Araq/Nim/issues/3103>`_)
- Fixed "`repr` cstring"
(`#3080 <https://github.com/Araq/Nim/issues/3080>`_)
@@ -276,8 +273,7 @@ t"
(`#3052 <https://github.com/Araq/Nim/issues/3052>`_)
- Fixed "Compiler assertion when evaluating template with static[T]"
(`#1858 <https://github.com/Araq/Nim/issues/1858>`_)
- Fixed "Erroneous overflow in iterators when compiler built with overflowChec
ks enabled"
- Fixed "Erroneous overflow in iterators when compiler built with overflowChecks enabled"
(`#3140 <https://github.com/Araq/Nim/issues/3140>`_)
- Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
(`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
@@ -289,8 +285,7 @@ ks enabled"
(`#3193 <https://github.com/Araq/Nim/issues/3193>`_)
- Fixed "VM crash when accessing array's element"
(`#3192 <https://github.com/Araq/Nim/issues/3192>`_)
- Fixed "Unexpected proc invoked when different modules add procs to a type fr
om a 3rd module"
- Fixed "Unexpected proc invoked when different modules add procs to a type from a 3rd module"
(`#2664 <https://github.com/Araq/Nim/issues/2664>`_)
- Fixed "Nim crashes on conditional declaration inside a template"
(`#2670 <https://github.com/Araq/Nim/issues/2670>`_)
@@ -298,8 +293,7 @@ om a 3rd module"
(`#2752 <https://github.com/Araq/Nim/issues/2752>`_)
- Fixed "VM: Cannot assign int value to ref variable"
(`#1329 <https://github.com/Araq/Nim/issues/1329>`_)
- Fixed "Incorrect code generated for tagged unions with enums not starting at
zero"
- Fixed "Incorrect code generated for tagged unions with enums not starting at zero"
(`#3096 <https://github.com/Araq/Nim/issues/3096>`_)
- Fixed "Compile time procs using forward declarations are silently ignored"
(`#3066 <https://github.com/Araq/Nim/issues/3066>`_)
@@ -307,8 +301,7 @@ om a 3rd module"
(`#1965 <https://github.com/Araq/Nim/issues/1965>`_)
- Fixed "os.getCreationTime is incorrect/impossible on Posix systems"
(`#1058 <https://github.com/Araq/Nim/issues/1058>`_)
- Fixed "Improve error message for osproc.startProcess when command does not e
xist"
- Fixed "Improve error message for osproc.startProcess when command does not exist"
(`#2183 <https://github.com/Araq/Nim/issues/2183>`_)
- Fixed "gctest segfaults with --gc:markandsweep on x86_64"
(`#2305 <https://github.com/Araq/Nim/issues/2305>`_)