Skip to content

Remove preset macros and constructs#242

Merged
soareschen merged 2 commits into
mainfrom
remove-preset-macros
Jun 28, 2026
Merged

Remove preset macros and constructs#242
soareschen merged 2 commits into
mainfrom
remove-preset-macros

Conversation

@soareschen

@soareschen soareschen commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

AI Overview

This PR removes the entire CGP preset feature — the cgp_preset! macro and every construct that existed to support it — because presets have been fully superseded by the newer CGP namespace feature. It is a pure deletion: a single commit on the remove-preset-macros branch that touches 48 files, removes roughly 3,360 lines, and adds only 3. No new functionality is introduced here, since the replacement (namespaces) already landed on main earlier; this change simply retires the old mechanism now that nothing in the CGP ecosystem needs it.

The headline consequence is that this is a breaking change. Any downstream crate that still writes presets will stop compiling after upgrading, and must migrate to namespaces. That migration has already been completed in the CGP projects that relied on presets, most notably Hypershell, whose contexts inherited their wiring from a HypershellPreset.

Why presets are being removed

Presets and namespaces solve the same problem — letting a context inherit and reuse a large bundle of component wirings — but they solve it in fundamentally different ways, and the namespace approach is strictly better. Understanding that difference explains why the whole preset subsystem can now be deleted rather than kept around.

Presets worked by copying mapping entries between modules at macro-expansion time. A preset was not a normal type; it was a module generated by cgp_preset! that carried its component map plus extra macros and re-exports needed to "merge" itself into other presets. Because the merging happened in macros, which cannot see real type information, a preset's source module had to be wrapped in #[re_export_imports] so that its imports could be re-exported and made visible to the copying machinery. Inheritance (PresetB: PresetA + ...), conflict resolution (the override keyword), and the underlying substitution (replace_with!) all existed to make this macro-level copying behave like real inheritance.

Namespaces achieve the same composition through the trait system itself, with no macro copying. Instead of duplicating entries, a namespace sets up a path-based redirection: component traits are tagged with #[prefix(@Key in Namespace)], a cgp_namespace! block maps each component to a path key, and a delegate_components! block opts in with a namespace MyNamespace; directive. Lookups then resolve through ordinary trait resolution (RedirectLookup over PathCons path keys) rather than through generated, module-local macros. The result is fewer moving parts, no re-export gymnastics, and inheritance that the compiler reasons about directly.

Because namespaces never depended on any of the preset plumbing, removing presets does not weaken CGP — it removes a parallel, more fragile mechanism that namespaces had already made redundant.

What was removed

The change deletes both the user-facing macros and the internal machinery that backed them. At the public-API level, four constructs disappear from the cgp and cgp-core preludes and re-exports:

  • cgp_preset! — the macro that defined a module-based, inheritable component map.
  • #[cgp_inherit(Preset)] — the attribute that let a context delegate all of a preset's keys to that preset's provider.
  • #[re_export_imports] — the wrapper attribute that re-exported a preset module's imports so the merging macros could find them. This is also dropped from the top-level cgp::re_export_imports and cgp_core::re_export_imports re-export paths.
  • replace_with! — the substitution helper used during preset merging.

Underneath those macros, the procedural-macro crate (cgp-macro-lib) loses the substantial body of code that implemented them. Entire modules are deleted: the preset parser (parse/, covering define_preset, delegate_components, path, and type_spec), the preset codegen (preset/, covering impl_is_preset and substitution_macro), the delegate_components/impl_delegate helper, the for_each_replace substitution engine, and the re_export_imports / replace_with entry points. The matching cgp_preset and cgp_inherit entry points are removed from cgp-macro. The net effect on the macro crate is a meaningful simplification — there is simply less metaprogramming to maintain.

The test suite is pruned to match. The complete preset_tests/ tree is removed — the basic, generics, generics_inheritance, inheritance, nested_inheritance, and wrapped scenarios, along with the preset.rs test entry that included them. One preset-specific sub-test (test_delegate_new_value_in_preset) is also stripped out of the otherwise-unrelated new_struct.rs delegation test, which is the only edit to a file that survives.

Impacts

The effects of this PR fall into three groups: a breaking change for users, a smaller public surface, and a lighter codebase to maintain.

Downstream code that uses presets will no longer compile. This is the only behavioral impact users will feel, and it is unavoidable for a removal of this kind. Projects must replace cgp_preset! definitions, #[cgp_inherit] context wiring, and the surrounding #[re_export_imports] modules with the equivalent namespace constructs (cgp_namespace!, #[prefix(...)] on component traits, and the namespace ...; directive in delegate_components!). The reference migration already exists in Hypershell, which moved its HypershellPreset-based contexts over to namespaces, so adopters have a concrete example to follow.

The public API of cgp and cgp-core shrinks by four macros. Anyone importing the prelude no longer receives cgp_preset, cgp_inherit, re_export_imports, or replace_with, and the two crate-root re_export_imports re-exports are gone. This makes the surface area smaller and the supported way to compose wirings unambiguous: namespaces.

The macro implementation becomes significantly simpler. Removing roughly 3,360 lines — most of it intricate token-level parsing and substitution in cgp-macro-lib — eliminates a whole class of macro-hygiene and merging edge cases that the preset feature was prone to. This lowers the long-term maintenance burden and reduces the risk surface of the procedural macros.

@soareschen soareschen merged commit 28f0235 into main Jun 28, 2026
5 checks passed
@soareschen soareschen deleted the remove-preset-macros branch June 28, 2026 14:23
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