summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/type.cpp42
-rw-r--r--src/hir_typeck/expr_cs.cpp26
2 files changed, 66 insertions, 2 deletions
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index 998314fa..58530a76 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -511,9 +511,49 @@ bool ::HIR::TypeRef::match_test_generics(const Span& sp, const ::HIR::TypeRef& x
::HIR::Compare HIR::TypeRef::compare_with_placeholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const
{
TRACE_FUNCTION_F(*this << " ?= " << x);
- assert( !this->m_data.is_Infer() );
const auto& right = (x.m_data.is_Infer() ? resolve_placeholder(x) : (x.m_data.is_Generic() ? resolve_placeholder(x) : x));
+ // If left is infer
+ TU_IFLET(::HIR::TypeRef::Data, this->m_data, Infer, e,
+ switch(e.ty_class)
+ {
+ case ::HIR::InferClass::None:
+ return Compare::Fuzzy;
+ case ::HIR::InferClass::Integer:
+ TU_IFLET( ::HIR::TypeRef::Data, right.m_data, Primitive, le,
+ switch(le)
+ {
+ case ::HIR::CoreType::I8: case ::HIR::CoreType::U8:
+ case ::HIR::CoreType::I16: case ::HIR::CoreType::U16:
+ case ::HIR::CoreType::I32: case ::HIR::CoreType::U32:
+ case ::HIR::CoreType::I64: case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::Isize: case ::HIR::CoreType::Usize:
+ return Compare::Fuzzy;
+ default:
+ return Compare::Unequal;
+ }
+ )
+ else {
+ return Compare::Unequal;
+ }
+ case ::HIR::InferClass::Float:
+ TU_IFLET( ::HIR::TypeRef::Data, right.m_data, Primitive, le,
+ switch(le)
+ {
+ case ::HIR::CoreType::F32:
+ case ::HIR::CoreType::F64:
+ return Compare::Fuzzy;
+ default:
+ return Compare::Unequal;
+ }
+ )
+ else {
+ return Compare::Unequal;
+ }
+ }
+ throw "";
+ )
+
// If righthand side is infer, it's a fuzzy match (or not a match)
TU_IFLET(::HIR::TypeRef::Data, right.m_data, Infer, e,
switch( e.ty_class )
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index f3c7b8d7..6e26b33a 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -734,6 +734,25 @@ namespace {
assert(fields_ptr);
const ::HIR::t_struct_fields& fields = *fields_ptr;
+ const auto& ty_params = node.m_path.m_params.m_types;
+ auto monomorph_cb = [&](const auto& gt)->const auto& {
+ const auto& ge = gt.m_data.as_Generic();
+ if( ge.binding == 0xFFFF ) {
+ return ty;
+ }
+ else if( ge.binding < 256 ) {
+ if( ge.binding >= ty_params.size() ) {
+ BUG(node.span(), "Type parameter index out of range (#" << ge.binding << " " << ge.name << ")");
+ }
+ return ty_params[ge.binding];
+ }
+ else {
+ BUG(node.span(), "Method-level parameter on struct (#" << ge.binding << " " << ge.name << ")");
+ }
+ };
+
+ node.m_value_types.resize( fields.size() );
+
// Bind fields with type params (coercable)
for( auto& val : node.m_values)
{
@@ -741,9 +760,14 @@ namespace {
auto it = ::std::find_if(fields.begin(), fields.end(), [&](const auto& v)->bool{ return v.first == name; });
assert(it != fields.end());
const auto& des_ty_r = it->second.ent;
+ auto& des_ty_cache = node.m_value_types[it - fields.begin()];
if( monomorphise_type_needed(des_ty_r) ) {
- TODO(node.span(), "Monomorphise struct variant type");
+ if( des_ty_cache == ::HIR::TypeRef() ) {
+ des_ty_cache = monomorphise_type_with(node.span(), des_ty_r, monomorph_cb);
+ }
+ // TODO: Is it an error when it's already populated?
+ this->context.equate_types_coerce(node.span(), des_ty_cache, val.second);
}
else {
this->context.equate_types_coerce(node.span(), des_ty_r, val.second);