From 7b0545f876708877560db69a5cf19cf4eeda5c83 Mon Sep 17 00:00:00 2001 From: Ajrat Makhmutov Date: Tue, 19 May 2026 17:29:07 +0300 Subject: [PATCH 1/2] hir_expand/static_borrow: Catch Defer from extracted-static const-eval This is necessary because the evaluator throws Defer when a dependency isn't resolved yet, but the SBC call sites had no try/catch, so a deferred eval propagated to std::terminate and aborted libcore on aarch64 once an earlier compare fix let the pass reach those cases. Handling Defer here mirrors what Constant Evaluate already does for the same situation. --- src/hir_conv/constant_evaluation.cpp | 2 +- src/hir_conv/constant_evaluation.hpp | 6 ++++++ src/hir_expand/static_borrow_constants.cpp | 21 +++++++++++++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index 039349b65..552939bf7 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -28,7 +28,7 @@ namespace { void ConvertHIR_ConstantEvaluate_Static(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::ItemPath& ip, ::HIR::Static& e); void ConvertHIR_ConstantEvaluate_FcnSig(const ::HIR::Crate& crate, const ::HIR::GenericParams* impl_params, const ::HIR::ItemPath& ip, ::HIR::Function& fcn); - struct Defer {}; + using HIR::Defer; struct NewvalState : public HIR::Evaluator::Newval diff --git a/src/hir_conv/constant_evaluation.hpp b/src/hir_conv/constant_evaluation.hpp index 7683c4b9d..b84050709 100644 --- a/src/hir_conv/constant_evaluation.hpp +++ b/src/hir_conv/constant_evaluation.hpp @@ -16,6 +16,12 @@ namespace MIR { namespace HIR { +// Thrown by Evaluator::evaluate_constant when some dependency of the +// constant being evaluated is itself not yet resolved (typically still a +// generic parameter or an inferred type). Callers outside this module are +// expected to catch and treat as "leave for a later pass to retry". +struct Defer {}; + struct Evaluator { class Newval diff --git a/src/hir_expand/static_borrow_constants.cpp b/src/hir_expand/static_borrow_constants.cpp index 5aaadd112..cbc53198c 100644 --- a/src/hir_expand/static_borrow_constants.cpp +++ b/src/hir_expand/static_borrow_constants.cpp @@ -1159,8 +1159,16 @@ namespace static_borrow_constants { if( !new_static.m_params.is_generic() ) { new_static.m_value.m_state->stage = ::HIR::ExprState::Stage::Sbc; - new_static.m_value_res = ::HIR::Evaluator(sp, m_crate, nvs).evaluate_constant( new_static_pair.path, new_static.m_value, new_static.m_type.clone()); - new_static.m_value_generated = true; + try { + new_static.m_value_res = ::HIR::Evaluator(sp, m_crate, nvs).evaluate_constant( new_static_pair.path, new_static.m_value, new_static.m_type.clone()); + new_static.m_value_generated = true; + } + catch(const ::HIR::Defer&) { + // A dependency is not fully resolved yet; leave the + // extracted static value as not-generated and let the + // subsequent passes pick it up rather than aborting. + DEBUG("Deferred static borrow eval: " << new_static_pair.path); + } } struct H { @@ -1402,8 +1410,13 @@ void HIR_Expand_StaticBorrowConstants_Expr(const ::HIR::Crate& crate, const ::HI if( !new_static.m_params.is_generic() ) { new_static.m_value.m_state->stage = ::HIR::ExprState::Stage::Sbc; - new_static.m_value_res = ::HIR::Evaluator(sp, crate, nvs).evaluate_constant( path, new_static.m_value, new_static.m_type.clone()); - new_static.m_value_generated = true; + try { + new_static.m_value_res = ::HIR::Evaluator(sp, crate, nvs).evaluate_constant( path, new_static.m_value, new_static.m_type.clone()); + new_static.m_value_generated = true; + } + catch(const ::HIR::Defer&) { + DEBUG("Deferred static borrow eval: " << path); + } } DEBUG(path << " = ?"); From 199b0121a0419515fcf2413fa9a96b1058139348 Mon Sep 17 00:00:00 2001 From: Ajrat Makhmutov Date: Sat, 23 May 2026 18:43:59 +0300 Subject: [PATCH 2/2] hir_expand/static_borrow: Keep lifted-static generic when source has const-generic This is necessary because extract_node's visitor doesn't enumerate every HIR construct that can carry a const-generic value-param reference; ARM Neon's core_arch::arm_shared::neon::generated lifted const blocks (vshl and friends) end up with _0 = Constant(N/*M:0*/) in the lifted static's MIR with the method-scope binding never remapped, then assert in MonomorphiserPP::get_value because params_def had been wiped to concrete. Until the visitor is exhaustively audited, suppress the wipe whenever the surrounding impl/item has any const-generic value-param -- it just defers the constant evaluation to Trans Monomorph, which already handles genuinely generic statics. --- src/hir_expand/static_borrow_constants.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/hir_expand/static_borrow_constants.cpp b/src/hir_expand/static_borrow_constants.cpp index cbc53198c..a37c3de36 100644 --- a/src/hir_expand/static_borrow_constants.cpp +++ b/src/hir_expand/static_borrow_constants.cpp @@ -910,7 +910,23 @@ namespace static_borrow_constants { } v(resolve, monomorph); node->visit(v); v.visit_type(node->m_res_type); - if( !v.is_generic ) { + // `is_generic` is set by the targeted visit overrides above + // (ExprNode_ConstParam, ExprNode_ArraySized) plus visit_type / + // visit_path_params. Those reliably cover type- and lifetime- + // generic references, but a const-generic value param can still + // leak through paths not yet enumerated -- e.g. ARM Neon's + // `core_arch::arm_shared::neon::generated` lifted const blocks + // hit `_ = Constant(N/*M:0*/)` in MIR with the surrounding + // method's `const N: i32` never remapped, then assert in + // MonomorphiserPP::get_value because the lifted static was + // wiped to a concrete (empty params) item. Preserve the params + // whenever the source context carries any const-generic value + // param: the only cost is a slightly later (Trans Monomorph) + // evaluation instead of an SBC-time concrete one. + bool has_value_generics = + !m_resolve.impl_generics().m_values.empty() + || !m_resolve.item_generics().m_values.empty(); + if( !v.is_generic && !has_value_generics ) { params_def = HIR::GenericParams(); constr_params = HIR::PathParams(); DEBUG("Concrete static");