summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-10-07 13:51:40 +0800
committerJohn Hodge <tpg@mutabah.net>2016-10-07 13:51:40 +0800
commit4cc6a2e6c83a9578fbee858affaf4932bfa13cd5 (patch)
tree248a2a4fc5fb75341d4aed16c22cf5d37e2cb33a /src
parent11c077f6f9fa2b97da1cb5e6ac9659d88092d371 (diff)
downloadmrust-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.hpp32
-rw-r--r--src/hir_typeck/expr_check.cpp23
-rw-r--r--src/hir_typeck/helpers.cpp45
-rw-r--r--src/hir_typeck/static.cpp2
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