diff options
author | John Hodge <tpg@mutabah.net> | 2016-07-08 18:01:34 +1000 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-07-08 18:01:34 +1000 |
commit | afbfbec7595cddc00700c5c13bc9e1d7ae6ff78e (patch) | |
tree | 3c4180f17657182dcc7a53051e258b853114eb6f /src | |
parent | 2fb86967142f5ee4e7a5e62457baedf040783461 (diff) | |
download | mrust-afbfbec7595cddc00700c5c13bc9e1d7ae6ff78e.tar.gz |
HIR Typecheck CS - Field accesses
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr_cs.cpp | 47 | ||||
-rw-r--r-- | src/hir_typeck/helpers.hpp | 2 |
2 files changed, 45 insertions, 4 deletions
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index 75869284..91e6e351 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -1373,7 +1373,6 @@ namespace { deref_res_types.pop_back(); node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Deref(node.span(), mv$(node.m_value)) ); node.m_value->m_res_type = mv$(ty); - this->context.add_ivars( node.m_value->m_res_type ); deref_count -= 1; } @@ -1512,13 +1511,55 @@ namespace { } this->context.equate_types(node.span(), node.m_res_type, node.m_cache.m_arg_types.back()); + // TODO: Apply derefs! + node.m_method_path = mv$(fcn_path); this->m_completed = true; } } void visit(::HIR::ExprNode_Field& node) override { - // TODO: - TODO(node.span(), "ExprNode_Field - revisit"); + const auto& field_name = node.m_field; + TRACE_FUNCTION_F("(Field) name=" << field_name << ", ty = " << this->context.m_ivars.fmt_type(node.m_value->m_res_type)); + ::HIR::TypeRef out_type; + + // Using autoderef, locate this field + 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; + ::std::vector< ::HIR::TypeRef> deref_res_types; + + do { + const auto& ty = *current_ty; + if( ty.m_data.is_Infer() ) { + current_ty = nullptr; + break; + } + if( this->context.m_resolve.find_field(node.span(), ty, field_name, out_type) ) { + this->context.equate_types(node.span(), node.m_res_type, out_type); + break; + } + + deref_count += 1; + current_ty = this->context.m_resolve.autoderef(node.span(), ty, tmp_type); + if( current_ty ) + deref_res_types.push_back( current_ty->clone() ); + } while(current_ty); + + if( current_ty ) + { + if( deref_count > 0 ) + DEBUG("Adding " << deref_count << " dereferences"); + assert( deref_count == deref_res_types.size() ); + while( !deref_res_types.empty() ) + { + auto ty = mv$(deref_res_types.back()); + deref_res_types.pop_back(); + node.m_value = ::HIR::ExprNodeP( new ::HIR::ExprNode_Deref(node.span(), mv$(node.m_value)) ); + node.m_value->m_res_type = mv$(ty); + } + + m_completed = true; + } } void visit(::HIR::ExprNode_Literal& node) override { diff --git a/src/hir_typeck/helpers.hpp b/src/hir_typeck/helpers.hpp index 56106cf1..5d613a5c 100644 --- a/src/hir_typeck/helpers.hpp +++ b/src/hir_typeck/helpers.hpp @@ -177,9 +177,9 @@ public: /// Apply an automatic dereference const ::HIR::TypeRef* autoderef(const Span& sp, const ::HIR::TypeRef& ty, ::HIR::TypeRef& tmp_type) const; + bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; private: bool find_method(const Span& sp, const HIR::t_trait_list& traits, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const; - bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; /// 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; |