Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange overload resolution behavior for procedures with typeclass arguments #1991

Closed
MasonMcGill opened this issue Jan 22, 2015 · 1 comment

Comments

@MasonMcGill
Copy link

Consider the following overload resolution scenario:

type ParameterizedType[T] = object

type CustomTypeClass = generic
  true

# Definition A: precedence level 1 (highest)
proc p[T](x: ParameterizedType[T]) =
  static: echo "x as ParameterizedType[T]"

# Definition B: precedence level 2 (lowest)
proc p(x: ParameterizedType) =
  static: echo "x as ParameterizedType"

# Definition C: precedence level 2 (lowest)
proc p(x: CustomTypeClass) =
  static: echo "x as CustomTypeClass"

p(ParameterizedType[int]()) # Definition A is called.

The signature of definition B is just the point-free equivalent of the signature of definition A, but it has a lower precedence in overload resolution. Also, a compiler error is raised if definition A is removed, because definitions B and C have the same precedence, even though definition B seems more concrete/specific (though I suppose this is subjective).

To clarify, the behavior I expected for overload resolution:

  • "is this"-style types (like ParameterizedType and ParameterizedType[T]) are treated equally, whether or not they are typeclasses.
  • "is this"-style types are preferred to "does this"-style types (like "CustomTypeClass").

The current behavior:

  • There is no distinction between "is this"- and "does this"-style types.
  • Signatures with explicit generic parameters are preferred to signatures with implicit generic parameters, even if they are semantically equivalent.

I'm not sure if this is a conscious design decision or a bug, since it's not mentioned in the manual, but I figured I'd mention it.

@MasonMcGill
Copy link
Author

Update: It looks like this is actually a problem with all typeclasses, not just user-defined typeclasses:

type A {.inheritable.} = object
type B = object of A

proc p[X](x: X): string = "generic"
proc p[X: A](x: X): string = "specialized"

echo p(B()) # prints "generic"

This is unfortunate, because it prohibits implementing common operations (==, $, repr, len, etc.) for instances of typeclasses. Currently, I'm trying to implement == and $ for generic n-dimensional arrays, but procedures in the system module keep hijacking my implementations. Can anyone suggest a workaround?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants