diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-07-18 12:16:54 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2016-07-18 12:16:54 +0200 |
commit | d779a9b722f432fff25de9ddb97f57b5179eaaef (patch) | |
tree | 8111008de19cd6607c1c195e30871d88874514b9 | |
parent | 55db59a897b0c61303b65c7af4d8ef9b110861ef (diff) | |
download | Nim-d779a9b722f432fff25de9ddb97f57b5179eaaef.tar.gz |
fixes #4478
-rw-r--r-- | compiler/sigmatch.nim | 39 | ||||
-rw-r--r-- | tests/typerel/tgeneric_subtype_regression.nim | 19 |
2 files changed, 49 insertions, 9 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 7c57936eb..a3b9de5f4 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -364,22 +364,43 @@ proc isObjectSubtype(a, f: PType): int = if t != nil: result = depth -proc skipToGenericBody(t: PType): PType = +type + SkippedPtr = enum skippedNone, skippedRef, skippedPtr + +proc skipToGenericBody(t: PType; skipped: var SkippedPtr): PType = var r = t + # we're allowed to skip one level of ptr/ref: + var ptrs = 0 while r != nil: - if r.kind in {tyGenericInst, tyGenericInvocation}: - return r.sons[0] - r = if r.len > 0: r.lastSon else: nil + case r.kind + of tyGenericInst, tyGenericInvocation: + result = r.sons[0] + break + of tyRef: + inc ptrs + skipped = skippedRef + r = r.lastSon + of tyPtr: + inc ptrs + skipped = skippedPtr + r = r.lastSon + of tyGenericBody: + r = r.lastSon + else: + break + if ptrs > 1: result = nil proc isGenericSubtype(a, f: PType, d: var int): bool = assert f.kind in {tyGenericInst, tyGenericInvocation, tyGenericBody} - var t = if a.kind == tyGenericBody: a else: a.skipToGenericBody - var r = if f.kind == tyGenericBody: f else: f.skipToGenericBody + var askip = skippedNone + var fskip = skippedNone + var t = if a.kind == tyGenericBody: a else: a.skipToGenericBody(askip) + var r = if f.kind == tyGenericBody: f else: f.skipToGenericBody(fskip) var depth = 0 - while t != nil and not sameObjectTypes(r, t): - t = t.skipToGenericBody + while t != nil and not sameObjectTypes(r, t) and askip == fskip: + t = t.skipToGenericBody(askip) inc depth - if t != nil: + if t != nil and askip == fskip: d = depth result = true diff --git a/tests/typerel/tgeneric_subtype_regression.nim b/tests/typerel/tgeneric_subtype_regression.nim new file mode 100644 index 000000000..e279c0ad4 --- /dev/null +++ b/tests/typerel/tgeneric_subtype_regression.nim @@ -0,0 +1,19 @@ +discard """ + errormsg: "type mismatch: got (FooRef[system.string])" + line: 15 +""" + +# bug #4478 + +type + Foo[T] = object + FooRef[T] = ref Foo[T] + +proc takeFoo[T](foo: Foo[T]): int = discard + +proc g(x: FooRef[string]) = + echo x.takeFoo() != 8 + +var x: FooRef[string] + +g(x) |