Skip to content

caller-attr: Option A @CTX_SWITCH caller-required attribute (postfix marker, foreach/opApply, mangling) - #12

Draft
yanivbenyehuda wants to merge 7 commits into
weka-1.38from
callerattr-option-a
Draft

caller-attr: Option A @CTX_SWITCH caller-required attribute (postfix marker, foreach/opApply, mangling)#12
yanivbenyehuda wants to merge 7 commits into
weka-1.38from
callerattr-option-a

Conversation

@yanivbenyehuda

Copy link
Copy Markdown
Collaborator

Caller-required attributes ("Option A") — @CTX_SWITCH

Adds a caller-required attribute mechanism to the Weka LDC fork: a callee marked with a
caller-attribute (e.g. @CTX_SWITCH, defined via core.attribute.callerAttr!"CTX_SWITCH")
must be acknowledged at every call site with a postfix marker, and the requirement
propagates to the calling function. This makes design-time-visible which call paths can
context-switch (yield a fiber), enforced by the compiler. A non-propagating variant
(callerAttrFake) acts as a radius limiter.

Semantics

  • Marker (postfix): callee(args) @CTX_SWITCH; — required iff callee carries the attribute.
    Calling a @CTX_SWITCH function without the marker is an error ("must be marked"); putting the
    marker on a non-@CTX_SWITCH callee is an error ("remove the marker").
  • Propagation: a function calling a @CTX_SWITCH callee must itself be @CTX_SWITCH (or the
    *_FAKE variant, which carries the attribute but stops propagation to its own callers).
  • Delegates / function pointers: a @CTX_SWITCH prefix on a delegate/function parameter type
    makes the indirect call a context-switching callee (dg() @CTX_SWITCH), and a context-switching
    lambda may only bind to such a parameter. Both concrete and template value parameters are supported.
  • Lambdas infer the attribute from their body.

Commits

  1. Add Option A caller-required attributes — core attribute plumbing and the propagation/marker checks.
  2. Switch the marker to postfix callee(args) @CTX_SWITCH syntax — ergonomic call-site syntax.
  3. foreach/opApply support + participate in name mangling
    • foreach over a context-switching opApply propagates the attribute to the enclosing function;
      an opApply that itself context-switches is marked accordingly.
    • The caller-attr now participates in name mangling, but only for a function that has a
      same-name/same-type overload sibling (e.g. a plain vs. @CTX_SWITCH opApply pair). This fixes
      overload-set collisions ("skipping definition … same mangled name") without breaking cross-module
      linking — standalone caller-attr functions keep their baseline mangle, since discriminating every
      caller-attr function produces inconsistent mangles across compilation units.

Tests

  • tests/dmd/compilable/callerattr.d — propagation, markers, delegates/function pointers, lambdas, *_FAKE.
  • tests/dmd/fail_compilation/callerattr_foreach.d, callerattr_foreach_unmarked.d — foreach/opApply enforcement.

Validated end-to-end by building the Weka wekanode binary against this compiler (the migration that
adds @CTX_SWITCH annotations across the codebase lives in a separate wekapp branch).

🤖 Generated with Claude Code

Implements the generalized callerAttr facility from the design spec:
a function tagged @CTX_SWITCH (callerAttr!"NAME") is a context-switching
callee; every call must carry the member-access marker callee.NAME(args),
and the capability propagates upward (a non-@CTX_SWITCH function may not
call one). callerAttrFake is the migration shim. Lambdas infer @CTX_SWITCH
from their body; a context-switching lambda may not be passed to a plain
delegate parameter.

Frontend:
- core.attribute: callerAttr / callerAttrFake templates
- id.d: udaCallerAttr; attrib.d: isCallerAttrStruct / isCallerAttrExp
- expression.d: CallExp.markedCallerAttr
- expressionsem.d: .ATTR marker interception (resolveUFCS + DotIdExp),
  checkCallerAttr enforcement (E1/E2/E3) for direct, method, and indirect
  (delegate / function-pointer) calls; lambda inference; value-side
  argument check (checkCallerAttrArgs)

