summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-09-05 01:17:03 +0200
committerAraq <rumpf_a@web.de>2014-09-05 01:17:03 +0200
commitbd4e2294640c634027f7a15d2a07eea21808dc61 (patch)
tree98d1f66e53ac305e1fbc249da4c65e19bb10789a
parentbf557a7cdb8f31aabca17d5b147a90ec155eaf23 (diff)
parent7d5e387a488200113664a3ffa60e5c63ec32c54b (diff)
downloadNim-bd4e2294640c634027f7a15d2a07eea21808dc61.tar.gz
Merge branch 'bigbreak' of https://github.com/Araq/Nimrod into bigbreak
-rw-r--r--compiler/semstmts.nim11
-rw-r--r--compiler/semtypinst.nim8
-rw-r--r--compiler/types.nim4
-rw-r--r--doc/manual.txt11
-rw-r--r--tests/metatype/typeclassinference.nim11
5 files changed, 36 insertions, 9 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 28d062392..93a1994a7 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -350,9 +350,14 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
     var def: PNode
     if a.sons[length-1].kind != nkEmpty:
       def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
-      # BUGFIX: ``fitNode`` is needed here!
-      # check type compability between def.typ and typ:
-      if typ != nil: def = fitNode(c, typ, def)
+      if typ != nil:
+        if typ.isMetaType:
+          def = inferWithMetaType(c, typ, def)
+          typ = def.typ
+        else:
+          # BUGFIX: ``fitNode`` is needed here!
+          # check type compability between def.typ and typ        
+          def = fitNode(c, typ, def)
       else:
         typ = skipIntLit(def.typ)
         if typ.kind in {tySequence, tyArray, tySet} and
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 9484bbe90..4563dc8d4 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -216,12 +216,16 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
     result.typ = replaceTypeVarsT(cl, s.typ)
     result.ast = replaceTypeVarsN(cl, s.ast)
     
-proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
+proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
     if cl.allowMetaTypes or tfRetType in t.flags: return
     localError(t.sym.info, errCannotInstantiateX, typeToString(t))
     result = errorType(cl.c)
+    # In order to prevent endless recursions, we must remember
+    # this bad lookup and replace it with errorType everywhere.
+    # These code paths are only active in nimrod check
+    idTablePut(cl.typeMap, t, result)
   elif result.kind == tyGenericParam and not cl.allowMetaTypes:
     internalError(cl.info, "substitution with generic parameter")
 
@@ -353,7 +357,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
 
   of tyGenericBody:
     localError(cl.info, errCannotInstantiateX, typeToString(t))
-    result = t
+    result = errorType(cl.c)
     #result = replaceTypeVarsT(cl, lastSon(t))
 
   of tyFromExpr:
diff --git a/compiler/types.nim b/compiler/types.nim
index adc03a13e..7b59fbf20 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -913,9 +913,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
           result = sameTypeAux(a.sons[0], b.sons[0], c)     
     else: 
       result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b)
-  of tyEnum, tyForward, tyProxy:
+  of tyEnum, tyForward:
     # XXX generic enums do not make much sense, but require structural checking
     result = a.id == b.id and sameFlags(a, b)
+  of tyError:
+    result = b.kind == tyError
   of tyTuple:
     cycleCheck()
     result = sameTuple(a, b, c) and sameFlags(a, b)
diff --git a/doc/manual.txt b/doc/manual.txt
index 10fe78336..144a3b2c0 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -3671,8 +3671,8 @@ once for each tested type and any static code included within them will also be
 executed once.
 
 
-Return Type Inference
----------------------
+Type inference with type classes
+--------------------------------
 
 If a type class is used as the return type of a proc and it won't be bound to
 a concrete type by some of the proc params, Nim will infer the return type
@@ -3681,13 +3681,18 @@ from the proc body. This is usually used with the ``auto`` type class:
 .. code-block:: nim
   proc makePair(a, b): auto = (first: a, second: b)
 
-The return type will be treated as additional generic param and can be
+The return type will be treated as an additional generic param and can be
 explicitly specified at call sites as any other generic param.
 
 Future versions of Nim may also support overloading based on the return type
 of the overloads. In such settings, the expected result type at call sites may 
 also influence the inferred return type.
 
+Likewise, if a type class is used in another position where Nim expects a
+concrete type (e.g. a variable declaration or a type coercion), Nim will try to
+infer the concrete type by applying the sane matching algorithm also used in
+overload resolution.
+
 
 Symbol lookup in generics
 -------------------------
diff --git a/tests/metatype/typeclassinference.nim b/tests/metatype/typeclassinference.nim
index 72b5aca96..2ac037ac5 100644
--- a/tests/metatype/typeclassinference.nim
+++ b/tests/metatype/typeclassinference.nim
@@ -1,3 +1,8 @@
+discard """
+  errormsg: "type mismatch: got (string) but expected 'ptr'"
+  line: 20
+"""
+
 import typetraits
 
 type
@@ -8,3 +13,9 @@ var x = Vec([1, 2, 3])
 static:
   assert x.type.name == "Vec[static[int](3), int]"
 
+var str1: string = "hello, world!"
+var ptr1: ptr = addr(str1)
+
+var str2: string = "hello, world!"
+var ptr2: ptr = str2
+