summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp67
-rw-r--r--src/hir_typeck/helpers.cpp124
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;