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..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"); @@ -1159,8 +1175,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 +1426,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 << " = ?");