summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-12 12:05:39 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-12 12:05:39 +0800
commit3135a763caba3bd0c7bead292084d371422ef901 (patch)
tree7a05def371c17f7363216931cc1f1b98db3abedb
parent25fc71ff92e8fb940377b4f4a513d535e2eb040f (diff)
downloadmrust-3135a763caba3bd0c7bead292084d371422ef901.tar.gz
HIR Typecheck - Rough index operator support
-rw-r--r--src/hir_typeck/expr.cpp63
-rw-r--r--src/hir_typeck/expr.hpp1
-rw-r--r--src/hir_typeck/expr_context.cpp68
3 files changed, 86 insertions, 46 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index cb335ad9..ed4d9965 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1065,11 +1065,66 @@ namespace typeck {
// - Index: Look for implementation of the Index trait
void visit(::HIR::ExprNode_Index& node) override
{
- this->context.find_trait_impls(this->context.m_crate.get_lang_item_path(node.span(), "index"), node.m_value->m_res_type, [&](const auto& args) {
- DEBUG("TODO: Insert index operator (if index arg matches)");
- return false;
- });
+ TRACE_FUNCTION_FR("_Index","_Index");
::HIR::ExprVisitorDef::visit(node);
+ const auto& path_Index = this->context.m_crate.get_lang_item_path(node.span(), "index");
+
+ const auto& index_ty = this->context.get_type(node.m_index->m_res_type);
+ // NOTE: Indexing triggers autoderef
+ unsigned int deref_count = 0;
+ ::HIR::TypeRef tmp_type; // Temporary type used for handling Deref
+ const auto* current_ty = &node.m_value->m_res_type;
+ do {
+ const auto& ty = this->context.get_type(*current_ty);
+ DEBUG("_Index: (: " << ty << ")[: " << index_ty << "]");
+ bool rv = this->context.find_trait_impls(path_Index, ty, [&](const auto& args) {
+ assert( args.m_types.size() == 1 );
+ const auto& impl_index = args.m_types[0];
+
+ auto cmp = impl_index.compare_with_paceholders(node.span(), index_ty, this->context.callback_resolve_infer());
+ if( cmp == ::HIR::Compare::Unequal)
+ return false;
+ if( cmp == ::HIR::Compare::Equal ) {
+ return true;
+ }
+ DEBUG("TODO: Handle fuzzy match index operator " << impl_index);
+ return false;
+ });
+ if( rv ) {
+ break;
+ }
+
+ deref_count += 1;
+ current_ty = this->context.autoderef(node.span(), ty, tmp_type);
+ } while( current_ty );
+
+ if( current_ty )
+ {
+ if( deref_count > 0 )
+ DEBUG("Adding " << deref_count << " dereferences");
+ while( deref_count > 0 )
+ {
+ node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Deref(node.span(), mv$(node.m_value)) );
+ this->context.add_ivars( node.m_value->m_res_type );
+ deref_count -= 1;
+ }
+
+ // Set output to `< "*current_ty" as Index<"index_ty> >::Output`
+ // TODO: Get the output type from the bound/impl in `find_trait_impls`
+ auto tp = ::HIR::GenericPath( path_Index );
+ tp.m_params.m_types.push_back( index_ty.clone() );
+ auto out_type = ::HIR::TypeRef::new_path(
+ ::HIR::Path(::HIR::Path::Data::Data_UfcsKnown {
+ box$(this->context.get_type(*current_ty).clone()),
+ mv$(tp),
+ "Output",
+ {}
+ }),
+ {}
+ );
+
+ this->context.apply_equality( node.span(), node.m_res_type, out_type );
+ }
}
// - Deref: Look for impl of Deref
void visit(::HIR::ExprNode_Deref& node) override
diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp
index c4e8cdc4..749c7d1a 100644
--- a/src/hir_typeck/expr.hpp
+++ b/src/hir_typeck/expr.hpp
@@ -149,6 +149,7 @@ public:
/// Locates a named method in a trait, and returns the path of the trait that contains it (with fixed parameters)
bool trait_contains_method(const Span& sp, const ::HIR::GenericPath& trait_path, const ::HIR::Trait& trait_ptr, const ::std::string& name, ::HIR::GenericPath& out_path) const;
+ const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const;
/// Locate the named method by applying auto-dereferencing.
/// \return Number of times deref was applied (or ~0 if _ was hit)
unsigned int autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const;
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index 1bbcb96a..a52d9719 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -1562,6 +1562,30 @@ bool typeck::TypecheckContext::trait_contains_method(const Span& sp, const ::HIR
// -------------------------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------------------------
+const ::HIR::TypeRef* typeck::TypecheckContext::autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const
+{
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e,
+ DEBUG("Deref " << ty << " into " << *e.inner);
+ return &*e.inner;
+ )
+ else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
+ DEBUG("Deref " << ty << " into [" << *e.inner << "]");
+ tmp_type = ::HIR::TypeRef::new_slice( e.inner->clone() );
+ return &tmp_type;
+ )
+ else {
+ // TODO: Search for a Deref impl
+ bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "deref"), ty, [&](const auto& args) {
+ return true;
+ });
+ if( succ ) {
+ TODO(sp, "Found a Deref impl for " << ty << ", use the output of it");
+ }
+ else {
+ return nullptr;
+ }
+ }
+}
unsigned int typeck::TypecheckContext::autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const
{
unsigned int deref_count = 0;
@@ -1584,27 +1608,7 @@ unsigned int typeck::TypecheckContext::autoderef_find_method(const Span& sp, con
// 3. Dereference and try again
deref_count += 1;
- TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e,
- DEBUG("Deref " << ty << " into " << *e.inner);
- current_ty = &*e.inner;
- )
- else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
- DEBUG("Deref " << ty << " into [" << *e.inner << "]");
- tmp_type = ::HIR::TypeRef::new_slice( e.inner->clone() );
- current_ty = &tmp_type;
- )
- else {
- // TODO: Search for a Deref impl
- bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "deref"), ty, [&](const auto& args) {
- return true;
- });
- if( succ ) {
- TODO(sp, "Found a Deref impl for " << ty << ", use the output of it");
- }
- else {
- current_ty = nullptr;
- }
- }
+ current_ty = this->autoderef(sp, ty, tmp_type);
} while( current_ty );
TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e,
@@ -1771,27 +1775,7 @@ unsigned int typeck::TypecheckContext::autoderef_find_field(const Span& sp, cons
// 3. Dereference and try again
deref_count += 1;
- TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e,
- DEBUG("Deref " << ty << " into " << *e.inner);
- current_ty = &*e.inner;
- )
- else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
- DEBUG("Deref " << ty << " into [" << *e.inner << "]");
- tmp_type = ::HIR::TypeRef::new_slice( e.inner->clone() );
- current_ty = &tmp_type;
- )
- else {
- // TODO: Search for a Deref impl
- bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "deref"), ty, [&](const auto& args) {
- return true;
- });
- if( succ ) {
- TODO(sp, "Found a Deref impl for " << ty << ", use the output of it");
- }
- else {
- current_ty = nullptr;
- }
- }
+ current_ty = this->autoderef(sp, ty, tmp_type);
} while( current_ty );
TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e,