Run more ordinary Fe at compile time - #1582
Open
micahscopes wants to merge 3 commits into
Open
micahscopes wants to merge 3 commits into
micahscopes wants to merge 3 commits into
Conversation
micahscopes
added a commit
that referenced
this pull request
Sep 23, 2026
Rename the placeholder newsfragments to the pull request number, following the repository's <PR>.<type>.md convention.
micahscopes
added a commit
that referenced
this pull request
Sep 23, 2026
Parse boolean conditions in `where` clauses next to type bounds, and check each condition that mentions no generic parameter where it is declared, even if the item is unused. A condition passes only when it evaluates to `true`; type errors, non-const operations and failed evaluation are errors. Const conditions in generic scopes are rejected until use-site checking exists. `where T` without `:` now parses as a const condition, so a lone path that names a type reports the missing trait bound instead of a type used as a value. The tree-sitter grammar, its vendored wasm build and the formatter learn the new predicate form. A predicate block goes through semantic borrow checking like any const body. Its test needs frame-local borrows in const evaluation (#1582) to evaluate the valid case, so it is added with that change.
micahscopes
force-pushed
the
pr/const-eval-capabilities
branch
from
September 23, 2026 13:19
82f1b5e to
ff45c5a
Compare
micahscopes
added a commit
that referenced
this pull request
Sep 23, 2026
Parse boolean conditions in `where` clauses next to type bounds, and check each condition that mentions no generic parameter where it is declared, even if the item is unused. A condition passes only when it evaluates to `true`; type errors, non-const operations and failed evaluation are errors. Const conditions in generic scopes are rejected until use-site checking exists. `where T` without `:` now parses as a const condition, so a lone path that names a type reports the missing trait bound instead of a type used as a value. The tree-sitter grammar, its vendored wasm build and the formatter learn the new predicate form. A predicate block goes through semantic borrow checking like any const body. Its test needs frame-local borrows in const evaluation (#1582) to evaluate the valid case, so it is added with that change.
Const evaluation rejected every borrow that carries address-space metadata. Explicit borrows of locals (`mut x`, `ref x`, and `mut` arguments) carry `Memory` metadata too, so a const fn that updated a local in place, or passed one to a helper by `mut`, failed to evaluate. Accept a `Memory` borrow whose place is rooted in a frame local and does not go through a dereference. Borrows through pointers and of provider-backed locals still fail with `InvalidProviderUse`, since constant evaluation has no memory outside its frames. A request cannot carry a pointer argument (request inputs are verified before execution), so the pointer case is tested inside the machine tests. When a frame returns a reference into itself, the value is read out if the declared result type is not a borrow, and the evaluation fails with `InvalidBorrow` if it is, so a dangling reference cannot escape. A reference into a caller's frame is returned unchanged. This fits the transactional evaluator from #1556 as is: machine references stay private to one attempt, and a blocked attempt discards its frames, so a replay after specialization starts from the original locals. #1556 recorded the borrowing restriction as intentionally kept (`docs/ctfe-deferral-audit.md`, "Borrowing scope") and pinned it with `ctfe_typed_read_preserves_provider_borrow_rejection`. That test now checks that the typed read through `ref value` evaluates to 7, under the name `ctfe_typed_read_through_frame_local_borrow_evaluates`, and the audit's borrowing paragraph describes the admitted borrows.
fe-common embeds `ingots/core` and `ingots/std` with rust-embed. The compiler records only the files that the previous expansion embedded as dependencies, so adding a new file to either library (for example a new `core` module) did not rebuild fe-common, and a cached build kept serving the old library. Add a build script that reruns when either directory changes and hashes the paths and contents of both trees into `FE_BUILTIN_FINGERPRINT`. `stdlib.rs` reads that variable, so rustc and compiler caches such as sccache treat the library's file set as an input. The fingerprint hashes native paths and raw file bytes, so its value differs between platforms and line-ending settings. It is only used to invalidate caches and is never compared.
Const functions could not use effects at all: a `uses` clause on a `const fn` was an error, a call to any function with effects was an error, and every `with` expression in a `const fn` was rejected. A trait provider is an ordinary value, so an immutable one can be evaluated at compile time like any other argument. Allow a `const fn` to declare immutable trait effects and to supply them with `with`. During evaluation a call passes each provider as a value into the callee's effect slot, matched by the effect's binding index rather than by its position among ordinary arguments. A `with` provider that lowering captured as a place (#1564) is read from that place. The checker still rejects mutable effects, type-keyed (storage) effects, and extern functions with effects. Deferral needs no special case. Since #1556, a call whose input is still generic blocks the whole attempt, which is discarded and replayed after specialization; the replay recomputes the providers from the caller's body. Term extraction already declines calls with effect arguments, so a provider never enters a retained term. A test checks that an effectful call blocks while generic and evaluates with its provider once specialized, like a pure call. Effect slots follow the same rules as ordinary argument slots: a request that supplies no providers for an effectful function is unsupported (`NotConstEvaluable`), and a slot count or index mismatch is an invalid operation, like the existing argument arity check. The `with`-in-const-fn diagnostic (8-0056) is removed, and the two remaining const-effect messages now say what is supported.
micahscopes
force-pushed
the
pr/const-eval-capabilities
branch
from
September 25, 2026 04:15
ff45c5a to
08e8b62
Compare
micahscopes
added a commit
that referenced
this pull request
Sep 25, 2026
Parse boolean conditions in `where` clauses next to type bounds, and check each condition that mentions no generic parameter where it is declared, even if the item is unused. A condition passes only when it evaluates to `true`; type errors, non-const operations and failed evaluation are errors. Const conditions in generic scopes are rejected until use-site checking exists. `where T` without `:` now parses as a const condition, so a lone path that names a type reports the missing trait bound instead of a type used as a value. The tree-sitter grammar, its vendored wasm build and the formatter learn the new predicate form. A predicate block goes through semantic borrow checking like any const body. Its test needs frame-local borrows in const evaluation (#1582) to evaluate the valid case, so it is added with that change.
micahscopes
marked this pull request as ready for review
September 25, 2026 04:51
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This lets compile-time evaluation run more ordinary Fe, so a helper does not need a separate const-only version.
A
const fncan update a local through amutborrowanswer()now evaluates to42; on master, evaluation rejects the borrow withInvalidProviderUse. Borrows through pointers or of provider-backed locals still fail, since compile-time evaluation has no memory outside its own call frames. Evaluation also fails if a function returns a borrow of its own local.A
const fncan take an immutable trait provider withuses, and a caller can supply one withwithOn master, the
usesclause and thewithare both errors. A test runs the same code at compile time and at runtime and checks that the results agree.Rebuild the compiler when a file is added to
coreorstd. Before, a new library file did not trigger a rebuild, so a cached build kept the old library. The fingerprint only invalidates caches and is never compared, so its per-platform value is harmless.A few decisions:
within aconst fn(8-0056) is removed, so that code is no longer emitted. The two remaining errors for effects in aconst fn(8-0055, 8-0063) now say which effects are supportedHow this fits mainline:
docs/ctfe-deferral-audit.mdis updated.withprovider such asNumber { value: 11 }once perwithentry and may pass it by place. Const evaluation reads a provider passed by place from that place.consts.rssee throughviewtypes. This PR does not change that code, and Keep integer width for view-typed values in constant evaluation #1594'sctfe_view_int_bitnot.fepasses.Overlap with open PRs: #1576 conflicts in
const_check.rsandmachine.rs. It moves theconst fneffects check, which this PR changes from "any effects" toconst_effects_supported, so whichever lands second carries that change into the moved check. #1455 and #1506 conflict inconst_check.rsas well. Other open PRs that touch these files conflict only where they already conflict with master.Planned later PRs in this series (trait evidence, named implementation selection, generated code) build on the provider support here.