Skip to content

Add const keyword - #452

Open
LesterEvSe wants to merge 5 commits into
BlockstreamResearch:masterfrom
LesterEvSe:feat/const-item
Open

LesterEvSe wants to merge 5 commits into
BlockstreamResearch:masterfrom
LesterEvSe:feat/const-item

Conversation

@LesterEvSe

@LesterEvSe LesterEvSe commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Previously, this functionality was deleted in #323 along with the old mod keyword support, but the lexer and parser still support this. So now we reintroduce const.

A const is a named, compile-time value. Its initializer must be a constant expression, and each use compiles to the precomputed value. Unlike a zero-argument function, which can read the transaction (e.g. jet::num_inputs()), a const is guaranteed to be fixed data. Constants can be pub and imported with use, like other items.

A motivating example is sha256_paddings.simf in the price-oracle repo.

So now we can do something like this:

mod config {
    pub const FEE: u32 = 1_000;
}

use crate::config::FEE;

const MAX: u32 = 10_000;

fn main() {
    assert!(jet::lt_32(FEE, MAX));
}

Checklist

  • New or changed language features are used in fixtures/kitchen_sink.simf (see its header).

@LesterEvSe
LesterEvSe requested a review from KyrylR October 23, 2026 14:08
@LesterEvSe LesterEvSe self-assigned this Oct 23, 2026
@LesterEvSe LesterEvSe added the enhancement New feature or request label Oct 23, 2026
@LesterEvSe
LesterEvSe marked this pull request as ready for review October 23, 2026 15:43
@LesterEvSe
LesterEvSe requested a review from delta1 as a code owner October 23, 2026 15:43
@LesterEvSe
LesterEvSe force-pushed the feat/const-item branch 2 times, most recently from fbc9738 to d8401ca Compare October 26, 2026 10:33

@stringhandler stringhandler left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I'm not sure about:
Is it possible to add const inside a function body? If so, how is that different from let?

Comment thread fixtures/kitchen_sink.simf Outdated
Comment thread fixtures/kitchen_sink.simf Outdated
Comment thread src/ast/analyze/expression.rs
@apoelstra

Copy link
Copy Markdown
Contributor

avoid using functions where a const would be enough

I'm confused about what the difference is. A pure function and a const should compile identically. (I know they don't, and that functions are always compiled to evaluate all their code even if they could be elided and replaced by a const word or a lookup, but this is an optimization bug.)

We could add a const keyword on functions which mark them as "pure" and forbid any transaction or witness access. But that would require some sort of effect system. We could also make const X: Y = y be a sort of alternate syntax for const fn X() -> Y { y } but I'd like to get constfns working before we try to add sugar for them.

@stringhandler

Copy link
Copy Markdown
Collaborator

Side note here, but I didn't see any relationship to #451, even though the description mentions it

@LesterEvSe

Copy link
Copy Markdown
Collaborator Author

One thing I'm not sure about: Is it possible to add const inside a function body? If so, how is that different from let?

No, const is an Item, and only a Module can contain other items, so a type alias, function, or const can't be placed inside a function body. I think this makes it easier to introduce the const keyword and to add further optimizations for it later.

The difference from let is that a const is evaluated at compile time and inlined as a value wherever it is used, so its initializer must be a constant expression, so witnesses, parameters, and function calls are rejected. It can also be pub and imported from another module with use.

One limitation is writing const inside a function body currently gives a confusing parser error (Unclosed delimiter {) instead of saying that items are not allowed there. That belongs to the error-reporting work, not to this PR

@LesterEvSe

Copy link
Copy Markdown
Collaborator Author

Side note here, but I didn't see any relationship to #451, even though the description mentions it

It's just easier for me to resolve the merge conflicts here rather than in the errors branch

@LesterEvSe

Copy link
Copy Markdown
Collaborator Author

But we can do it in another order. It is not critical

@LesterEvSe
LesterEvSe force-pushed the feat/const-item branch 3 times, most recently from dcb5f9a to 7983356 Compare October 26, 2026 16:10
@LesterEvSe
LesterEvSe force-pushed the feat/const-item branch 2 times, most recently from d8426dc to efe06b4 Compare October 27, 2026 10:48
@LesterEvSe

Copy link
Copy Markdown
Collaborator Author

I'm confused about what the difference is. A pure function and a const should compile identically. (I know they don't, and that functions are always compiled to evaluate all their code even if they could be elided and replaced by a const word or a lookup, but this is an optimization bug.)

We could add a const keyword on functions which mark them as "pure" and forbid any transaction or witness access. But that would require some sort of effect system. We could also make const X: Y = y be a sort of alternate syntax for const fn X() -> Y { y } but I'd like to get constfns working before we try to add sugar for them.

Agreed, codegen isn't the reason, I'll fix the description. The reason is the guarantee, where a const is checked to be a fixed value (no calls, witnesses, or parameters), while a zero-argument function can read the transaction. That needs no effect system, because a const initializer can't call anything. And it doesn't conflict with const fn. Once that exists, const initializers can be allowed to call const fns

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants