diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 67 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 124 |
2 files changed, 117 insertions, 74 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index cd86ca2e..d613ad1e 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -4311,11 +4311,11 @@ namespace { { const auto& trait = dep->m_trait.m_path; - ImplRef best_impl; - unsigned int count = 0; // Check for trait impl if( trait.m_path != ::HIR::SimplePath() ) { + ImplRef best_impl; + unsigned int count = 0; bool found = context.m_resolve.find_trait_impls(sp, trait.m_path, trait.m_params, src, [&](auto impl, auto cmp) { DEBUG("TraitObject coerce from - cmp="<<cmp<<", " << impl); count ++; @@ -4395,17 +4395,37 @@ namespace { if( H::type_is_bounded(src) ) { const auto& lang_Unsize = context.m_crate.get_lang_item_path(sp, "unsize"); + DEBUG("Search for `Unsize<" << dst << ">` impl for `" << src << "`"); + + ImplRef best_impl; + unsigned int count = 0; ::HIR::PathParams pp { dst.clone() }; - bool found = context.m_resolve.find_trait_impls(sp, lang_Unsize, pp, src, [](auto , auto){ return true; }); + bool found = context.m_resolve.find_trait_impls(sp, lang_Unsize, pp, src, [&best_impl,&count](auto impl, bool fuzzy){ + DEBUG("[check_unsize_tys] Found impl " << impl << (fuzzy ? " (fuzzy)" : "")); + if( impl.more_specific_than(best_impl) ) + { + best_impl = mv$(impl); + count ++; + } + // TODO: Record the best impl (if fuzzy) and equate params + return !fuzzy; + }); if( found ) { return CoerceResult::Unsize; } + else if( count == 1 ) + { + auto pp = best_impl.get_trait_params(); + DEBUG("Fuzzy, best was Unsize" << pp); + context.equate_types(sp, dst, pp.m_types.at(0)); + return CoerceResult::Unsize; + } else { // TODO: Fuzzy? - //this->context.equate_types(sp, *e.inner, *s_e.inner); + //context.equate_types(sp, *e.inner, *s_e.inner); } } @@ -4613,14 +4633,12 @@ namespace { // Any other type, check for pointer // - If not a pointer, return Equality - TU_MATCH_DEF(::HIR::TypeRef::Data, (src.m_data), (se), - ( - // NOTE: ! should be handled above or in caller? - return CoerceResult::Equality; - ), - (Infer, - // If the other side isn't a pointer, equate + if(const auto* sep = src.m_data.opt_Infer()) + { + const auto& se = *sep; ASSERT_BUG(sp, ! dst.m_data.is_Infer(), "Already handled?"); + + // If the other side isn't a pointer, equate if( dst.m_data.is_Pointer() || dst.m_data.is_Borrow() ) { context.possible_equate_type_coerce_to(se.index, dst); @@ -4630,8 +4648,10 @@ namespace { { return CoerceResult::Equality; } - ), - (Pointer, + } + else if(const auto* sep = src.m_data.opt_Pointer()) + { + const auto& se = *sep; if( const auto* dep = dst.m_data.opt_Infer() ) { context.possible_equate_type_coerce_from(dep->index, src); @@ -4660,7 +4680,7 @@ namespace { auto& node_ptr = *node_ptr_ptr; // Add cast down auto span = node_ptr->span(); - node_ptr->m_res_type = src.clone(); + //node_ptr->m_res_type = src.clone(); node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), dst.clone() )); node_ptr->m_res_type = dst.clone(); @@ -4676,8 +4696,10 @@ namespace { ERROR(sp, E0000, "Type mismatch between " << dst << " and " << src << " - Pointer mutability differs"); } return CoerceResult::Equality; - ), - (Borrow, + } + else if(const auto* sep = src.m_data.opt_Borrow()) + { + const auto& se = *sep; if( const auto* dep = dst.m_data.opt_Infer() ) { context.possible_equate_type_coerce_from(dep->index, src); @@ -4747,7 +4769,7 @@ namespace { if( node_ptr_ptr ) { // > Goes from `src` -> `*src` -> `&`dep->type` `*src` - const auto& inner_ty = *se.inner; + const auto inner_ty = se.inner->clone(); auto dst_bt = dep->type; auto new_type = ::HIR::TypeRef::new_borrow(dst_bt, inner_ty.clone()); @@ -4819,8 +4841,12 @@ namespace { // TODO: Error here? return CoerceResult::Equality; } - ) - ) + } + else + { + // TODO: ! should be handled above or in caller? + return CoerceResult::Equality; + } } bool check_coerce(Context& context, const Context::Coercion& v) { @@ -5881,7 +5907,8 @@ void Typecheck_Code_CS(const typeck::ModuleState& ms, t_args& args, const ::HIR: for(size_t i = 0; i < context.link_coerce.size(); ) { auto ent = mv$(context.link_coerce[i]); - const auto& src_ty = (**ent.right_node_ptr).m_res_type; + auto& src_ty = (**ent.right_node_ptr).m_res_type; + //src_ty = context.m_resolve.expand_associated_types( (*ent.right_node_ptr)->span(), mv$(src_ty) ); ent.left_ty = context.m_resolve.expand_associated_types( (*ent.right_node_ptr)->span(), mv$(ent.left_ty) ); if( check_coerce(context, ent) ) { diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index f56be694..dab633ec 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -939,9 +939,16 @@ void TraitResolution::prep_indexes() ), (TraitBound, DEBUG("[prep_indexes] `" << be.type << " : " << be.trait); + // Explicitly listed bounds for( const auto& tb : be.trait.m_type_bounds ) { DEBUG("[prep_indexes] Equality (TB) - <" << be.type << " as " << be.trait.m_path << ">::" << tb.first << " = " << tb.second); - auto ty_l = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), be.trait.m_path.clone(), tb.first ) ); + + // Locate the source trait + ::HIR::GenericPath source_trait_path; + bool rv = this->trait_contains_type(sp, be.trait.m_path, m_crate.get_trait_by_path(sp, be.trait.m_path.m_path), tb.first, source_trait_path); + ASSERT_BUG(sp, rv, "Can't find `" << tb.first << "` in " << be.trait.m_path); + + auto ty_l = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), mv$(source_trait_path), tb.first ) ); ty_l.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); add_equality( mv$(ty_l), tb.second.clone() ); @@ -964,20 +971,29 @@ void TraitResolution::prep_indexes() }; const auto& trait = m_crate.get_trait_by_path(sp, be.trait.m_path.m_path); + // Bounds implied by associated trait bounds on the parent trait for(const auto& a_ty : trait.m_types) { ::HIR::TypeRef ty_a; - for( const auto& a_ty_b : a_ty.second.m_trait_bounds ) { + for( const auto& a_ty_b : a_ty.second.m_trait_bounds ) + { DEBUG("[prep_indexes] (Assoc) " << a_ty_b); + const auto& itrait = m_crate.get_trait_by_path(sp, a_ty_b.m_path.m_path); auto trait_mono = monomorphise_traitpath_with(sp, a_ty_b, cb_mono, false); - for( auto& tb : trait_mono.m_type_bounds ) { + for( auto& tb : trait_mono.m_type_bounds ) + { if( ty_a == ::HIR::TypeRef() ) { ty_a = ::HIR::TypeRef( ::HIR::Path( be.type.clone(), be.trait.m_path.clone(), a_ty.first ) ); ty_a.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); } DEBUG("[prep_indexes] Equality (ATB) - <" << ty_a << " as " << a_ty_b.m_path << ">::" << tb.first << " = " << tb.second); - auto ty_l = ::HIR::TypeRef( ::HIR::Path( ty_a.clone(), trait_mono.m_path.clone(), tb.first ) ); + // Find the source trait for this associated type + ::HIR::GenericPath source_trait_path; + bool rv = this->trait_contains_type(sp, trait_mono.m_path, itrait, tb.first, source_trait_path); + ASSERT_BUG(sp, rv, "Can't find `" << tb.first << "` in " << trait_mono.m_path); + + auto ty_l = ::HIR::TypeRef( ::HIR::Path( ty_a.clone(), mv$(source_trait_path), tb.first ) ); ty_l.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); add_equality( mv$(ty_l), mv$(tb.second) ); @@ -1100,55 +1116,6 @@ bool TraitResolution::find_trait_impls(const Span& sp, } } - // Magic Unsize impls to trait objects - if( trait == lang_Unsize ) - { - ASSERT_BUG(sp, params.m_types.size() == 1, "Unsize trait requires a single type param"); - const auto& dst_ty = this->m_ivars.get_type(params.m_types[0]); - - if( find_trait_impls_bound(sp, trait, params, type, callback) ) - return true; - - bool rv = false; - auto cb = [&](auto new_dst) { - ::HIR::PathParams real_params { mv$(new_dst) }; - rv = callback( ImplRef(type.clone(), mv$(real_params), {}), ::HIR::Compare::Fuzzy ); - }; - //if( dst_ty.m_data.is_Infer() || type.m_data.is_Infer() ) - //{ - // rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Fuzzy ); - // return rv; - //} - auto cmp = this->can_unsize(sp, dst_ty, type, cb); - if( cmp == ::HIR::Compare::Equal ) - { - assert(!rv); - rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Equal ); - } - return rv; - } - - // Magical CoerceUnsized impls for various types - if( trait == lang_CoerceUnsized ) { - const auto& dst_ty = params.m_types.at(0); - // - `*mut T => *const T` - TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Pointer, e, - TU_IFLET( ::HIR::TypeRef::Data, dst_ty.m_data, Pointer, de, - if( de.type < e.type ) { - auto cmp = e.inner->compare_with_placeholders(sp, *de.inner, this->m_ivars.callback_resolve_infer()); - if( cmp != ::HIR::Compare::Unequal ) - { - ::HIR::PathParams pp; - pp.m_types.push_back( dst_ty.clone() ); - if( callback( ImplRef(type.clone(), mv$(pp), {}), cmp ) ) { - return true; - } - } - } - ) - ) - } - // Magic impls of the Fn* traits for closure types TU_IFLET(::HIR::TypeRef::Data, type.m_data, Closure, e, DEBUG("Closure, "<< trait <<" " << trait_fn << " " << trait_fn_mut << " " << trait_fn_once); @@ -1418,6 +1385,55 @@ bool TraitResolution::find_trait_impls(const Span& sp, } ) + // Magic Unsize impls to trait objects + if( trait == lang_Unsize ) + { + ASSERT_BUG(sp, params.m_types.size() == 1, "Unsize trait requires a single type param"); + const auto& dst_ty = this->m_ivars.get_type(params.m_types[0]); + + if( find_trait_impls_bound(sp, trait, params, type, callback) ) + return true; + + bool rv = false; + auto cb = [&](auto new_dst) { + ::HIR::PathParams real_params { mv$(new_dst) }; + rv = callback( ImplRef(type.clone(), mv$(real_params), {}), ::HIR::Compare::Fuzzy ); + }; + //if( dst_ty.m_data.is_Infer() || type.m_data.is_Infer() ) + //{ + // rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Fuzzy ); + // return rv; + //} + auto cmp = this->can_unsize(sp, dst_ty, type, cb); + if( cmp == ::HIR::Compare::Equal ) + { + assert(!rv); + rv = callback( ImplRef(type.clone(), params.clone(), {}), ::HIR::Compare::Equal ); + } + return rv; + } + + // Magical CoerceUnsized impls for various types + if( trait == lang_CoerceUnsized ) { + const auto& dst_ty = params.m_types.at(0); + // - `*mut T => *const T` + TU_IFLET( ::HIR::TypeRef::Data, type.m_data, Pointer, e, + TU_IFLET( ::HIR::TypeRef::Data, dst_ty.m_data, Pointer, de, + if( de.type < e.type ) { + auto cmp = e.inner->compare_with_placeholders(sp, *de.inner, this->m_ivars.callback_resolve_infer()); + if( cmp != ::HIR::Compare::Unequal ) + { + ::HIR::PathParams pp; + pp.m_types.push_back( dst_ty.clone() ); + if( callback( ImplRef(type.clone(), mv$(pp), {}), cmp ) ) { + return true; + } + } + } + ) + ) + } + // 1. Search generic params if( find_trait_impls_bound(sp, trait, params, type, callback) ) return true; @@ -3150,7 +3166,7 @@ bool TraitResolution::trait_contains_type(const Span& sp, const ::HIR::GenericPa if( cmp != ::HIR::Compare::Equal ) { - DEBUG("> Found bound (fuzzy) " << dst_ty << "=" << be_dst << " <- " << src_ty); + DEBUG("[can_unsize] > Found bound (fuzzy) " << dst_ty << "=" << be_dst << " <- " << src_ty); rv = ::HIR::Compare::Fuzzy; } return true; |