Conversation
a68ebee to
e116db8
Compare
ba776b7 to
629b2d7
Compare
Previously, lambda bodies always inherited the outer function's tracked_context. This meant an `untracked` lambda inside a tracked function would still be checked as tracked, preventing it from calling untracked functions. Now the type checker sets tracked_context=false for untracked lambda bodies, consistent with how method_body_ handles untracked functions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Functions annotated with @allow_tracked_call can be called from tracked contexts even if they are untracked. This provides a controlled escape hatch for cases like unsafe_untracked_call where the caller takes responsibility for correctness. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tests @allow_tracked_call with two variants: - trackedCaller1: wraps untracked call in an untracked lambda - trackedCaller2: passes untracked function directly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Provides a controlled escape hatch for calling untracked functions from tracked contexts (e.g., performing I/O inside reactive computations where the caller takes responsibility for correctness). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
beauby
reviewed
Mar 27, 2026
| // computations where you take responsibility for correctness and | ||
| // invalidation. | ||
| @allow_tracked_call | ||
| untracked fun unsafe_untracked_call<T>(f: untracked () -> T): T { |
Contributor
There was a problem hiding this comment.
Why does unsafe_untracked_call need to be untracked itself? Isn't the idea that it "appears tracked" although it calls the untracked function f?
Contributor
Author
There was a problem hiding this comment.
It's untracked so that we can call untracked stuff in it. The annotation applies to callers only
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.
Summary
tracked_contextin the type checker: lambda bodies now derive their tracking context from the lambda's own modifiers rather than always inheriting from the enclosing function@allow_tracked_callannotation to selectively bypass the tracking check at call sitesUnsafe.unsafe_untracked_call<T>, a generic escape hatch that allows tracked code to call untracked functionsMotivation
SKStore lazy directory compute functions run in a tracked context, which means they cannot call
untrackedfunctions. This is correct for pure reactive computations, but becomes a blocker for use cases like lazy file system access in mappers, where:untrackedCurrently, volatile functions like
Time.time_ms(),print_string, andFileSystem.readTextFileare not markeduntrackedeven though they should be — precisely because doing so would make them uncallable from mapper contexts. This escape hatch allows us to eventually mark these functions as properlyuntrackedwithout breaking existing code.Commits
Set tracked_context for untracked lambda bodies — Previously lambda bodies always inherited the outer function's
tracked_context. Now they derive it from their own modifiers:untrackedlambdas get an untracked context, tracked (~>) lambdas enforce tracking even inside untracked functions.Add @allow_tracked_call annotation — In
tfun_call, before callingcheck_tracking, the type checker looks up the callee's annotations. If@allow_tracked_callis present, the tracking check is skipped.Add AllowTrackedCall compiler test — Tests two variants: wrapping in an
untrackedlambda, and passing an untracked function directly.Add Unsafe.unsafe_untracked_call to stdlib — A simple generic function annotated with
@allow_tracked_callthat takes anuntracked () -> Tlambda and calls it.Better tracked_context for lambdas — Improved the lambda tracking logic to be bidirectional: derives context from modifiers when present, falls back to enclosing context otherwise.
Usage
Test plan
AllowTrackedCalltest: tracked function calls untracked function via both lambda and direct referenceuntracked_fun2anduntracked_lambda2invalid tests still fail🤖 Generated with Claude Code