Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7fbfa26
Implement derive codegen via HirBuilder during lowering
micahscopes May 17, 2026
262ffec
Wire CTFE machine derive mode: Symbolic ExprId handling at BinOp/Fiel…
micahscopes May 17, 2026
b31902a
Fix salsa cycle: use TyId::unit placeholder for strategy T parameter
micahscopes May 17, 2026
91abb8e
Add CTFE machine interception points for derive mode
micahscopes May 17, 2026
a1475c1
Replace blanket type-check filter with surgical DynField deferred typing
micahscopes May 17, 2026
9271050
Add deferred BinOp lowering for strategy bodies in SMIR
micahscopes May 17, 2026
673b755
Add SMIR relaxed lowering for strategy bodies (partial)
micahscopes May 17, 2026
113844e
CTFE drives Eq derive output end-to-end via HIR walker
micahscopes May 17, 2026
b0f9fe5
WIP: HIR walker handles Eq/Ord, needs Default/Hash
micahscopes May 17, 2026
ca9de9d
All 11 derive tests pass via CTFE HIR walker
micahscopes May 17, 2026
50bfb2e
Delete pattern evaluator from production path
micahscopes May 17, 2026
21325c1
Clean up CTFE machine: remove dead SMIR derive code, HIR walker is pr…
micahscopes May 17, 2026
c90b0f3
Remove dead SMIR machine derive mode — HIR walker is sole path
micahscopes May 17, 2026
7973f4a
Fix Ord lexicographic ordering + add correctness tests
micahscopes May 17, 2026
2996f0f
Add tests proving strategy body drives output
micahscopes May 17, 2026
5dea9b0
Harden derive HIR walker: fix double-emission, remove dead code, add …
micahscopes May 18, 2026
ee7d105
Replace hardcoded Ord le/gt/ge with Fe strategies, add capability-bas…
micahscopes May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/common/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ pub enum DiagnosticPass {
MsgLower,
EventLower,
ErrorLower,
DeriveLower,
ArithmeticAttr,
PayableAttr,

Expand Down Expand Up @@ -215,6 +216,7 @@ impl DiagnosticPass {
Self::MsgLower => 9,
Self::EventLower => 10,
Self::ErrorLower => 16,
Self::DeriveLower => 17,
Self::ArithmeticAttr => 12,
Self::PayableAttr => 13,
Self::InlineAttr => 14,
Expand Down
20 changes: 18 additions & 2 deletions crates/hir/src/analysis/analysis_pass.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::analysis::{HirAnalysisDb, diagnostics::DiagnosticVoucher};
use crate::{
ArithmeticAttrError, ErrorDiagnostic, EventError, InlineAttrError, LoopUnrollAttrError,
ParserError, PayableError, SelectorError,
ArithmeticAttrError, DeriveError, ErrorDiagnostic, EventError, InlineAttrError,
LoopUnrollAttrError, ParserError, PayableError, SelectorError,
hir_def::{ModuleTree, TopLevelMod},
lower::{parse_file_impl, scope_graph_impl},
};
Expand Down Expand Up @@ -131,6 +131,22 @@ impl ModuleAnalysisPass for ErrorLowerPass {
}
}

/// Analysis pass that collects derive lowering errors from `#[derive(...)]` struct desugaring.
pub struct DeriveLowerPass {}

impl ModuleAnalysisPass for DeriveLowerPass {
fn run_on_module<'db>(
&mut self,
db: &'db dyn HirAnalysisDb,
top_mod: TopLevelMod<'db>,
) -> Vec<Box<dyn DiagnosticVoucher>> {
scope_graph_impl::accumulated::<DeriveError>(db, top_mod)
.into_iter()
.map(|d| Box::new(d.clone()) as _)
.collect::<Vec<_>>()
}
}

/// Analysis pass that collects arithmetic attribute validation errors.
pub struct ArithmeticAttrPass {}

Expand Down
46 changes: 46 additions & 0 deletions crates/hir/src/analysis/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,52 @@ impl DiagnosticVoucher for crate::ErrorDiagnostic {
}
}

