`syntax_meta.flip_introduce` can lead to ambiguous bindings
This arises during an attempt to fix Shplait’s let not using the original identifier. The following code defines two versions of let in terms of nested definition contexts, but only the version using Syntax.replace_scopes works as expected:
#lang rhombus/static/and_meta
expr.macro 'let1 $id = $rhs:
$body':
def tmp = id.replace_scopes('here')
'block:
def $tmp = $rhs
block:
def $id = $tmp
$body'
expr.macro 'let2 $id = $rhs:
$body':
def tmp = syntax_meta.flip_introduce(id)
'block:
def $tmp = $rhs
block:
def $id = $tmp
$body'
let1 x = 1: x
// This leads to "x: identifier's binding is ambiguous"
let2 x = 2: x
Shplait’s version of let currently is missing unquotes inside the template, therefore hiding this bug.
Thanks for this report!
I think the blame here belongs on the attempted use of syntax_meta.flip_introduce in let, since (in retrospect) that doesn't work right for a binder in a definition context.
Doing the right thing will be easier if I provide a variant of Syntax.make_temp_id that uses the given name as-is, which is something I had been considering, anyway.
To my understanding, syntax-local-introduce is not a reliable way to break hygiene in Racket; thus it seems like a bad idea to document syntax_meta.flip_introduce as for this purpose in Rhombus.
The definition and use site of a macro may be distinguished by many scopes other than the macro and use-site scopes, like module scopes, so a macro can't make an identifier match the use-site just by flipping the macro and use scopes.
The original issue is solved by the addition of use-site scopes in enforestation, so I’m closing this.
To my understanding,
syntax-local-introduceis not a reliable way to break hygiene in Racket; thus it seems like a bad idea to documentsyntax_meta.flip_introduceas for this purpose in Rhombus.
The doc can be updated to better state what exactly scope-flipping achieves, but this is a minor issue.