summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir/item_path.hpp5
-rw-r--r--src/hir_conv/constant_evaluation.cpp26
-rw-r--r--src/hir_typeck/common.cpp4
-rw-r--r--src/hir_typeck/common.hpp1
4 files changed, 34 insertions, 2 deletions
diff --git a/src/hir/item_path.hpp b/src/hir/item_path.hpp
index d19435eb..d93df9e8 100644
--- a/src/hir/item_path.hpp
+++ b/src/hir/item_path.hpp
@@ -87,6 +87,11 @@ public:
return name ? name : "";
}
+ const ItemPath& get_top_ip() const {
+ if( this->parent )
+ return this->parent->get_top_ip();
+ return *this;
+ }
ItemPath operator+(const ::std::string& name) const {
return ItemPath(*this, name.c_str());
}
diff --git a/src/hir_conv/constant_evaluation.cpp b/src/hir_conv/constant_evaluation.cpp
index a4210e05..acb613be 100644
--- a/src/hir_conv/constant_evaluation.cpp
+++ b/src/hir_conv/constant_evaluation.cpp
@@ -73,6 +73,9 @@ namespace {
(Invalid,
return ::HIR::Literal();
),
+ (Defer,
+ return ::HIR::Literal::make_Defer({});
+ ),
(List,
::std::vector< ::HIR::Literal> vals;
for(const auto& val : e) {
@@ -400,8 +403,13 @@ namespace {
),
(Const,
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(); }) )
+ {
+ DEBUG("Return Literal::Defer for constant " << e2.p << " which references a generic parameter");
+ return ::HIR::Literal::make_Defer({});
+ }
MonomorphState const_ms;
- // TODO: If there's any mention of Self in this path, then return Literal::Defer
auto ent = get_ent_fullpath(state.sp, this->resolve.m_crate, p, EntNS::Value, const_ms);
MIR_ASSERT(state, ent.is_Constant(), "MIR Constant::Const(" << p << ") didn't point to a Constant - " << ent.tag_str());
const auto& c = *ent.as_Constant();
@@ -588,6 +596,8 @@ namespace {
(BinOp,
auto inval_l = read_param(e.val_l);
auto inval_r = read_param(e.val_r);
+ if( inval_l.is_Defer() || inval_r.is_Defer() )
+ return ::HIR::Literal::make_Defer({});
MIR_ASSERT(state, inval_l.tag() == inval_r.tag(), "Mismatched literal types in binop - " << inval_l << " and " << inval_r);
TU_MATCH_DEF( ::HIR::Literal, (inval_l, inval_r), (l, r),
(
@@ -654,6 +664,8 @@ namespace {
),
(UniOp,
auto inval = local_state.read_lval(e.val);
+ if( inval.is_Defer() )
+ return ::HIR::Literal::make_Defer({});
TU_IFLET( ::HIR::Literal, inval, Integer, i,
switch( e.op )
{
@@ -830,7 +842,15 @@ namespace {
const auto* mir = this->resolve.m_crate.get_or_gen_mir(ip, expr, exp);
if( mir ) {
- return evaluate_constant_mir(ip, *mir, {}, mv$(exp), {});
+ ::HIR::TypeRef ty_self { "Self", GENERIC_Self };
+ // Might want to have a fully-populated MonomorphState for expanding inside impl blocks
+ // HACK: Generate a roughly-correct one
+ MonomorphState ms;
+ const auto& top_ip = ip.get_top_ip();
+ if( top_ip.trait && !top_ip.ty ) {
+ ms.self_ty = &ty_self;
+ }
+ return evaluate_constant_mir(ip, *mir, mv$(ms), mv$(exp), {});
}
else {
BUG(this->root_span, "Attempting to evaluate constant expression with no associated code");
@@ -839,6 +859,8 @@ namespace {
void check_lit_type(const Span& sp, const ::HIR::TypeRef& type, ::HIR::Literal& lit)
{
+ if( lit.is_Defer() )
+ return ;
// TODO: Mask down limited size integers
TU_MATCHA( (type.m_data), (te),
(Infer,
diff --git a/src/hir_typeck/common.cpp b/src/hir_typeck/common.cpp
index e78ed21b..4b0328e7 100644
--- a/src/hir_typeck/common.cpp
+++ b/src/hir_typeck/common.cpp
@@ -113,6 +113,10 @@ bool visit_ty_with(const ::HIR::TypeRef& ty, t_cb_visit_ty callback)
)
return false;
}
+bool visit_path_tys_with(const ::HIR::Path& path, t_cb_visit_ty callback)
+{
+ return visit_ty_with__path(path, callback);
+}
bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl)
{
diff --git a/src/hir_typeck/common.hpp b/src/hir_typeck/common.hpp
index 09a5d9b2..14d9162f 100644
--- a/src/hir_typeck/common.hpp
+++ b/src/hir_typeck/common.hpp
@@ -33,6 +33,7 @@ typedef ::std::function<bool(const ::HIR::TypeRef&)> t_cb_visit_ty;
/// Calls the provided callback on every type seen when recursing the type.
/// If the callback returns `true`, no further types are visited and the function returns `true`.
extern bool visit_ty_with(const ::HIR::TypeRef& ty, t_cb_visit_ty callback);
+extern bool visit_path_tys_with(const ::HIR::Path& ty, t_cb_visit_ty callback);
typedef ::std::function<bool(const ::HIR::TypeRef&, ::HIR::TypeRef&)> t_cb_clone_ty;
/// Clones a type, calling the provided callback on every type (optionally providing a replacement)