diff options
author | John Hodge <tpg@mutabah.net> | 2016-10-07 13:51:40 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-10-07 13:51:40 +0800 |
commit | 4cc6a2e6c83a9578fbee858affaf4932bfa13cd5 (patch) | |
tree | 248a2a4fc5fb75341d4aed16c22cf5d37e2cb33a /src | |
parent | 11c077f6f9fa2b97da1cb5e6ac9659d88092d371 (diff) | |
download | mrust-4cc6a2e6c83a9578fbee858affaf4932bfa13cd5.tar.gz |
HIR Typecheck Expr - Use bounds from traits for opaque associated types
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/common.hpp | 32 | ||||
-rw-r--r-- | src/hir_typeck/expr_check.cpp | 23 | ||||
-rw-r--r-- | src/hir_typeck/helpers.cpp | 45 | ||||
-rw-r--r-- | src/hir_typeck/static.cpp | 2 |
4 files changed, 101 insertions, 1 deletions
diff --git a/src/hir_typeck/common.hpp b/src/hir_typeck/common.hpp index ff63d965..ce569351 100644 --- a/src/hir_typeck/common.hpp +++ b/src/hir_typeck/common.hpp @@ -28,4 +28,36 @@ extern ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR: extern ::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer=true); extern ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl); +static inline t_cb_generic monomorphise_type_get_cb(const Span& sp, const ::HIR::TypeRef* self_ty, const ::HIR::PathParams* params_i, const ::HIR::PathParams* params_m, const ::HIR::PathParams* params_p=nullptr) +{ + return [=](const auto& gt)->const auto& { + const auto& ge = gt.m_data.as_Generic(); + if( ge.binding == 0xFFFF ) { + ASSERT_BUG(sp, self_ty, "Self wasn't expected here"); + return *self_ty; + } + else if( (ge.binding >> 8) == 0 ) { + auto idx = ge.binding & 0xFF; + ASSERT_BUG(sp, params_i, "Impl-level params were not expected - " << gt); + ASSERT_BUG(sp, idx < params_i->m_types.size(), "Parameter out of range " << gt << " >= " << params_i->m_types.size()); + return params_i->m_types[idx]; + } + else if( (ge.binding >> 8) == 1 ) { + auto idx = ge.binding & 0xFF; + ASSERT_BUG(sp, params_m, "Method-level params were not expected - " << gt); + ASSERT_BUG(sp, idx < params_m->m_types.size(), "Parameter out of range " << gt << " >= " << params_m->m_types.size()); + return params_m->m_types[idx]; + } + else if( (ge.binding >> 8) == 2 ) { + auto idx = ge.binding & 0xFF; + ASSERT_BUG(sp, params_p, "Placeholder params were not expected - " << gt); + ASSERT_BUG(sp, idx < params_p->m_types.size(), "Parameter out of range " << gt << " >= " << params_p->m_types.size()); + return params_p->m_types[idx]; + } + else { + BUG(sp, "Invalid generic type - " << gt); + } + }; +} + extern void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct); diff --git a/src/hir_typeck/expr_check.cpp b/src/hir_typeck/expr_check.cpp index 4c372c40..fda3d51e 100644 --- a/src/hir_typeck/expr_check.cpp +++ b/src/hir_typeck/expr_check.cpp @@ -456,6 +456,25 @@ namespace { assert(fields_ptr); const ::HIR::t_struct_fields& fields = *fields_ptr; + #if 1 + 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 << ")"); + } + }; + #endif + // Bind fields with type params (coercable) for( auto& val : node.m_values) { @@ -466,11 +485,13 @@ namespace { auto& des_ty_cache = node.m_value_types[it - fields.begin()]; const auto* des_ty = &des_ty_r; - DEBUG(name << " : " << des_ty_r); if( monomorphise_type_needed(des_ty_r) ) { assert( des_ty_cache != ::HIR::TypeRef() ); + des_ty_cache = monomorphise_type_with(node.span(), des_ty_r, monomorph_cb); + m_resolve.expand_associated_types(node.span(), des_ty_cache); des_ty = &des_ty_cache; } + DEBUG("." << name << " : " << *des_ty); check_types_equal(*des_ty, val.second); } diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index 1ada84a8..a7573301 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -1256,6 +1256,45 @@ bool TraitResolution::find_trait_impls(const Span& sp, } ) + // If this type is an opaque UfcsKnown - check bounds + TU_IFLET(::HIR::TypeRef::Data, type.m_data, Path, e, + if( e.binding.is_Opaque() ) + { + ASSERT_BUG(sp, e.path.m_data.is_UfcsKnown(), "Opaque bound type wasn't UfcsKnown - " << type); + const auto& pe = e.path.m_data.as_UfcsKnown(); + + // If this associated type has a bound of the desired trait, return it. + const auto& trait_ref = m_crate.get_trait_by_path(sp, pe.trait.m_path); + ASSERT_BUG(sp, trait_ref.m_types.count( pe.item ) != 0, "Trait " << pe.trait.m_path << " doesn't contain an associated type " << pe.item); + const auto& aty_def = trait_ref.m_types.find(pe.item)->second; + + for(const auto& bound : aty_def.m_trait_bounds) + { + if( bound.m_path.m_path == trait ) + { + auto cmp = ::HIR::Compare::Equal; + if( monomorphise_pathparams_needed(bound.m_path.m_params) ) + { + auto monomorph_cb = monomorphise_type_get_cb(sp, &*pe.type, &pe.trait.m_params, nullptr, nullptr); + auto b_params_mono = monomorphise_path_params_with(sp, bound.m_path.m_params, monomorph_cb, false); + cmp = this->compare_pp(sp, b_params_mono, params); + + // TODO: bound.m_type_bounds + //if( callback( ImplRef(&type, mv$(b_params_mono), {}), cmp ) ) + if( callback( ImplRef(type.clone(), mv$(b_params_mono), {}), cmp ) ) + return true; + } + else + { + // TODO: bound.m_type_bounds + if( callback( ImplRef(&type, &bound.m_path.m_params, &null_assoc), cmp ) ) + return true; + } + } + } + } + ) + // 1. Search generic params if( find_trait_impls_bound(sp, trait, params, type, callback) ) return true; @@ -1714,6 +1753,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, DEBUG("Searching for impl"); bool can_fuzz = true; unsigned int count = 0; + bool is_specialisable = false; ImplRef best_impl; rv = this->find_trait_impls_crate(sp, trait_path.m_path, trait_path.m_params, *pe.type, [&](auto impl, auto qual) { DEBUG("[expand_associated_types__UfcsKnown] Found " << impl << " qual=" << qual); @@ -1739,6 +1779,7 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, if( impl.type_is_specialisable(pe.item.c_str()) ) { // Check if this is more specific if( impl.more_specific_than( best_impl ) ) { + is_specialisable = true; best_impl = mv$(impl); } return false; @@ -1759,6 +1800,10 @@ void TraitResolution::expand_associated_types_inplace__UfcsKnown(const Span& sp, if( can_fuzz && count > 1 ) { // Fuzzy match with multiple choices - can't know yet } + else if( is_specialisable ) { + e.binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({}); + return ; + } else { auto ty = best_impl.get_type( pe.item.c_str() ); if( ty == ::HIR::TypeRef() ) diff --git a/src/hir_typeck/static.cpp b/src/hir_typeck/static.cpp index 426f9cb0..2f971a44 100644 --- a/src/hir_typeck/static.cpp +++ b/src/hir_typeck/static.cpp @@ -735,6 +735,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI this->expand_associated_types(sp, input); return; } + /* if( best_impl.is_valid() ) { auto nt = best_impl.get_type( e2.item.c_str() ); DEBUG("Converted UfcsKnown (best specialisation) - " << e.path << " = " << nt); @@ -743,6 +744,7 @@ void StaticTraitResolve::expand_associated_types__UfcsKnown(const Span& sp, ::HI this->expand_associated_types(sp, input); return; } + */ // If the type is a generic or an opaque associated, we can't know. // - If the trait contains any of the above, it's unknowable |