# Document Expr(:symbolicgoto, ...) and :symboliclabel

**URL:** https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267
**Category:** Internals & Design
**Tags:** question, documentation, macros
**Created:** [May 24, 2026, 11:11am UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267 "2026-05-24T11:11:53Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [May 24, 2026, 11:11am UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/1 "2026-05-24T11:11:53Z")

</div>

To get something equivalent to `@goto foo` and `@label foo` in a _macro_, one has to use `Expr(:symbolicgoto, :foo)` or `Expr(:symbolicgoto, :foo)` (see eg [this](https://discourse.julialang.org/t/programmatic-goto/69271) and similar topics).

Would it make sense to document this in the docstring of `@goto` and `@label`? It is not in the manual or docstrings at all AFAICT.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [May 24, 2026, 11:53am UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/2 "2026-05-24T11:53:36Z")

</div>

What do you mean exactly, because it is possible to write macro calls in quotes:

```julia-auto
julia> macro fbody()
         esc(quote
         @goto A
         print("skipped")
         @label A
         print("A")
         end)
       end
@fbody (macro with 1 method)

julia> f() = (@fbody); f()
A
julia> @macroexpand f() = (@fbody)
:(f() = begin
          #= REPL[45]:1 =#
          begin
              #= REPL[42]:3 =#
              $(Expr(:symbolicgoto, :A))
              #= REPL[42]:4 =#
              print("skipped")
              #= REPL[42]:5 =#
              $(Expr(:symboliclabel, :A))
              #= REPL[42]:6 =#
              print("A")
          end
      end)

```

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [May 24, 2026, 12:13pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/3 "2026-05-24T12:13:15Z")

</div>

I could not find a way without escaping the whole body. Specifically, when I want to determine the labels myself, as in

```julia
macro fbody()
    quote
        @goto $esc(A)
        print("skipped")
        @label $esc(A)
        print("A")
    end
end

```

but perhaps I am using the wrong syntax.

There are two issues here though:

1. getting the above to work,
2. having part of the AST undocumented (which I think still is an issue).

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [May 24, 2026, 12:15pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/4 "2026-05-24T12:15:32Z")

</div>

Like this?

```julia-auto
julia> macro fbody(name::Symbol)
         esc(quote
         @goto $name
         print("skipped")
         @label $name
         print("A")
         end)
       end
@fbody (macro with 2 methods)

julia> f() = @fbody(x); f()
A

```

The problem with `@goto $esc(A)` is it’s only escaping `esc` and the variable `A` does not exist.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [May 24, 2026, 12:19pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/5 "2026-05-24T12:19:10Z")

</div>

Sorry, perhaps I was not clear in my reply. Again, assume that I _don’t want to escape the whole block_.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [May 24, 2026, 12:31pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/6 "2026-05-24T12:31:28Z")

</div>

I see now, `@goto`/`@label` only take `name::Symbol`, not `esc(name)::Expr`. It’s backwards to force every macro to support escaped input expressions anyway. We can instead escape the `@goto`/`@label` expressions, weirdly nested interpolated quotes but whatever:

```julia-auto
julia> macro fbody(name::Symbol)
         quote
         $( esc(:(@goto $name)) )
         print("skipped")
         $( esc(:(@label $name)) )
         print("A")
         end
       end
@fbody (macro with 2 methods)

julia> @macroexpand f() = @fbody(x)
:(f() = begin
          #= REPL[80]:1 =#
          begin
              #= REPL[79]:3 =#
              $(Expr(:symbolicgoto, :x))
              #= REPL[79]:4 =#
              Main.print("skipped")
              #= REPL[79]:5 =#
              $(Expr(:symboliclabel, :x))
              #= REPL[79]:6 =#
              Main.print("A")
          end
      end)

```

I believe using API in the expression as in source code is idiomatic. The stability of undocumented expression headers like `:symbolicgoto` is dubious; there are definitely some expression headers like `:thunk` that have been mentioned to be strictly internal. I’m not even entirely certain about the stability of the headers and structure of expressions for documented syntax or language keywords, maybe those should be documented or clarified as internal. For example, I don’t see it written anywhere that `:(@mac func(input))` needs a line number argument: `Expr(:macrocall, Symbol("@mac"), LineNumberNode(0, Symbol("blah")), Expr(:call, :func, :input))`.

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [May 24, 2026, 12:34pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/7 "2026-05-24T12:34:28Z")

</div>

Nested macro ~~are exempted from~~ interact badly with macro hygiene. It’s a wart in the language, people are working on fixing it with the new JuliaLowering system to have a whole new type of macros.

~~But for now, when you call a macro inside another macro, it is effectively already escaped from the point of view of the outer macro.~~

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [May 24, 2026, 12:40pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/8 "2026-05-24T12:40:51Z")

</div>

I think that might be about the expressions inside the inner macro call’s definition’s body because the inputs at its call are definitely affected:

```julia-auto
julia> macro hygienedemo(name)
         quote $( esc(:(@goto $name)) ) end
       end
@hygienedemo (macro with 1 method)

julia> @macroexpand @hygienedemo(x)
quote
    #= REPL[84]:2 =#
    $(Expr(:symbolicgoto, :x))
end

julia> macro hygienedemo2(name)
         quote $( (:(@goto $name)) ) end
       end
@hygienedemo2 (macro with 1 method)

julia> @macroexpand @hygienedemo2(x)
quote
    #= REPL[86]:2 =#
    $(Expr(:symbolicgoto, Symbol("#33#x")))
end

```

which is why `macro fbody(name::Symbol)` looks as ugly as it is.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [May 24, 2026, 12:41pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/9 "2026-05-24T12:41:10Z")

</div>

> [@Mason](#):
>
> Nested macro are exempted from macro hygiene.

Yes, but the immediate problem is that the surface syntax for `@goto` and `@label` are technically macros (or are exposed via macros), so this is hard to avoid.

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [May 24, 2026, 12:44pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/10 "2026-05-24T12:44:22Z")

</div>

Yes, you’re right, I made way too broad a statement. IIRC there’s some edge-cases where they can essentially auto-escape themselves, but that’s not always the case. I don’t remember the specifics though, I think it’s about the dangers of interpolating into nested macros.

---

<div class="post-metadata">

### Author: ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)
#### Post date: [May 24, 2026, 1:26pm UTC](https://discourse.julialang.org/t/document-expr-symbolicgoto-and-symboliclabel/137267/11 "2026-05-24T13:26:13Z")

</div>

The reason for them staying behind the macro is in case we ever want to change the representation of goto to something different (or make it first class). It would mean making a breaking change, so we’d rather keep it behind the macro for now