impl DiagnosticVoucher for crate::DeriveError {
fn to_complete(&self, _db: &dyn SpannedHirAnalysisDb) -> CompleteDiagnostic {
use crate::DeriveErrorKind;

let primary_span = Span::new(self.file, self.primary_range, SpanKind::Original);

let (code, message, label, notes) = match &self.kind {
DeriveErrorKind::DeriveOnEnum => (
1,
"`#[derive]` is only valid on structs".to_string(),
"`#[derive]` cannot be applied to enums".to_string(),
vec!["move `#[derive]` to a struct declaration".to_string()],
),
DeriveErrorKind::DeriveOnGenericStruct { trait_name } => (
2,
format!("`#[derive({trait_name})]` structs must be non-generic"),
"generics are not supported on derived structs".to_string(),
vec!["remove generic parameters from the struct".to_string()],
),
DeriveErrorKind::UnknownDeriveTrait { name } => (
3,
format!("unknown derive trait `{name}`"),
format!("`{name}` is not a recognized derive trait"),
vec![format!(
"recognized traits: {}",
crate::lower::derive::KNOWN_DERIVE_TRAITS.join(", ")
)],
),
};

let error_code = GlobalErrorCode::new(DiagnosticPass::DeriveLower, code);

CompleteDiagnostic::new(
Severity::Error,
message,
vec![SubDiagnostic::new(
LabelStyle::Primary,
label,
Some(primary_span),
)],
notes,
error_code,
)
}
}

impl DiagnosticVoucher for crate::InlineAttrError {
fn to_complete(&self, _db: &dyn SpannedHirAnalysisDb) -> CompleteDiagnostic {
use crate::hir_def::InlineAttrErrorKind;
Expand Down
5 changes: 3 additions & 2 deletions crates/hir/src/analysis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub mod place;
pub mod semantic;

use self::analysis_pass::{
AnalysisPassManager, ArithmeticAttrPass, ErrorLowerPass, EventLowerPass, InlineAttrPass,
LoopUnrollAttrPass, MsgLowerPass, ParsingPass, PayableAttrPass,
AnalysisPassManager, ArithmeticAttrPass, DeriveLowerPass, ErrorLowerPass, EventLowerPass,
InlineAttrPass, LoopUnrollAttrPass, MsgLowerPass, ParsingPass, PayableAttrPass,
};
use self::name_resolution::ImportAnalysisPass;
use self::ty::{
Expand All @@ -33,6 +33,7 @@ pub fn initialize_analysis_pass() -> AnalysisPassManager {
pass_manager.add_module_pass("MsgLower", Box::new(MsgLowerPass {}));
pass_manager.add_module_pass("EventLower", Box::new(EventLowerPass {}));
pass_manager.add_module_pass("ErrorLower", Box::new(ErrorLowerPass {}));
pass_manager.add_module_pass("DeriveLower", Box::new(DeriveLowerPass {}));
pass_manager.add_module_pass("InlineAttr", Box::new(InlineAttrPass {}));
pass_manager.add_module_pass("LoopUnrollAttr", Box::new(LoopUnrollAttrPass {}));
pass_manager.add_module_pass("MsgSelector", Box::new(MsgSelectorAnalysisPass {}));
Expand Down
1 change: 1 addition & 0 deletions crates/hir/src/analysis/semantic/borrowck/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ impl<'db> NormalizeCtxt<'db> {
place,
}
}
SExpr::DynField { base, .. } => NExpr::Use(self.normalize_operand(*base, origin)),
SExpr::Index { base, index } => {
let place = self.project_local_place(
base.value,
Expand Down
1 change: 1 addition & 0 deletions crates/hir/src/analysis/semantic/ctfe/canonicalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ fn writable_local_roots<'db>(
| SExpr::ExtractEnumField { .. }
| SExpr::CodeRegionOffset { .. }
| SExpr::CodeRegionLen { .. }
| SExpr::DynField { .. }
| SExpr::Call { .. } => {}
}
}
Expand Down
Loading
Loading