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

explicitly instantiated generic template fails when it has a proc overload #16376

Closed
Araq opened this issue Dec 16, 2020 · 6 comments · Fixed by #24010
Closed

explicitly instantiated generic template fails when it has a proc overload #16376

Araq opened this issue Dec 16, 2020 · 6 comments · Fixed by #24010

Comments

@Araq
Copy link
Member

Araq commented Dec 16, 2020

The following snippet doesn't compile, but should:

type
  Matrix[T] = object
    data: T


proc randMatrix*[T](m, n: int, max: T): Matrix[T] = discard
proc randMatrix*[T](m, n: int, x: Slice[T]): Matrix[T] = discard

template randMatrix*[T](m, n: int): Matrix[T] = randMatrix[T](m, n, T(1.0))

let B = randMatrix[float32](20, 10)
@timotheecour
Copy link
Member

timotheecour commented Dec 16, 2020

The root cause is that explicit instantiation of generic templates doesn't work, see examples below, some are regressions, some are pre-existing bugs.

example 1: regression

reduced from top example

when defined case5:
  proc fn[T](max: int) = discard
  proc fn[T](x: string) = discard
  template fn[T]() = fn[T](1)
  fn[float32]()

regression: works in 0.19.6
fails in 0.20.0

in devel:

t11520.nim(5, 1) template/generic instantiation from here
t11520.nim(39, 14) Error: expression 'fn[float32]()' cannot be called
    fn[float32]()
               ^
/Users/timothee/git_clone/nim/Nim_devel/compiler/semcall.nim(414, 19) compiler msg initiated here [MsgOrigin]

example 2: bad error msg

this one is not a regression: doesn't work in either devel nor 0.19.6

when defined case6: # D20201216T124119:here
  #[

bad error message for 2 reasons: doesn't show proc name, and shouldn't be an error in the 1st place

t11520.nim(5, 1) template/generic instantiation from here
t11520.nim(60, 14) Error: type mismatch: got <>
but expected one of:
proc (max: int){.noSideEffect, gcsafe, locks: 0.} [proc]
    fn[float32]()
               ^
/Users/timothee/git_clone/nim/Nim_devel/compiler/semexprs.nim(972, 21) compiler msg initiated here [MsgOrigin]
  ]#
  proc fn[T](max: int) = discard
  template fn[T]() = fn[T](1)
  fn[float32]()

example 3: regression: accepts invalid

when defined case7: # D20201216T124243:here
  #[
  devel: bug
  current output: ok2
  expected output: ok1

  0.19.6: good
  Error: ambiguous call
  ]#
  proc fn[T](max: int) = echo "ok1"
  proc fn[T]() =  echo "ok2"
  template fn[T]() = fn[T](1)
  fn[float32]()

example 4

this shows that what's buggy is when you call an overloaded generic template with explicit instantiation:

when defined case7i: # D20201216T143655:here
  proc fn[T](max: T, y: string) = discard
  template fn[T](a: T) = fn[int](1, "")
  fn[int8](2) # Error: type mismatch: got <int literal(2)> but expected one of: proc (max: int8, y: string){
  # these are ok:
  # fn(2)
  # also works if we change template name so it's not overloaded
  # also works if `s/proc fn[T]/template fn[T]/`

links

@timotheecour timotheecour changed the title Mixing templates and procs explicitly instantiated generic template fails when it has a proc overload Dec 16, 2020
@timotheecour
Copy link
Member

@Araq

The following snippet doesn't compile, but should:

nimdigger found that #11303 introduced the regression

@Araq
Copy link
Member Author

Araq commented Jun 29, 2021

And that helps me how exactly? "The regression in overloading resolution was caused by a change in the overloading resolution logic", well I could have guessed that much. The PR you pointed to affects the tyOr operator. In my example there is no or operator in sight. Now what? Maybe I simply need to debug and fix the bug...

@timotheecour
Copy link
Member

timotheecour commented Jun 29, 2021

And that helps me how exactly?

by narrowing down the lines to look at down to only the 8 that were touched in that PR. The overloading resolution logic has a much larger surface; seems like a no-brainer gain.

@Araq
Copy link
Member Author

Araq commented Jun 29, 2021

But so far (no 'or' operator in sight, remember?) it looks like it worked by chance before that or-operator related change...

timotheecour added a commit to timotheecour/Nim that referenced this issue Jun 29, 2021
timotheecour added a commit to timotheecour/Nim that referenced this issue Jun 29, 2021
@metagn
Copy link
Collaborator

metagn commented Aug 23, 2024

explicitGenericInstantiation restricts to non-macro/template symbols only here because it calls explicitGenericSym which calls generateInstance here which can't be used for macros or templates. The more general problem is the compiler thinks we can neatly pack the information of the instantiated routines into syms, which isn't true for macros and templates. Among themselves macros and templates also pick a random sym to use for explicit generic instantiation:

type
  Matrix[T] = object
    data: T


template randMatrix*[T](m: T, n: T): Matrix[T] = Matrix[T](data: T(1.0))
template randMatrix*[T, U](m: T, n: U): (Matrix[T], U) = (Matrix[T](data: T(1.0)), default(U))

let B = randMatrix[float32](20, 10)
echo B # ((data: 1.0), 0) -- overload with 2 generic params??

It's weird because resolveOverloads should be able to handle it if we just call semDirectOp. There's a branch in semExpr that whitelists it if the identifier is a symchoice.

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