ADR-0016: Preview Feature Infrastructure
Status
Implemented
Summary
Complete the preview feature infrastructure by threading PreviewFeatures through the compiler pipeline to Sema, implementing the require_preview() gating method, and introducing a permanently-unstable test_infra feature as both a testing fixture and usage example.
Context
ADR-0005 introduced the preview feature system design, but the implementation was incomplete:
Missing pipeline threading: The
--previewflag is parsed at the CLI and stored inCompileOptions, butpreview_featuresnever reachesSemawhere feature gates are checked.No gating mechanism:
Semalacks arequire_preview()method, so there's no way to actually gate feature usage.Empty enum instability: When
MutableStringswas stabilized (makingPreviewFeatureempty), various places broke becausematchon an empty enum has edge cases. Having at least one permanent variant solves this.No example usage: New contributors have no working example of how to gate a feature at each compiler stage.
The current data flow is:
CLI (--preview flag) → CompileOptions.preview_features → compile_with_options() → [dead end]
What we need:
CLI → CompileOptions → compile_frontend_*() → Sema::new(preview_features) → require_preview() checks
Why Sema is Sufficient
Later stages (CfgBuilder, codegen, regalloc, emit, link) do not need preview feature access because:
Sema is the decision point: It decides what semantics to apply and encodes those decisions in the typed AIR.
Later stages are implementation points: They process the AIR that Sema already approved. They don't make policy decisions.
Feature semantics become data: For example, inout parameters are represented as
param_modes: Vec<bool>in AIR/CFG. Codegen doesn't ask "is inout enabled?" - it seesparam_modes[i] = trueand generates appropriate code.Rejected code never reaches codegen: If Sema errors on ungated feature usage, later stages never see it.
This architecture is intentional and matches how Zig and Rust handle feature gating.
Decision
1. Thread PreviewFeatures to Sema
Add preview_features to the compilation pipeline:
// gruel-compiler/src/lib.rs
Update the call in compile_with_options() to pass the features through.
2. Add preview_features to Sema
// gruel-air/src/sema.rs
3. Introduce test_infra permanently-unstable feature
Add a new preview feature that is never stabilized:
// gruel-error/src/lib.rs
This feature:
- Provides a permanent variant so the enum is never empty
- Serves as documentation/example for how to implement feature gates
- Can be used in CI to verify the infrastructure works
- Gates a trivial no-op intrinsic (
@test_preview_gate()) that can be used in tests
4. Add @test_preview_gate() intrinsic
A minimal gated intrinsic that:
- Requires
--preview test_infrato use - Takes no arguments, returns
() - Does nothing at runtime
- Exercises the full pipeline from lexer through codegen
// Only compiles with --preview test_infra
fn main() -> i32 {
@test_preview_gate();
0
}
5. Update test helpers
Add preview feature support to the in-process test helpers:
// gruel-compiler/src/lib.rs (test module)
Implementation Phases
- Phase 1: Pipeline threading - gruel-0slf.1
- Phase 2: Gating method - gruel-0slf.2
- Phase 3: test_infra feature - gruel-0slf.3
- Phase 4: Cleanup - gruel-0slf.4
Consequences
Positive
- Complete infrastructure: Preview features now actually work end-to-end
- Stable enum:
PreviewFeaturealways has at least one variant - Living documentation:
test_infrashows exactly how to gate a feature - CI validation: Infrastructure can be tested without depending on real features
- Simpler stabilization: Future features can be stabilized without worrying about empty enum edge cases
Negative
- Extra variant: One permanently-unstable feature exists just for testing
- Trivial intrinsic:
@test_preview_gate()has no real use beyond testing
Neutral
- This is purely infrastructure; no user-facing language changes
Open Questions
None - this is a straightforward infrastructure completion.
Future Work
- Consider adding
--preview allfor convenience during development - Add a CI job that verifies preview feature gating works correctly
References
- ADR-0005: Preview Features (original design)
- ADR-0014: Mutable Strings (first feature to use the system, now stabilized)