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

callOperator doesn't work inside generic procs at inner scope #21214

Open
shirleyquirk opened this issue Jan 1, 2023 · 2 comments
Open

callOperator doesn't work inside generic procs at inner scope #21214

shirleyquirk opened this issue Jan 1, 2023 · 2 comments

Comments

@shirleyquirk
Copy link
Contributor

shirleyquirk commented Jan 1, 2023

Description

{.experimental:"callOperator".}
block:
  type Foo = object
  proc `()`(f:Foo,x:int):int = x*x
  proc bar[T](f:T):int = f(5)
  echo bar(Foo())

Nim Version

Nim Compiler Version 1.9.1 [Linux: amd64]
Compiled at 2022-12-21
Copyright (c) 2006-2022 by Andreas Rumpf

git hash: 8a77798
active boot switches: -d:release

Current Output

/tmp/asdfds.nim(6, 11) template/generic instantiation of `bar` from here
/tmp/asdfds.nim(5, 27) Error: attempting to call routine: 'f'
  found 'f' [param declared in /tmp/asdfds.nim(5, 15)]

Expected Output

25

Possible Solution

proc bar[T:proc | object](f:T):int = f(5)

doesn't work either

you can do something like:

type Callable = concept c
  c(5) is int

proc bar(f:Callable):int =
  when (f is proc):
    f(5)
  else:
    `()`(f,5)

but it rather defeats the purpose, and you have to have declared the call operator first

Additional Information

No response

@metagn
Copy link
Collaborator

metagn commented Jan 2, 2023

This if branch gets executed:

Nim/compiler/semexprs.nim

Lines 553 to 558 in 3b965f4

proc overloadedCallOpr(c: PContext, n: PNode): PNode =
# quick check if there is *any* () operator overloaded:
var par = getIdent(c.cache, "()")
var amb = false
if searchInScopes(c, par, amb) == nil:
result = nil

When you iterate over each scope and their symbols, you get:

scope 1
scope 2
result
f
T
scope 3
scope 4
scope 5
tgenericcallop
system

So for some reason all the symbols in the block: scope are deleted.

@shirleyquirk
Copy link
Contributor Author

shirleyquirk commented Jan 3, 2023

Precisely, I saw the same thing. And i notice that passing, e.g.

block:
  ...
  proc xxx(x:int):int = X
  ...
  bar(xxx)

works just fine, it doesn't look for symbols, it uses all that machinery in sigmatch that I don't understand.
Here:

let m = resolveIndirectCall(c, n, nOrig, t)

So I was thinking. Since any object with a call operator can be trivially converted to a closure, if you have an object O in a call with type (args...):ret, instead of doing the lookup against a symbol O matching that type, look for a symbol "()" with type (O,args...):ret

The main point is, instead of different paths for special Operators and procTy, can we use the same path as much as possible

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

No branches or pull requests

2 participants