diff options
author | Jason Beetham <beefers331@gmail.com> | 2022-01-13 09:39:55 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-14 00:39:55 +0800 |
commit | a93f6e7acc9e02deb40a864d345e4c715346a98c (patch) | |
tree | e04b3ef68f3e0651a1c3ed18596f5777a71f251e | |
parent | 9b9ae8a487c6fbf77c8c72196e2b74f3371382b2 (diff) | |
download | Nim-a93f6e7acc9e02deb40a864d345e4c715346a98c.tar.gz |
Generic parameters now can constrain statics in type definitions (#19362)
* Parameters now can constrain static in type definitions resolved regression with generic procedures * Update compiler/sigmatch.nim Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
-rw-r--r-- | compiler/sigmatch.nim | 14 | ||||
-rw-r--r-- | tests/generics/tstatic_constrained.nim | 42 |
2 files changed, 54 insertions, 2 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 93be92676..4d8e03fe9 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1739,11 +1739,22 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, let prev = PType(idTableGet(c.bindings, f)) if prev == nil: if aOrig.kind == tyStatic: - if f.base.kind != tyNone: + if f.base.kind notin {tyNone, tyGenericParam}: result = typeRel(c, f.base, a, flags) if result != isNone and f.n != nil: if not exprStructuralEquivalent(f.n, aOrig.n): result = isNone + elif f.base.kind == tyGenericParam: + # Handling things like `type A[T; Y: static T] = object` + if f.base.len > 0: # There is a constraint, handle it + result = typeRel(c, f.base.lastSon, a, flags) + else: + # No constraint + if tfGenericTypeParam in f.flags: + result = isGeneric + else: + # for things like `proc fun[T](a: static[T])` + result = typeRel(c, f.base, a, flags) else: result = isGeneric if result != isNone: put(c, f, aOrig) @@ -1993,7 +2004,6 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, arg = argSemantized a = a c = m.c - if tfHasStatic in fMaybeStatic.flags: # XXX: When implicit statics are the default # this will be done earlier - we just have to diff --git a/tests/generics/tstatic_constrained.nim b/tests/generics/tstatic_constrained.nim new file mode 100644 index 000000000..07318d1bd --- /dev/null +++ b/tests/generics/tstatic_constrained.nim @@ -0,0 +1,42 @@ +discard """ + cmd: "nim check --hints:off --warnings:off $file" + action: "reject" + nimout:''' +tstatic_constrained.nim(41, 20) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(27, 3)] +got: <typedesc[int], int literal(10)> +but expected: <T: float or string, Y> +tstatic_constrained.nim(41, 20) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(27, 3)] +got: <typedesc[int], int literal(10)> +but expected: <T: float or string, Y> +tstatic_constrained.nim(41, 29) Error: object constructor needs an object type [proxy] +tstatic_constrained.nim(41, 29) Error: expression '' has no type (or is ambiguous) +tstatic_constrained.nim(42, 20) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(27, 3)] +got: <typedesc[byte], uint8> +but expected: <T: float or string, Y> +tstatic_constrained.nim(42, 20) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(27, 3)] +got: <typedesc[byte], uint8> +but expected: <T: float or string, Y> +tstatic_constrained.nim(42, 32) Error: object constructor needs an object type [proxy] +tstatic_constrained.nim(42, 32) Error: expression '' has no type (or is ambiguous) +''' +""" + +type + MyType[T; X: static T] = object + data: T + MyOtherType[T: float or string, Y: static T] = object + +func f[T,X](a: MyType[T,X]): MyType[T,X] = + when T is string: + MyType[T,X](data: a.data & X) + else: + MyType[T,X](data: a.data + X) + +discard MyType[int, 2](data: 1) +discard MyType[string, "Helelello"](data: "Hmmm") +discard MyType[int, 2](data: 1).f() +discard MyType[string, "Helelello"](data: "Hmmm").f() +discard MyOtherType[float, 1.3]() +discard MyOtherType[string, "Hello"]() +discard MyOtherType[int, 10]() +discard MyOtherType[byte, 10u8]() \ No newline at end of file |