rhombus-prototype icon indicating copy to clipboard operation
rhombus-prototype copied to clipboard

"Identifier already defined" error when `fun` and `statinfo.macro` define the same identifier

Open jetjinser opened this issue 1 year ago • 2 comments

When I was reading the guide, I tried one of the examples described in it, but an error occurred.

description

When fun zero() and statinfo.macro 'zero' are declared at the same time, an "Identifier already defined: zero" error will appear.

link

online docs: https://docs.racket-lang.org/rhombus/annotation-macro.html source: https://github.com/racket/rhombus/blob/48890894d874df648fcb33de351c9dd60009f86c/rhombus/rhombus/scribblings/guide/annotation-macro.scrbl#L166-L179

reproducible code

#lang rhombus

use_static

import:
  rhombus/meta open

class Posn(x, y)

dot.macro 'vector_dot_provider $left . $right':
  match right
  | 'angle': 'vector_angle($left)'
  | 'magnitude': 'vector_magnitude($left)'

fun vector_angle(Posn(x, y)):
  math.atan(y, x)

fun vector_magnitude(Posn(x, y)):
  math.sqrt(x*x + y*y)

def zero:
  fun():
    Posn(0, 0)
// BUG: Identifier already defined
// fun zero():
//   Posn(0, 0)
statinfo.macro 'zero':
  '(($statinfo_meta.call_result_key,
     $(statinfo_meta.pack(
         '(($statinfo_meta.dot_provider_key,
            vector_dot_provider))'
       ))))'

zero().magnitude

It looks like there are some subtle differences between "def fun" and "fun", is this a bug or is it by design?

jetjinser avatar Oct 11 '24 03:10 jetjinser

Yes, this is expected. Maybe the example can be adjusted to be less confusing, but generally examples are run in a REPL-like setting, and things can work differently between modules and the REPL (top level).

The long explanation: The difference in fun name .... and def name: fun .... is a known issue. Normally, fun comes with static infos including call results and function arity. The definition fun (former) associates those with the defined name, while the expression fun (latter, inside the def) wraps those onto the function expression. Unfortunately, because fun is both a definition and expression, the conservative shortcut that propagates static infos from the right-hand side of def can’t apply, and only the former gets a binding in the statinfo space. And, as expected, redefinition (here, in the statinfo space) is not allowed within a module. However, examples are run in a REPL-like setting, and so redefinition works.

If anyone has an idea how to solve the mentioned issue, please help!

usaoc avatar Oct 11 '24 06:10 usaoc

I think we should probably avoid examples in the docs that don't work in a module, so maybe just switching to the def/fun form is the best choice.

samth avatar Oct 11 '24 15:10 samth