fix(checker): hold an inferred Flags to the power-of-two rule #190
Loading…
Reference in a new issue
No description provided.
Delete branch "loop/48-inferred-flags-rule"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Task
Closes #48
What and why
The power-of-two rule of
docs/design/FLAGS.mdsection 2 ran only intypeFromReference, i.e. only whereFlags<Case>is written. AFlagswhose type a call infers (Flags.of(Permission.Read),Flags.from([Permission.Read]), a genericfn flagsOf<Case: RawValue>(first: Case): Flags<Case>called withPermission.Read) never passed through it, socase Both = 3went unreported and the value stored the bits of the number as they are (section 6 named the gap).compiler/src/semantics/checker/case-value.trb: the rule is nowflagBitsProblem, which answers the diagnostic;requireFlagBits(written types) reports it as before, and the newrequireInferredFlagBitsreports it for an inferred result at the call, unless the module already has that message.compiler/src/semantics/checker/call.trb:checkCallnotes right after instantiating the callee whether its result type mentions a variable of this call (hasVariable), i.e. whether the call infers it, and runsrequireInferredFlagBitson the resolved result. A callee with a written concrete result (fn all(): Flags<Permission>) or a call with written type arguments is not re-reported: its written type already was.const access: Flags<Permission> = Flags.of(Permission.Read)reports once, at the annotation; a module reports the same root cause once however many calls infer it.docs/language/types/case-values.md,docs/standard-library/collections.mdand the doc comment ofstd/collections/src/flags.trbsay "written or inferred";skills/regenerated withtorb docs skill docs skills.Test
New tests in
compiler/tests/case-values.test.trb, groupFlags<Case>(thecollectionsstub gainedstatic fn ofandstatic fn from):const access = Flags.of(Permission.Read)withcase Both = 3: exactly the one message.const access = Flags.from([Permission.Read]): the same message once.const access: Flags<Permission> = Flags.of(Permission.Read): one message, not two.flagsOf<Case: RawValue>(first: Case): Flags<Case>called withPermission.Read: reported once at the call, nothing in the generic body.1,2,64) throughFlags.ofand through the generic function: no problems.Locally (today's nightly):
torb format --checkon the touched.trbfiles,torb check compiler("361 files, no problems"), and the test programs checked and run against the realstd/collections. Gates (tier A) run in the forge CI; tier B is not required (nothing undercompiler/src/ir,backendorruntime/changed).Seed: no. No syntax change, no new native, no driver flag, no new std name looked up by string (
wellKnown.flagsis already in use).Approved at
3c58492. Checklist:compiler/tests/case-values.test.trbcoverFlags.of,Flags.from, the written-plus-inferred case (reported once), a genericflagsOf<Case: RawValue>(reported at the call, not in the body) and the all-powers-of-two negative. CI is green on this head (tier A, gates, bootstrap, pdisc). Tier B is correctly skipped, since nothing underir,backendorruntime/changed.flagBitsProblemis a pure extraction of the old rule, sorequireFlagBitsbehaves as before.checkCallrecordshasVariablebefore the result is resolved and reports only when the call infers the result, so a concrete written result or explicit type arguments is not re-reported. The per-module message dedup makes the annotation case report once.Flags, plus a checker test), with no drive-bys.flags.trbdoc comment and the regeneratedskills/copies are consistent; pdisc is green.Non-blocking:
requireInferredFlagBitsdedups on the message text against diagnostics already reported in the module. If a call that infers theFlagsis checked before a writtenFlags<Permission>that appears later in the same module, the same message could appear twice. That is cosmetic and needs no change here.