summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir_typeck/expr.cpp16
-rw-r--r--src/hir_typeck/expr.hpp3
-rw-r--r--src/hir_typeck/expr_context.cpp133
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;
+}
// -------------------------------------------------------------------------------------------------------------------