summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-07-08 18:01:34 +1000
committerJohn Hodge <tpg@mutabah.net>2016-07-08 18:01:34 +1000
commitafbfbec7595cddc00700c5c13bc9e1d7ae6ff78e (patch)
tree3c4180f17657182dcc7a53051e258b853114eb6f /src
parent2fb86967142f5ee4e7a5e62457baedf040783461 (diff)
downloadmrust-afbfbec7595cddc00700c5c13bc9e1d7ae6ff78e.tar.gz
HIR Typecheck CS - Field accesses
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr_cs.cpp47
-rw-r--r--src/hir_typeck/helpers.hpp2
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;