diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 25 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 38 |
2 files changed, 61 insertions, 2 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 729571d3..e8bf8842 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -3004,7 +3004,6 @@ namespace { return true; } - // If either side (or both) are ivars, then coercion can't be known yet - but they could be equal // TODO: Fix and deduplicate the following code for InferClass::Diverge @@ -3219,7 +3218,29 @@ namespace { return true; } - // TODO: CoerceUnsized trait + // CoerceUnsized trait + // - Only valid for generic or path destination types + if( ty_dst.m_data.is_Generic() || ty_dst.m_data.is_Path() ) { + + const auto& lang_CoerceUnsized = context.m_crate.get_lang_item_path(sp, "coerce_unsized"); + ::HIR::PathParams pp; + pp.m_types.push_back( ty_dst.clone() ); + bool found = context.m_resolve.find_trait_impls(sp, lang_CoerceUnsized, pp, ty_src, [&](auto impl, auto cmp) { + // TODO: Allow fuzzy match if only match + return cmp == ::HIR::Compare::Equal; + }); + if( found ) + { + DEBUG("- CoerceUnsize " << &*node_ptr << " -> " << ty_dst); + + TODO(sp, "Add Coerce op applying to pointer type for " << ty_src << " -> " << ty_dst); + //add_coerce_borrow(context, node_ptr, ty_dst, [&](auto& node_ptr) { + // auto span = node_ptr->span(); + // node_ptr = NEWNODE( ty_dst.clone(), span, _Unsize, mv$(node_ptr), ty_dst.clone() ); + // }); + return true; + } + } // 1. Check that the source type can coerce TU_MATCH( ::HIR::TypeRef::Data, (ty_src.m_data), (e), diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index ec62bcfe..b5a122ae 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1109,6 +1109,44 @@ bool TraitResolution::find_trait_impls(const Span& sp, } } } + + if( trait == m_crate.get_lang_item_path(sp, "unsize") ) + { + ASSERT_BUG(sp, params.m_types.size() == 1, ""); + const auto& dst_ty = m_ivars.get_type( params.m_types[0] ); + if( ! dst_ty.m_data.is_TraitObject() ) { + // If the destination isn't a trait object, don't even bother + return false; + } + const auto& e2 = dst_ty.m_data.as_TraitObject(); + + auto cmp = ::HIR::Compare::Equal; + + // TODO: Fuzzy compare + if( e2.m_trait != e.m_trait ) { + return false; + } + // The destination must have a strict subset of marker traits. + const auto& src_markers = e.m_markers; + const auto& dst_markers = e2.m_markers; + for(const auto& mt : dst_markers) + { + // TODO: Fuzzy match + bool found = false; + for(const auto& omt : src_markers) { + if( omt == mt ) { + found = true; + break; + } + } + if( !found ) { + // Return early. + return false; + } + } + + return callback( ImplRef(&type, &e.m_trait.m_path.m_params, &e.m_trait.m_type_bounds), cmp ); + } ) // 1. Search generic params |