diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir/type.cpp | 42 | ||||
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 26 |
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); |