diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-05-24 18:33:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-24 18:33:53 +0200 |
commit | ef8ddef47b6ea10c6e5e504165245ab514391056 (patch) | |
tree | aa1d68dfd81bef608f033af9b25daba96e97e613 | |
parent | d67a9f024eeeb2bc26fb38a98be9a53956003290 (diff) | |
download | Nim-ef8ddef47b6ea10c6e5e504165245ab514391056.tar.gz |
fixes #10912 (#11317)
* fixes #10912 * update the tutorial examples
-rw-r--r-- | compiler/cgmeth.nim | 6 | ||||
-rw-r--r-- | doc/tut2.rst | 6 | ||||
-rw-r--r-- | tests/method/tsingle_methods.nim | 48 |
3 files changed, 54 insertions, 6 deletions
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index db548ccc9..ab406bc4b 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -56,7 +56,7 @@ proc methodCall*(n: PNode; conf: ConfigRef): PNode = type MethodResult = enum No, Invalid, Yes -proc sameMethodBucket(a, b: PSym): MethodResult = +proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult = if a.name.id != b.name.id: return if sonsLen(a.typ) != sonsLen(b.typ): return @@ -75,7 +75,7 @@ proc sameMethodBucket(a, b: PSym): MethodResult = if sameType(a.typ.sons[i], b.typ.sons[i]): if aa.kind == tyObject and result != Invalid: result = Yes - elif aa.kind == tyObject and bb.kind == tyObject: + elif aa.kind == tyObject and bb.kind == tyObject and (i == 1 or multiMethods): let diff = inheritanceDiff(bb, aa) if diff < 0: if result != Invalid: @@ -162,7 +162,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = var witness: PSym for i in 0 ..< L: let disp = g.methods[i].dispatcher - case sameMethodBucket(disp, s) + case sameMethodBucket(disp, s, multimethods = optMultiMethods in g.config.globalOptions) of Yes: add(g.methods[i].methods, s) attachDispatcher(s, disp.ast[dispatcherPos]) diff --git a/doc/tut2.rst b/doc/tut2.rst index fda953eda..44b76f5ac 100644 --- a/doc/tut2.rst +++ b/doc/tut2.rst @@ -277,7 +277,7 @@ Procedures always use static dispatch. For dynamic dispatch replace the a, b: Expression # watch out: 'eval' relies on dynamic binding - method eval(e: Expression): int = + method eval(e: Expression): int {.base.} = # override this base method quit "to override!" @@ -300,7 +300,7 @@ In a multi-method all parameters that have an object type are used for the dispatching: .. code-block:: nim - :test: "nim c $1" + :test: "nim c --multiMethods:on $1" type Thing = ref object of RootObj @@ -611,7 +611,7 @@ To pass a block of statements to a template, use 'untyped' for the last paramete :test: "nim c $1" template withFile(f: untyped, filename: string, mode: FileMode, - body: untyped): typed = + body: untyped) = let fn = filename var f: File if open(f, fn, mode): diff --git a/tests/method/tsingle_methods.nim b/tests/method/tsingle_methods.nim new file mode 100644 index 000000000..40269559a --- /dev/null +++ b/tests/method/tsingle_methods.nim @@ -0,0 +1,48 @@ +discard """ + cmd: "nim c --multimethods:off $file" + output: '''base +base +base +base +base +base +''' +""" + +# bug #10912 + +type + X = ref object of RootObj + +type + A* = ref object of RootObj + B* = ref object of A + C* = ref object of A + D* = ref object of A + E* = ref object of A + F* = ref object of A + +method resolve(self: var X, stmt: A) {.base.} = echo "base" + +proc resolveSeq*(self: var X, statements: seq[A]) = + for statement in statements: + resolve(self, statement) + +method resolve(self: var X, stmt: B) = + echo "B" + +method resolve(self: var X, stmt: D) = + echo "D" + +method resolve(self: var X, stmt: E) = + echo "E" + +method resolve(self: var X, stmt: C) = + echo "C" + +method resolve(self: var X, stmt: F) = + echo "F" + +var x = X() +var a = @[A(), B(), C(), D(), E(), F()] +resolveSeq(x, a) |