Repository navigation
Lint sweeps for STYLE042 / STYLE043 / PERF033, => line continuation, inscope after break/continue - #4217
Merged
Conversation
aleksisch
force-pushed
the
lint-sweep-fixes
branch
2 times, most recently
from
October 6, 2026 15:20
df14308 to
29b9814
Compare
aleksisch
marked this pull request as ready for review
October 6, 2026 15:21
aleksisch
force-pushed
the
lint-sweep-fixes
branch
2 times, most recently
from
October 6, 2026 20:22
3b6ac8f to
dc7b3e3
Compare
…ders The reverse half of LINT026 - an anchor nothing cites - read citers only under the run's roots. A rule document binds its subfolders, so it often sits above the folder whose anchors it names: modules/REVIEW_SHADER_EMITTERS.md cites dasMetal/ARCHITECTURE.md#kernel-model-asymmetry-ledger. check_lint_changed lints only the changed folders, so any change to a dasMetal source reported that anchor as uncited. The pass now also reads the .md files in every folder above a root, as citers only - their own anchors and citations are judged when their folder is linted.
LINT033 resolves a cited path from the citing folder, its tree and its ancestors; benchmarks/ is a sibling of performance/, so the bare name never resolved. The neighbouring citation already spells ../benchmarks/.
…ings_boost one Both requires serve only the llvm_tune static_if half. A build with llvm_tune uses dasllama_home_dir, so STYLE030 stays silent and its nolint reads as stale; line 14 already carries LINT019 for the same reason, line 9 now does too.
A function, method, block or lambda arrow body that does not fit beside its
signature can move below it:
def scale(first_argument, second_argument : int; factor : float) : float =>
float(first_argument * second_argument) * factor
The lexer takes the line break right after `=>` as part of the token, so it
never ends the statement. Every grammar rule with `=>` requires an expression
after it, so a newline there was always a syntax error - no program that
compiled before changes meaning. Only that one break joins: a blank line or a
comment after `=>` still ends the statement. tree-sitter already parsed the
form; its corpus and the grammar canary now pin it.
A var inscope is finalized when its scope ends, and an early exit ends it too - before the declaration ran when the exit comes first. ExprLet's early_out relocation zeroes such a variable at the top of the block, but only return marked the scope chain: a break or a continue in a nested block before the declaration left the slot holding whatever the stack had, and the finalizer deleted it - 'can't delete locked array', or worse, in the interpreter (JIT happened to be fine). break and continue now mark the chain the same way.
… return A while body that owns a finalizer (a var inscope local) leaves through loopend_fin, runs the finalizer, and goes back to the loop head. The head evaluated the condition before it looked at stopFlags, so a return in the body ran the condition once more - and when the condition is a real call, that call clears the pending return on its way out, so the loop went on as if the return never happened. A parser loop such as read_toml's spun forever on bad input in the interpreter; JIT and AOT were fine. The head now checks stopFlags first.
def f(...) { return EXPR } -> def f(...) => EXPR (=> <- EXPR for a move),
written by the STYLE042 rule's --fix (PR #4213) over the tree and re-linted
per file. A body that does not fit in 100 columns takes the expression on the
line after =>; a single comment in the body moves to the end of the new line.
tests/daslib/ast_cursor_fixture.das becomes _ast_cursor_fixture.das - its
cursor positions are pinned by its test, so lint must leave it alone.
…ration var a : T / var b : T -> var a, b : T, written by the STYLE043 rule's --fix (PR #4213) over the tree and re-linted per file; five same-line pairs (var a : T; var b : T) merged by hand.
var x : array<T> / let x <- ... inside a loop -> var inscope x, written by the PERF033 rule's --fix (PR #4213) over the tree and re-linted per file; a whole multi-variable declaration takes inscope when every variable in it is a container the rule reports.
aleksisch
force-pushed
the
lint-sweep-fixes
branch
from
October 6, 2026 21:15
dc7b3e3 to
f042382
Compare
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.
The tree sweeps for three new lint rules (STYLE042, STYLE043, PERF033 - the rules themselves are #4213, which stacks on this branch), plus the three compiler and interpreter fixes the sweeps need and three small lint fixes their CI needs.
Commits
check_lint_changedlints only the changed folders, so an anchor cited from a rule document one folder up (modules/REVIEW_SHADER_EMITTERS.md->dasMetal/ARCHITECTURE.md#kernel-model-asymmetry-ledger) read as uncited whenever a dasMetal source changed. The pass now also reads the.mdfiles above each root, as citers only.setup_lcpp_ref.dasby its path - LINT033: the bare name never resolved fromperformance/.dasllama_envrequire takes LINT019 like itsstrings_boostone - both serve only thellvm_tunehalf, so the nolint is stale in a build with llvm_tune.=>at the end of a line continues on the next - the lexer takes the line break right after=>as part of the token. Every grammar rule with=>requires an expression after it, so a newline there was always a syntax error; no program that compiled before changes meaning. A blank line or a comment after=>still ends the statement. tree-sitter already parsed the form; its corpus and the grammar canary now pin it. The STYLE042 sweep needs it for bodies that do not fit beside their signature.break/continuein a nested block before avar inscopedeclaration left its slot uninitialized, and the finalizer deleted garbage ("can't delete locked array"). Found by the PERF033 sweep;tests/daslib/test_inscope_early_out.daspins it.whilebody that owns a finalizer (avar inscopelocal) evaluated the loop condition before it looked atstopFlags, and a condition that is a real call cleared the pendingreturnon its way out - the loop went on.read_tomlspun forever on bad input in the interpreter (JIT and AOT were fine); the PERF033 sweep'sinscopeindaslib/toml.dasexposed it.tests/language/loop_ret.daspins it.def f(...) { return EXPR }->def f(...) => EXPR(=> <- EXPRfor a move), 936 files.var a : T/var b : T->var a, b : T, 257 files.array/tabledeclared inside a loop becomesvar inscope, 223 files. Without it every iteration leaks the buffer until the heap resets.Commits 7-9 were written by each rule's
--fixand re-linted per file. They cover the code master has; the sweep of the lint code #4213 adds is in #4213.Verification
check_lint_treeis clean except for findings master already has.utils/lint/tests,tests/lint,ast_cursor_test,test_inscope_early_out,function_arrow_bodypass on this branch alone (277/277).testssuite: running.