typecheck: a _ctx-first container that returns its handle is not a block setter - #2060
Merged
Merged
Conversation
…ock setter
E0200 (0.667) used "the callee's module also defines a builder" as the
whole discriminator between a block setter and a DSL container, on the
premise that a widget-style module has no builders. aether-ui's ui
module has four (window, render_to, record, nav_page) beside some fifty
_ctx-first containers, so `ui.vstack(10) { ... }` — every app in that
repository — became a compile error past 0.666 (aether-ui#147).
The rule now also requires that the callee yield no value. A container
RETURNS the handle its block runs inside (that value is the block's
_ctx); a block setter records config and returns nothing, which is
exactly why its own trailing block can never be entered. aeb's setters
are all void, so the misuse the rule was written for is still caught.
The void check runs on the already-resolved symbol: call_yields_no_value
re-looks the callee up by its bare name, which a `mod.name` call does
not resolve, so it answered "yields a value" for every qualified call.
tests/integration/setter_in_builder_position gains uimod — a builder
beside handle-returning containers and one void setter — with LEGIT C
(the container compiles) and MISUSE B (the setter still errors).
…eturns-handle # Conflicts: # CHANGELOG.md
…eturns-handle # Conflicts: # CHANGELOG.md
…eturns-handle # Conflicts: # CHANGELOG.md
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.
Why
Moving aether-ui from 0.645 to 0.681 (aether-lang-dev/aether-ui#147) fails every example in the fan-out with:
E0200 (b551fe5, 0.667) discriminates a block setter from a DSL container by "the callee's module also defines a
builder", on the premise that a widget-style module has none. aether-ui'suimodule has four (window,render_to,record,nav_page) beside ~50_ctx-first containers (vstack,hstack,scrollview,splitview, …), so the rule's own comment ("a widget-style DSL module has no builders and is never flagged") does not hold for the largest DSL consumer in the org.What
A fourth condition: the callee must yield no value. A container returns the handle its trailing block runs inside — that return value is the block's
_ctx— while a block setter records config and returns nothing, which is precisely why its own trailing block can never be entered. That is the semantic line, not a heuristic:rspec,minitest,env,gem_dep,rbenv, …) is void → still flagged;_ctx-first functions (bg_color,font_size,tooltip, …) are setters and are never written with a trailing block in that tree — and would now be flagged if they were, which is the rule working.The void check runs on the already-resolved
symbol(fn_yields_no_value, factored out ofcall_yields_no_value): the existing helper re-looks the callee up by bare name, which amod.namecall does not resolve, so it answered "yields a value" for every qualified call.Verified
tests/integration/setter_in_builder_position: the three existing cases plus LEGIT C (uimod: a builder beside handle-returning containers —uimod.window("app") { vstack(10) { label("hello") } }compiles) and MISUSE B (uimod.font_size(14) { … }, the module's void setter, still errors). 5/5..aesources under aether-uiexamples/,apps/,tests/type-check with this build (aetherc --check --lib .), against 1 before (every app).