summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hir_typeck/expr_cs.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 84442a1b..5303c432 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -4452,8 +4452,38 @@ namespace {
}
return false;
}
+
+ static ::HIR::TypeRef make_pruned(Context& context, const ::HIR::TypeRef& ty)
+ {
+ const auto& binding = ty.m_data.as_Path().binding;
+ const auto& sm = binding.as_Struct()->m_struct_markings;
+ ::HIR::GenericPath gp = ty.m_data.as_Path().path.m_data.as_Generic().clone();
+ if( sm.coerce_param == ~0u ) {
+ for(size_t i = 0; i < gp.m_params.m_types.size(); i ++ )
+ gp.m_params.m_types.at(i) = context.m_ivars.new_ivar_tr();
+ }
+ else {
+ gp.m_params.m_types.at(sm.coerce_param) = context.m_ivars.new_ivar_tr();
+ }
+ return ::HIR::TypeRef::new_path(mv$(gp), binding.as_Struct());
+ }
};
+ // Coercing to a CoerceUnsized type can only happen from something of the same generic type
+ // - Create a copy of the known type, but with the `Coerce` parameter set to a new ivar
+ if( ty_src.m_data.is_Infer() && H::type_has_coerce_path(context, ty_dst) && ty_dst.m_data.as_Path().binding.is_Struct() )
+ {
+ DEBUG("Create ivar filled version of " << ty_dst);
+ context.equate_types(sp, ty_src, H::make_pruned(context, ty_dst));
+ return false;
+ }
+ if( ty_dst.m_data.is_Infer() && H::type_has_coerce_path(context, ty_src) && ty_src.m_data.as_Path().binding.is_Struct() )
+ {
+ DEBUG("Create ivar filled version of " << ty_src);
+ context.equate_types(sp, ty_dst, H::make_pruned(context, ty_src));
+ return false;
+ }
+
// CoerceUnsized trait
// - Only valid for generic or path destination types
if( ty_dst.m_data.is_Generic() || H::type_has_coerce_path(context, ty_dst) )