Docs: design spec + Option A implementation spec.
Tests: compilable/callerattr.d; fail_compilation/callerattr_{unmarked,
propagation,badmarker,delegate,lambda_leak}.d.
Replaces the member-access marker (callee.CTX_SWITCH(args)) with a postfix
attribute on the call. Parser change in parsePostExp adds the new expression
grammar (PostfixExpression '@' Identifier); the member-access interception in
resolveUFCS/visit(DotIdExp) is removed. checkCallerAttr now resolves the raw
marker identifier through its callerAttr alias. Enforcement, lambda inference
and the value-side argument check are unchanged.

Note: unlike the member-access form, this `@`-postfix grammar is intrusive to
third-party D parsers (libdparse/DCD/serve-d) until they are taught it.

Tests and the implementation spec updated to the new syntax.
Extends the Option A caller-required-attribute feature (@CTX_SWITCH):

- foreach over @CTX_SWITCH opApply: statementsem auto-marks the lowered
  opApply call (CallExp.callerAttrAutoMarked) and propagates the attribute
  to the enclosing function; funcsem adds an overload tie-breaker so the
  @CTX_SWITCH opApply overload is selected; expressionsem reports the
  propagation error at the context-switching call site.
- CallExp.syntaxCopy copies markedCallerAttr so markers survive template
  instantiation.
- dmangle: caller-attr now participates in name mangling, but ONLY when the
  function has a same-name/same-type overload sibling (the real collision,
  e.g. RobinHashTable's plain vs @CTX_SWITCH opApply). Standalone caller-attr
  functions keep their baseline mangle, so cross-module references resolve.
- tests: compilable foreach cases + fail_compilation/callerattr_foreach{,_unmarked}.d.
Add .gitignore for the out-of-source /build/ dir.
… syntax

Replace the postfix `callee() @CTX_SWITCH` marker with a prefix `@CTX_SWITCH callee()`
form.

Parser (dmd/parse.d):
- Remove the postfix `@`-marker handling from parsePostExp.
- Add a prefix `@`-marker case in parseUnaryExp: `@MARK` binds the following
  unary expression and attaches the marker to its (outermost) CallExp.
- Add statement-level disambiguation in parseStatement: a statement starting with
  `@` is routed to expression parsing only when, after skipAttributes, what follows
  is not a declaration and not an attribute scope (`:`) or block (`{`); otherwise it
  remains a declaration. This resolves the new `@CTX_SWITCH yield();` vs `@safe void f()`
  ambiguity that the prefix form introduces.

Diagnostics (dmd/expressionsem.d): E2 suggested-fix wording now reads
`must be marked `@CTX_SWITCH callee()``; comments updated.

Tests/docs: all callerattr tests and the walkthrough doc updated to the prefix form.
Switch the call-site marker from prefix to the glued/infix form
`callee@CTX_SWITCH(args)` (handled in parsePostExp via a pendingCallerAttr
stashed on @name and attached to the next CallExp). This removes the
statement-level @-ambiguity the prefix form introduced (no Phobos regression).

Enforcement is unchanged: E1 (propagation), E2 (must-mark), E3 (marker on a
non-attr callee is an error) all still apply.
…reen baseline)

Snapshot of the callerattr-option-a working tree that produces the ldc-base
image (642510c03f462ee0) building wekapp weka 6.0.0.3189 green.

- Layer 2: fold caller-attr into the TypeFunction type identity
  (foldParamCallerAttrs / foldFuncDeclCallerAttrs), asymmetric implicit-conversion
  rule (callerAttrsCovariant), type-level deco mangling, foreach/opApply overload
  selection reflection, clean hdrgen rendering.
- druntime core.attribute: rename callerAttrFake -> callerAttrUnchecked.
- Fix (this baseline): gate FAKE (@mayYieldUnchecked) caller-attrs OUT of the
  symbol mangle (dmangle.d mangleCallerAttrs: `if (fake) return`) so standalone
  boundary functions keep baseline names -> no cross-unit "undefined symbol"
  (e.g. ReactorThreadPool.submitTask); real @mayYield still mangles (YR...).
  Also invalidate fd.mangleString on the function-side fold (funcsem.d) so a
  mangle taken before the fold is recomputed.
- Tests: callerattr* compilable/fail_compilation/runnable, incl. new
  callerattr_alias_overload / callerattr_overload.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant