diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr.cpp | 16 | ||||
-rw-r--r-- | src/hir_typeck/expr.hpp | 3 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 133 |
3 files changed, 151 insertions, 1 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 4fb8cc9f..c090bf80 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1499,6 +1499,22 @@ namespace typeck { void visit(::HIR::ExprNode_Field& node) override { ::HIR::ExprVisitorDef::visit(node); + + ::HIR::TypeRef out_type; + unsigned int deref_count = this->context.autoderef_find_field(node.span(), node.m_value->m_res_type, node.m_field, out_type); + if( deref_count != ~0u ) + { + assert( out_type != ::HIR::TypeRef() ); + 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; + } + this->context.apply_equality(node.span(), node.m_res_type, out_type); + } } // - PathValue: Insert type from path void visit(::HIR::ExprNode_PathValue& node) override diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp index a3a5147b..18523823 100644 --- a/src/hir_typeck/expr.hpp +++ b/src/hir_typeck/expr.hpp @@ -152,6 +152,9 @@ public: unsigned int autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const; bool find_method(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& method_name, /* Out -> */::HIR::Path& fcn_path) const; + unsigned int autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; + bool find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_type) const; + public: ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> callback_resolve_infer() { return [&](const auto& ty)->const auto& { diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 4c0ae071..92a996a8 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -1605,7 +1605,23 @@ bool typeck::TypecheckContext::find_method(const Span& sp, const ::HIR::TypeRef& } TU_IFLET(::HIR::TypeRef::Data, ty.m_data, TraitObject, e, - // TODO: Search methods on object's traits + // TODO: This _Should_ be set, but almost needs a pass? + //assert( e.m_trait.m_trait_ptr ); + //const auto& trait = *e.m_trait.m_trait_ptr; + const auto& trait = this->m_crate.get_trait_by_path(sp, e.m_trait.m_path.m_path); + auto it = trait.m_values.find( method_name ); + if( it != trait.m_values.end() ) + { + if( it->second.is_Function() ) { + fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({ + box$( ty.clone() ), + e.m_trait.m_path.clone(), + method_name, + {} + }) ); + return true; + } + } ) TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e, @@ -1681,6 +1697,121 @@ bool typeck::TypecheckContext::find_method(const Span& sp, const ::HIR::TypeRef& return false; } +unsigned int typeck::TypecheckContext::autoderef_find_field(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string& field_name, /* Out -> */::HIR::TypeRef& field_type) const +{ + unsigned int deref_count = 0; + ::HIR::TypeRef tmp_type; // Temporary type used for handling Deref + const auto* current_ty = &top_ty; + TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e, + current_ty = &*e.inner; + deref_count += 1; + ) + + do { + const auto& ty = this->get_type(*current_ty); + if( ty.m_data.is_Infer() ) { + return ~0u; + } + + if( this->find_field(sp, ty, field_name, field_type) ) { + return deref_count; + } + + // 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; + } + } + } while( current_ty ); + + TU_IFLET(::HIR::TypeRef::Data, this->get_type(top_ty).m_data, Borrow, e, + const auto& ty = this->get_type(top_ty); + + if( find_field(sp, ty, field_name, field_type) ) { + return 0; + } + ) + + // Dereference failed! This is a hard error (hitting _ is checked above and returns ~0) + this->dump(); + TODO(sp, "Error when no field could be found, but type is known - (: " << top_ty << ")." << field_name); +} +bool typeck::TypecheckContext::find_field(const Span& sp, const ::HIR::TypeRef& ty, const ::std::string& name, /* Out -> */::HIR::TypeRef& field_ty) const +{ + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Path, e, + TU_MATCH(::HIR::TypeRef::TypePathBinding, (e.binding), (be), + (Unbound, + // Wut? + TODO(sp, "Handle TypePathBinding::Unbound - " << ty); + ), + (Opaque, + // Ignore, no fields on an opaque + ), + (Struct, + // Has fields! + const auto& str = *be; + TU_MATCH(::HIR::Struct::Data, (str.m_data), (se), + (Unit, + // No fields on a unit struct + ), + (Tuple, + for( unsigned int i = 0; i < se.size(); i ++ ) + { + // TODO: Privacy + if( FMT(i) == name ) { + field_ty = monomorphise_type_with(sp, se[i].ent, [&](const auto& gt)->const auto&{ TODO(sp, "Monomorphise tuple struct field types"); return gt; }); + return true; + } + } + ), + (Named, + for( const auto& fld : se ) + { + // TODO: Privacy + if( fld.first == name ) { + field_ty = monomorphise_type_with(sp, fld.second.ent, [&](const auto& gt)->const auto&{ TODO(sp, "Monomorphise named struct field types"); return gt; }); + return true; + } + } + ) + ) + ), + (Enum, + // No fields on enums either + ) + ) + ) + else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Tuple, e, + for( unsigned int i = 0; i < e.size(); i ++ ) + { + if( FMT(i) == name ) { + field_ty = e[i].clone(); + return true; + } + } + ) + else { + } + return false; +} // ------------------------------------------------------------------------------------------------------------------- |