Skip to content

RFC: Module prepend#29

Open
stakach wants to merge 4 commits into
crystal-lang:masterfrom
stakach:rfc/module-prepend
Open

RFC: Module prepend#29
stakach wants to merge 4 commits into
crystal-lang:masterfrom
stakach:rfc/module-prepend

Conversation

@stakach
Copy link
Copy Markdown

@stakach stakach commented May 23, 2026

Rendered: https://github.com/stakach/rfcs/blob/rfc/module-prepend/text/0029-module-prepend.md

Summary

Add prepend as a class/module/struct body keyword, analogous to include and extend, that inserts a module ahead of the host in its method-resolution order. Methods defined in the prepended module override the host's same-named methods and can delegate to them with super — giving Crystal a first-class way to express wrapper / "around" patterns without monkey-patching, proxies, or macro rewriting.

class Service
  prepend Tracer
  def foo; do_work; end
end

Tracer#foo runs first; its super reaches Service#foo. Multiple prepends stack; prepended joins included / extended as a macro hook; cyclic prepends are caught at compile time. The host's own super is unchanged — wrappers see the host, the host doesn't see the wrappers.

Motivation

#10504 — Crystal has no first-class wrapping mechanism today. Logging, instrumentation, retries, transactions and other cross-cutting concerns currently require either previous_def (forces edits to the host), proxies (object identity changes), or macro-rewrites (high-friction, per-wrapper boilerplate). prepend collapses all of those workarounds into a one-line declarative form that composes — and brings Crystal to parity with Ruby's Module#prepend, easing porting in both directions.

Status

Drafted at the user-visible-semantics level. Reference-level explanation covers the lookup-chain change, super semantics (the symmetry/asymmetry between wrapper and host), the prepended macro hook, ancestor exposure to macros, and the cycle / non-module / self errors. Deferred / unresolved questions: post-definition Module.prepend, prepend into generic-module instances, and the precise scope of the prepend keyword reservation.

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