diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hir_typeck/expr.cpp | 7 | ||||
-rw-r--r-- | src/hir_typeck/expr.hpp | 2 | ||||
-rw-r--r-- | src/hir_typeck/expr_context.cpp | 136 |
3 files changed, 134 insertions, 11 deletions
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 0db51ffc..6c762ddb 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1542,6 +1542,7 @@ namespace typeck { cache.m_monomorph_cb = mv$(monomorph_cb); } + // --- Apply equalities from return and arguments --- for( unsigned int i = arg_ofs; i < cache.m_arg_types.size() - 1; i ++ ) { auto& arg_expr_ptr = args[i - arg_ofs]; @@ -1550,14 +1551,10 @@ namespace typeck { this->context.apply_equality(sp, arg_ty, arg_expr_ptr->m_res_type, &arg_expr_ptr); } - // TODO: Remove if not needed - // HACK: Expand UFCS again - cache.m_arg_types.back() = this->context.expand_associated_types(sp, mv$(cache.m_arg_types.back())); - DEBUG("RV " << cache.m_arg_types.back()); this->context.apply_equality(sp, res_type, cache.m_arg_types.back(), &this_node_ptr); - // Check generic bounds (after links between args and params are known) + // --- Check generic bounds (after links between args and params are known) --- // - HACK! Below just handles closures and fn traits. // - TODO: Make this FAR more generic than it is for(const auto& bound : cache.m_fcn_params->m_bounds) diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp index 9972e8e4..43003cf2 100644 --- a/src/hir_typeck/expr.hpp +++ b/src/hir_typeck/expr.hpp @@ -92,6 +92,8 @@ public: bool pathparams_contain_ivars(const ::HIR::PathParams& pps) const; bool type_contains_ivars(const ::HIR::TypeRef& ty) const; + bool pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const; + bool types_equal(const ::HIR::TypeRef& l, const ::HIR::TypeRef& r) const; /// Adds a local variable binding (type is mutable so it can be inferred if required) void add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type); diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp index 8659e1de..bb7bd325 100644 --- a/src/hir_typeck/expr_context.cpp +++ b/src/hir_typeck/expr_context.cpp @@ -184,7 +184,114 @@ bool typeck::TypecheckContext::type_contains_ivars(const ::HIR::TypeRef& ty) con throw ""; } - +namespace { + bool type_list_equal(const typeck::TypecheckContext& context, const ::std::vector< ::HIR::TypeRef>& l, const ::std::vector< ::HIR::TypeRef>& r) + { + if( l.size() != r.size() ) + return false; + + for( unsigned int i = 0; i < l.size(); i ++ ) { + if( !context.types_equal(l[i], r[i]) ) + return false; + } + return true; + } +} +bool typeck::TypecheckContext::pathparams_equal(const ::HIR::PathParams& pps_l, const ::HIR::PathParams& pps_r) const +{ + return type_list_equal(*this, pps_l.m_types, pps_r.m_types); +} +bool typeck::TypecheckContext::types_equal(const ::HIR::TypeRef& rl, const ::HIR::TypeRef& rr) const +{ + const auto& l = this->get_type(rl); + const auto& r = this->get_type(rr); + if( l.m_data.tag() != r.m_data.tag() ) + return false; + + TU_MATCH(::HIR::TypeRef::Data, (l.m_data, r.m_data), (le, re), + (Infer, return le.index == re.index; ), + (Primitive, return le == re; ), + (Diverge, return true; ), + (Generic, return le.binding == re.binding; ), + (Path, + if( le.path.m_data.tag() != re.path.m_data.tag() ) + return false; + TU_MATCH(::HIR::Path::Data, (le.path.m_data, re.path.m_data), (lpe, rpe), + (Generic, + if( lpe.m_path != rpe.m_path ) + return false; + return pathparams_equal(lpe.m_params, rpe.m_params); + ), + (UfcsKnown, + if( lpe.item != rpe.item ) + return false; + if( types_equal(*lpe.type, *rpe.type) ) + return false; + if( pathparams_equal(lpe.trait.m_params, rpe.trait.m_params) ) + return false; + return pathparams_equal(lpe.params, rpe.params); + ), + (UfcsInherent, + if( lpe.item != rpe.item ) + return false; + if( types_equal(*lpe.type, *rpe.type) ) + return false; + return pathparams_equal(lpe.params, rpe.params); + ), + (UfcsUnknown, + BUG(Span(), "UfcsUnknown"); + ) + ) + ), + (Borrow, + if( le.type != re.type ) + return false; + return types_equal(*le.inner, *re.inner); + ), + (Pointer, + if( le.type != re.type ) + return false; + return types_equal(*le.inner, *re.inner); + ), + (Slice, + return types_equal(*le.inner, *re.inner); + ), + (Array, + if( le.size_val != re.size_val ) + return false; + return types_equal(*le.inner, *re.inner); + ), + (Closure, + if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) ) + return false; + return types_equal(*le.m_rettype, *re.m_rettype); + ), + (Function, + if( !type_list_equal(*this, le.m_arg_types, re.m_arg_types) ) + return false; + return types_equal(*le.m_rettype, *re.m_rettype); + ), + (TraitObject, + if( le.m_markers.size() != re.m_markers.size() ) + return false; + for(unsigned int i = 0; i < le.m_markers.size(); i ++) { + const auto& lm = le.m_markers[i]; + const auto& rm = re.m_markers[i]; + if( lm.m_path != rm.m_path ) + return false; + if( ! pathparams_equal(lm.m_params, rm.m_params) ) + return false; + } + if( le.m_trait.m_path.m_path != re.m_trait.m_path.m_path ) + return false; + return pathparams_equal(le.m_trait.m_path.m_params, re.m_trait.m_path.m_params); + ), + (Tuple, + return type_list_equal(*this, le, re); + ) + ) + throw ""; +} /// /// Add inferrence variables to the provided type (if they're not already set) @@ -438,7 +545,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Type mismatch in struct pattern - " << type << " is not " << e.path); ), (Infer, throw ""; ), (Path, @@ -462,7 +569,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Type mismatch in struct pattern - " << type << " is not " << e.path); ), (Infer, throw ""; ), (Path, @@ -507,7 +614,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Type mismatch in enum pattern - " << type << " is not " << e.path); ), (Infer, throw ""; ), (Path, @@ -549,7 +656,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Type mismatch in enum pattern - " << type << " is not " << e.path); ), (Infer, throw ""; ), (Path, @@ -576,7 +683,7 @@ void typeck::TypecheckContext::add_binding(const Span& sp, ::HIR::Pattern& pat, TU_MATCH_DEF(::HIR::TypeRef::Data, (type.m_data), (te), ( - // TODO: Type mismatch + ERROR(sp, E0000, "Type mismatch in enum pattern - " << type << " is not " << e.path); ), (Infer, throw ""; ), (Path, @@ -896,6 +1003,23 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR } } + DEBUG("CoerceUnsized - " << this->type_contains_ivars(l_t) << this->type_contains_ivars(r_t) << this->types_equal(l_t, r_t)); + if( !this->type_contains_ivars(l_t) && !this->type_contains_ivars(r_t) && !this->types_equal(l_t, r_t) ) + { + // TODO: If the types are fully known, and not equal. Search for CoerceUnsized + ::HIR::PathParams pp; + pp.m_types.push_back( l_t.clone() ); + bool succ = this->find_trait_impls(sp, this->m_crate.get_lang_item_path(sp, "coerce_unsized"), pp, r_t, [&](const auto& args, const auto& ) { + DEBUG("- Found coerce_unsized from " << l_t << " to " << r_t); + return true; + }); + if( succ ) + { + // TODO: + TODO(sp, "Apply CoerceUnsized - " << l_t << " <- " << r_t); + } + } + // - If tags don't match, error if( l_t.m_data.tag() != r_t.m_data.tag() ) { |