google / google/xls

const_assert! loses track of name references inside for loop

Open
#2,194 0 comments 0 reactions 0 assignees View on GitHub
bug dslx:type-checking
Dominant language
C++
Stars
1.9k
Forks
283
Avg merge
2d 10h
Merged PRs (30d)
135

Description

**Describe the bug**

When using a `const_assert!` specifically inside a for loop, some references seem to be missing, causing an internal error.

```
INTERNAL: BytecodeEmitter could not find slot or binding for name: result @ ...

stack: 0x55f03400bf7a: std::__u::__variant_detail::__visitation::__base::__dispatcher<>::__dispatch<>()
0x55f0340016f0: xls::dslx::BytecodeEmitter::HandleNameRef()
0x55f033fffc4d: xls::dslx::BytecodeEmitter::HandleInvocation()
0x55f033ff2a08: xls::dslx::BytecodeEmitter::HandleBinop()
0x55f033ff0a4e: xls::dslx::BytecodeEmitter::EmitExpression()
0x55f033fddbff: xls::dslx::ConstexprEvaluator::InterpretExpr()
0x55f033fdfa36: xls::dslx::ConstexprEvaluator::HandleBinop()
0x55f033fdd027: xls::dslx::ConstexprEvaluator::Evaluate()
0x55f033f785a7: xls::dslx::(anonymous namespace)::DeduceVisitor::HandleConstAssert()
```

**To Reproduce**
```
fn foo(x: u32) -> u32[8] { u32[8]:[x, ...] }

fn bar() {
for (i, _) in u32:0..u32:100 {
let result = foo(i);
const EXPECTED_SIZE = u32:2 * u32:4;
const RESULT_SIZE = array_size(result);
const_assert!(RESULT_SIZE == EXPECTED_SIZE);
const_assert!(array_size(result) == EXPECTED_SIZE);
}(());
}
```

The first `const_assert` works without any errors, so it appears that `array_size` can be used in a constexpr context correctly. The second `const_assert` generates the error above, saying that it can't find `result`.

**Expected behavior**
I would expect both to work the same, without the need to explicitly add a constant for the result size.

**Additional context**
It seems that this is only a problem inside a for loop. `unroll_for!` also does not cause an error (which makes sense I guess).

```
fn foo(x: u32) -> u32[8] { u32[8]:[x, ...] }

fn bar() {
let result = foo(u32:1);
const EXPECTED_SIZE = u32:2 * u32:4;
const RESULT_SIZE = array_size(result);
const_assert!(RESULT_SIZE == EXPECTED_SIZE);
const_assert!(array_size(result) == EXPECTED_SIZE);
}
```

Both `const_assert!`s pass without errors once the for loop is removed.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.