# AstGen: correctly deduplicate \`ref\` of \`param\` and \`alloc_inferred\` · gitcafe/zig

[View on GitCafe](https://git.cafe/gitcafe/zig/commit/03f5b967f0d0dcdcb850061613cdb0793e2d8be2)

Repository: [gitcafe/zig](https://git.cafe/gitcafe/zig)

Visibility: public

Requested revision: 03f5b967f0d0dcdcb850061613cdb0793e2d8be2

Requested commit: 03f5b967f0d0dcdcb850061613cdb0793e2d8be2

Commit: 03f5b967f0d0dcdcb850061613cdb0793e2d8be2

Tree: b24253b9f2c865e5564e1503f3533c170df1bd58

Author: mlugg

Committer: mlugg

## Message

```
AstGen: correctly deduplicate `ref` of `param` and `alloc_inferred`

Both of these instructions were previously under a special case in
`rvalue` which resulted in every reference to such an instruction adding
a new `ref` instruction. This had the effect that, for instance,
`&a != &a` for parameters. Deduplicating these `ref` instructions was
problematic for different reasons.

For `alloc_inferred`, the problem was that it's not valid to `ref` the
alloc until the allocation has been resolved (`resolve_inferred_alloc`),
but `AstGen.appendBodyWithFixups` would place the `ref` directly after
the `alloc_inferred`. This is solved by bringing
`resolve_inferred_alloc` in line with `make_ptr_const` by having it
*return* the final pointer, rather than modifying `sema.inst_map` of the
original `alloc_inferred`. That way, the `ref` refers to the
`resolve_inferred_alloc` instruction, so is placed immediately after it,
avoiding this issue.

For `param`, the problem is a bit trickier: `param` instructions live in
a body which must contain only `param` instructions, then a
`func{,_inferred,_fancy}`, then a `break_inline`. Moreover, `param`
instructions may be referenced not only by the function body, but also
by other parameters, the return type expression, etc. Each of these
bodies requires separate `ref` instructions. This is solved by pulling
entries out of `ref_table` after evaluating each component of the
function declaration, and appending the refs later on when actually
putting the bodies together. This gives way to another issue: if you
write `fn f(x: T) @TypeOf(x.foo())`, then since `x.foo()` takes a
reference to `x`, this `ref` instruction is now in a comptime context
(outside of the `@TypeOf` ZIR body), so emits a compile error. This is
solved by loosening the rules around `ref` instructions; because they
are not side-effecting, it is okay to allow `ref` of runtime values at
comptime, resulting in a runtime-known value in a comptime scope. We
already apply this mechanism in some cases; for instance, it's why
`runtime_array.len` works in a `comptime` context. In future, we will
want to give similar treatment to many operations in Sema: in general,
it's fine to apply runtime operations at comptime provided they don't
have side effects!

Resolves: #22140

```

## Parents

- [e62aac3ec4b21da20d7c57d937e508f2929138d0](https://git.cafe/gitcafe/zig/commit/e62aac3ec4b21da20d7c57d937e508f2929138d0?format=markdown)

[Source at this commit](https://git.cafe/gitcafe/zig/tree/03f5b967f0d0dcdcb850061613cdb0793e2d8be2?format=markdown)
