nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.44k stars 1.47k forks source link

Overloading resolution chooses a generic template instead of a method for an inherited type #17003

Closed ghost closed 3 years ago

ghost commented 3 years ago

This code is expected to call the dispose method but it calls a template instead.

Found in the 4th NiGui example. It crashes with ARC/ORC because Nim calls ARC's dispose from here instead of NiGui's dispose defined here (it's exported in the forward declaration at the top of the file).

Example

type
  Window* = ref object of RootObj
  WindowImpl* = ref object of Window

# Without that template the method will be called
template dispose[T](x: ref T) = 
  echo "called the template dispose"

method dispose(t: Window) {.base.} = 
  echo "called the method dispose"

var t = WindowImpl()
t.dispose()

Current Output

called the template dispose

Expected Output

called the method dispose
$ nim -v
Nim Compiler Version 1.5.1 [Linux: amd64]
Compiled at 2021-02-10
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: 216be4060a853b3425501318537d598c4842eefc
active boot switches: -d:release
ghost commented 3 years ago

Not sure if this is related to ARC/ORC at all - might be overloading resolution instead?

Araq commented 3 years ago

From the spec:

Every arg in args needs to match. There are multiple different categories how an argument can match. Let f be the formal parameter's type and a the type of the argument.

  1. Generic match: f is a generic type and a matches, for instance a is int and f is a generic (constrained) parameter type (like in [T] or [T: int|char].
  2. Subrange or subtype match: a is a range[T] and T matches f exactly. Or: a is a subtype of f.

These matching categories have a priority: An exact match is better than a literal match and that is better than a generic match etc.

The compiler is correct.