diff options
author | John Hodge <tpg@mutabah.net> | 2018-12-22 18:31:15 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-12-22 18:31:15 +0800 |
commit | 883cf34da3e273cd3878026d855b9579055c09c0 (patch) | |
tree | 789c9b807454aaae94a89bc5d31c81d664ef9ddb /src | |
parent | d0e127f48e35ec7ad95b1c595c259f91c20628b8 (diff) | |
download | mrust-883cf34da3e273cd3878026d855b9579055c09c0.tar.gz |
Constant Evaluation - Evaluate missing associated constants with trait impl versions
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/expr_ptr.cpp | 7 | ||||
-rw-r--r-- | src/hir/expr_ptr.hpp | 1 | ||||
-rw-r--r-- | src/hir_conv/bind.cpp | 3 | ||||
-rw-r--r-- | src/hir_conv/constant_evaluation.cpp | 115 | ||||
-rw-r--r-- | src/trans/enumerate.cpp | 3 | ||||
-rw-r--r-- | src/trans/trans_list.hpp | 1 |
6 files changed, 107 insertions, 23 deletions
diff --git a/src/hir/expr_ptr.cpp b/src/hir/expr_ptr.cpp index fcef34bd..7b3a6811 100644 --- a/src/hir/expr_ptr.cpp +++ b/src/hir/expr_ptr.cpp @@ -45,6 +45,13 @@ } +const Span& HIR::ExprPtr::span() const +{ + static Span static_sp; + if( *this ) + return (*this)->span(); + return static_sp; +} const ::MIR::Function* HIR::ExprPtr::get_mir_opt() const { if(!this->m_mir) diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp index b510e737..58fa3762 100644 --- a/src/hir/expr_ptr.hpp +++ b/src/hir/expr_ptr.hpp @@ -105,6 +105,7 @@ public: ::HIR::ExprNode* get() const { return node.get(); } void reset(::HIR::ExprNode* p) { node.reset(p); } + const Span& span() const; ::HIR::ExprNode& operator*() { return *node; } const ::HIR::ExprNode& operator*() const { return *node; } ::HIR::ExprNode* operator->() { return &*node; } diff --git a/src/hir_conv/bind.cpp b/src/hir_conv/bind.cpp index 227ccd9f..37a6e494 100644 --- a/src/hir_conv/bind.cpp +++ b/src/hir_conv/bind.cpp @@ -140,6 +140,9 @@ namespace { TU_MATCH(::HIR::Literal, (lit), (e), (Invalid, ), + (Defer, + // Shouldn't happen here, but ... + ), (List, for(auto& val : e) { visit_literal(sp, val); diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp index acb613be..78148ba4 100644 --- a/src/hir_conv/constant_evaluation.cpp +++ b/src/hir_conv/constant_evaluation.cpp @@ -16,6 +16,8 @@ #include <trans/target.hpp> #include <hir/expr_state.hpp> +#include <trans/monomorphise.hpp> // For handling monomorph of MIR in provided associated constants + #define CHECK_DEFER(var) do { if( var.is_Defer() ) { m_rv = ::HIR::Literal::make_Defer({}); return ; } } while(0) namespace { @@ -382,29 +384,24 @@ namespace { LocalState local_state( state, retval, args, locals ); auto const_to_lit = [&](const ::MIR::Constant& c)->::HIR::Literal { - TU_MATCH(::MIR::Constant, (c), (e2), - (Int, + TU_MATCH_HDR( (c), {) + TU_ARM(c, Int, e2) { return ::HIR::Literal(static_cast<uint64_t>(e2.v)); - ), - (Uint, + } + TU_ARM(c, Uint, e2) return ::HIR::Literal(e2.v); - ), - (Float, + TU_ARM(c, Float, e2) return ::HIR::Literal(e2.v); - ), - (Bool, + TU_ARM(c, Bool, e2) return ::HIR::Literal(static_cast<uint64_t>(e2.v)); - ), - (Bytes, + TU_ARM(c, Bytes, e2) return ::HIR::Literal::make_String({e2.begin(), e2.end()}); - ), - (StaticString, + TU_ARM(c, StaticString, e2) return ::HIR::Literal(e2); - ), - (Const, + TU_ARM(c, Const, e2) { auto p = ms.monomorph(state.sp, e2.p); // If there's any mention of generics in this path, then return Literal::Defer - if( visit_path_tys_with(e2.p, [&](const auto& ty)->bool { return ty.m_data.is_Generic(); }) ) + if( visit_path_tys_with(p, [&](const auto& ty)->bool { return ty.m_data.is_Generic(); }) ) { DEBUG("Return Literal::Defer for constant " << e2.p << " which references a generic parameter"); return ::HIR::Literal::make_Defer({}); @@ -418,7 +415,7 @@ namespace { auto& item = const_cast<::HIR::Constant&>(c); // Challenge: Adding items to the module might invalidate an iterator. ::HIR::ItemPath mod_ip { item.m_value.m_state->m_mod_path }; - auto eval = Evaluator { item.m_value->span(), resolve.m_crate, NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") } }; + auto eval = Evaluator { item.m_value.span(), resolve.m_crate, NewvalState { item.m_value.m_state->m_module, mod_ip, FMT(&c << "$") } }; DEBUG("- Evaluate " << p); DEBUG("- " << ::HIR::ItemPath(p)); item.m_value_res = eval.evaluate_constant(::HIR::ItemPath(p), item.m_value, item.m_type.clone()); @@ -426,11 +423,10 @@ namespace { //check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); } return clone_literal( c.m_value_res ); - ), - (ItemAddr, + } + TU_ARM(c, ItemAddr, e2) return ::HIR::Literal::make_BorrowPath( ms.monomorph(state.sp, e2) ); - ) - ) + } throw ""; }; auto read_param = [&](const ::MIR::Param& p) -> ::HIR::Literal @@ -961,6 +957,79 @@ namespace { m_mod_path = saved_mp; } + void visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) override + { + static Span sp; + TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type); + const auto& trait = m_crate.get_trait_by_path(sp, trait_path); + + StaticTraitResolve resolve( m_crate ); + // - TODO: Defer this call until first missing item? + resolve.set_impl_generics(impl.m_params); + + auto mp = ::HIR::ItemPath(impl.m_src_module); + m_mod_path = ∓ + m_mod = &m_crate.get_mod_by_path(sp, impl.m_src_module); + + for(const auto& vi : trait.m_values) + { + // Search for any constants that are in the trait itself, but NOT in this impl + // - For each of these, find the lowest parent specialisation with the constant set + // - Ensure that the MIR has been generated for the constant (TODO: This only needs to be done for + // specialisations, not trait-provided) + // - Monomorphise the MIR for this impl, and let expansion happen as usual + if( vi.second.is_Constant() ) + { + if( impl.m_constants.count(vi.first) > 0 ) + continue; + DEBUG("- Constant " << vi.first << " missing, looking for a source"); + // This trait impl doesn't have this constant, need to find the provided version that applies + + MonomorphState ms; + ms.self_ty = &impl.m_type; + ms.pp_impl = &impl.m_trait_args; + + resolve.find_impl(sp, trait_path, impl.m_trait_args, impl.m_type, [&](ImplRef found_impl, bool is_fuzzed)->bool { + ASSERT_BUG(sp, found_impl.m_data.is_TraitImpl(), ""); + // If this found impl is the current one, keep searching + if( found_impl.m_data.as_TraitImpl().impl == &impl ) + return false; + TODO(sp, "Found a possible parent specialisation of " << trait_path << impl.m_trait_args << " for " << impl.m_type << " - " << found_impl); + return false; + }); + const auto& template_const = vi.second.as_Constant(); + if( template_const.m_value_res.is_Defer() ) { + auto eval = Evaluator { sp, m_crate, NewvalState { *m_mod, *m_mod_path, FMT("impl" << &impl << "$" << vi.first << "$") } }; + ::HIR::ExprPtr ep; + Trans_Params tp(sp); + tp.self_type = ms.self_ty->clone(); + tp.pp_impl = ms.pp_impl->clone(); + ep.m_mir = Trans_Monomorphise(resolve, mv$(tp), template_const.m_value.m_mir); + ep.m_state = ::HIR::ExprStatePtr( ::HIR::ExprState(*m_mod, m_mod_path->get_simple_path()) ); + ep.m_state->stage = ::HIR::ExprState::Stage::Mir; + impl.m_constants.insert(::std::make_pair( + vi.first, + ::HIR::TraitImpl::ImplEnt<::HIR::Constant> { + /*is_specialisable=*/false, + ::HIR::Constant { + template_const.m_params.clone(), + /*m_type=*/ms.monomorph(sp, template_const.m_type), + /*m_value=*/mv$(ep), + ::HIR::Literal() + } + } + )); + } + else { + TODO(sp, "Assign associated type " << vi.first << " in impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type); + } + } + } + ::HIR::Visitor::visit_trait_impl(trait_path, impl); + m_mod = nullptr; + m_mod_path = nullptr; + } + void visit_type(::HIR::TypeRef& ty) override { ::HIR::Visitor::visit_type(ty); @@ -988,12 +1057,12 @@ namespace { ::HIR::Visitor::visit_constant(p, item); // NOTE: Consteval needed here for MIR match generation to work - if( item.m_value ) + if( item.m_value || item.m_value.m_mir ) { - auto eval = Evaluator { item.m_value->span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; + auto eval = Evaluator { item.m_value.span(), m_crate, NewvalState { *m_mod, *m_mod_path, FMT(p.get_name() << "$") } }; item.m_value_res = eval.evaluate_constant(p, item.m_value, item.m_type.clone()); - check_lit_type(item.m_value->span(), item.m_type, item.m_value_res); + check_lit_type(item.m_value.span(), item.m_type, item.m_value_res); DEBUG("constant: " << item.m_type << " = " << item.m_value_res); } diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp index e16f9dcf..ce3eb53a 100644 --- a/src/trans/enumerate.cpp +++ b/src/trans/enumerate.cpp @@ -1599,6 +1599,9 @@ void Trans_Enumerate_FillFrom_Literal(EnumState& state, const ::HIR::Literal& li TU_MATCHA( (lit), (e), (Invalid, ), + (Defer, + // TODO: Bug? + ), (List, for(const auto& v : e) Trans_Enumerate_FillFrom_Literal(state, v, pp); diff --git a/src/trans/trans_list.hpp b/src/trans/trans_list.hpp index 703180fd..b58a241d 100644 --- a/src/trans/trans_list.hpp +++ b/src/trans/trans_list.hpp @@ -18,6 +18,7 @@ class Function; class Static; } +// TODO: This is very similar to "hir_typeck/common.hpp" MonomorphState struct Trans_Params { Span sp; |