diff options
author | John Hodge <tpg@ucc.asn.au> | 2016-06-09 17:04:50 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2016-06-09 17:04:50 +0800 |
commit | 01d97106b9977f5f0226b4c446616f195fbeaaf4 (patch) | |
tree | 27dde34b6c780ae0a5dfdfa32600c3d7522dbaee | |
parent | dbcc52b7a61f16893353572d4b9234967c33a39b (diff) | |
download | mrust-01d97106b9977f5f0226b4c446616f195fbeaaf4.tar.gz |
HIR Typecheck - Replace associated types with known bounds (IntoIter)
-rw-r--r-- | src/hir/path.cpp | 90 | ||||
-rw-r--r-- | src/hir/path.hpp | 12 | ||||
-rw-r--r-- | src/hir/type.cpp | 37 | ||||
-rw-r--r-- | src/hir/type.hpp | 7 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 40 |
5 files changed, 141 insertions, 45 deletions
diff --git a/src/hir/path.cpp b/src/hir/path.cpp index 4fcd46e5..6a8b2c07 100644 --- a/src/hir/path.cpp +++ b/src/hir/path.cpp @@ -144,4 +144,94 @@ namespace HIR { throw ""; } +namespace { + ::HIR::Compare compare_with_paceholders( + const Span& sp, + const ::HIR::PathParams& l, const ::HIR::PathParams& r, + ::HIR::t_cb_resolve_type resolve_placeholder + ) + { + using ::HIR::Compare; + + auto rv = Compare::Equal; + if( l.m_types.size() > 0 || r.m_types.size() > 0 ) { + if( l.m_types.size() != r.m_types.size() ) { + return Compare::Unequal; + } + for( unsigned int i = 0; i < r.m_types.size(); i ++ ) + { + auto rv2 = l.m_types[i].compare_with_paceholders( sp, r.m_types[i], resolve_placeholder ); + if( rv2 == Compare::Unequal ) + return Compare::Unequal; + if( rv2 == Compare::Fuzzy ) + rv = Compare::Fuzzy; + } + } + return rv; + } + ::HIR::Compare compare_with_paceholders( + const Span& sp, + const ::HIR::GenericPath& l, const ::HIR::GenericPath& r, + ::HIR::t_cb_resolve_type resolve_placeholder + ) + { + using ::HIR::Compare; + + if( l.m_path.m_crate_name != r.m_path.m_crate_name ) + return Compare::Unequal; + if( l.m_path.m_components.size() != r.m_path.m_components.size() ) + return Compare::Unequal; + for(unsigned int i = 0; i < l.m_path.m_components.size(); i ++ ) + { + if( l.m_path.m_components[i] != r.m_path.m_components[i] ) + return Compare::Unequal; + } + + return compare_with_paceholders(sp, l.m_params, r.m_params, resolve_placeholder); + } +} + +#define CMP(rv, cmp) do { \ + switch(cmp) {\ + case ::HIR::Compare::Unequal: return ::HIR::Compare::Unequal; \ + case ::HIR::Compare::Fuzzy: rv = ::HIR::Compare::Fuzzy; break; \ + case ::HIR::Compare::Equal: break; \ + }\ +} while(0) + +::HIR::Compare HIR::Path::compare_with_paceholders(const Span& sp, const Path& x, t_cb_resolve_type resolve_placeholder) const +{ + if( this->m_data.tag() != x.m_data.tag() ) + return Compare::Unequal; + TU_MATCH(::HIR::Path::Data, (this->m_data, x.m_data), (ple, pre), + (Generic, + return ::compare_with_paceholders(sp, ple, pre, resolve_placeholder); + ), + (UfcsUnknown, + if( ple.item != pre.item) + return Compare::Unequal; + + TODO(sp, "Path::compare_with_paceholders - UfcsUnknown"); + ), + (UfcsInherent, + if( ple.item != pre.item) + return Compare::Unequal; + ::HIR::Compare rv = ::HIR::Compare::Equal; + CMP(rv, ple.type->compare_with_paceholders(sp, *pre.type, resolve_placeholder)); + CMP(rv, ::compare_with_paceholders(sp, ple.params, pre.params, resolve_placeholder)); + return rv; + ), + (UfcsKnown, + if( ple.item != pre.item) + return Compare::Unequal; + + ::HIR::Compare rv = ::HIR::Compare::Equal; + CMP(rv, ple.type->compare_with_paceholders(sp, *pre.type, resolve_placeholder)); + CMP(rv, ::compare_with_paceholders(sp, ple.trait, pre.trait, resolve_placeholder)); + CMP(rv, ::compare_with_paceholders(sp, ple.params, pre.params, resolve_placeholder)); + return rv; + ) + ) + throw ""; +} diff --git a/src/hir/path.hpp b/src/hir/path.hpp index 89eddba1..d56b11a9 100644 --- a/src/hir/path.hpp +++ b/src/hir/path.hpp @@ -1,4 +1,5 @@ - +/* + */ #ifndef _HIR_PATH_HPP_ #define _HIR_PATH_HPP_ #pragma once @@ -6,11 +7,19 @@ #include <common.hpp> #include <tagged_union.hpp> #include <hir/type_ptr.hpp> +#include <span.hpp> namespace HIR { class Trait; +typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type; +enum Compare { + Equal, + Fuzzy, + Unequal, +}; + /// Simple path - Absolute with no generic parameters struct SimplePath { @@ -129,6 +138,7 @@ public: Path(SimplePath _); Path clone() const; + Compare compare_with_paceholders(const Span& sp, const Path& x, t_cb_resolve_type resolve_placeholder) const; friend ::std::ostream& operator<<(::std::ostream& os, const Path& x); }; diff --git a/src/hir/type.cpp b/src/hir/type.cpp index d324bc57..a4f96fa0 100644 --- a/src/hir/type.cpp +++ b/src/hir/type.cpp @@ -414,7 +414,7 @@ namespace { ) throw ""; } -::HIR::TypeRef::Compare HIR::TypeRef::compare_with_paceholders(const Span& sp, const ::HIR::TypeRef& x, ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> resolve_placeholder) const +::HIR::Compare HIR::TypeRef::compare_with_paceholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const { TRACE_FUNCTION_F(*this << " ?= " << x); assert( !this->m_data.is_Infer() ); @@ -476,40 +476,7 @@ namespace { return (le == re ? Compare::Equal : Compare::Unequal); ), (Path, - if( le.path.m_data.tag() != re.path.m_data.tag() ) - return Compare::Unequal; - TU_MATCH_DEF(::HIR::Path::Data, (le.path.m_data, re.path.m_data), (ple, pre), - ( - TODO(sp, "TypeRef::compare_with_paceholders - non-generic paths"); - ), - (Generic, - if( ple.m_path.m_crate_name != pre.m_path.m_crate_name ) - return Compare::Unequal; - if( ple.m_path.m_components.size() != pre.m_path.m_components.size() ) - return Compare::Unequal; - for(unsigned int i = 0; i < ple.m_path.m_components.size(); i ++ ) - { - if( ple.m_path.m_components[i] != pre.m_path.m_components[i] ) - return Compare::Unequal; - } - - auto rv = Compare::Equal; - if( ple.m_params.m_types.size() > 0 || pre.m_params.m_types.size() > 0 ) { - if( ple.m_params.m_types.size() != pre.m_params.m_types.size() ) { - return Compare::Unequal; - } - for( unsigned int i = 0; i < pre.m_params.m_types.size(); i ++ ) - { - auto rv2 = ple.m_params.m_types[i].compare_with_paceholders( sp, pre.m_params.m_types[i], resolve_placeholder ); - if( rv2 == Compare::Unequal ) - return Compare::Unequal; - if( rv2 == Compare::Fuzzy ) - rv = Compare::Fuzzy; - } - } - return rv; - ) - ) + return le.path.compare_with_paceholders( sp, re.path, resolve_placeholder ); ), (Generic, if( le.binding != re.binding ) diff --git a/src/hir/type.hpp b/src/hir/type.hpp index 597319a9..b3dd0fc8 100644 --- a/src/hir/type.hpp +++ b/src/hir/type.hpp @@ -15,8 +15,6 @@ class Enum; class TypeRef; -typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> t_cb_resolve_type; - enum class InferClass { None, @@ -172,11 +170,6 @@ public: // Raises a bug against `sp` if there is a form mismatch or `this` has an infer void match_generics(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder, ::std::function<void(unsigned int, const ::HIR::TypeRef&)> callback) const; - enum Compare { - Equal, - Fuzzy, - Unequal, - }; // Compares this type with another, using `resolve_placeholder` to get replacements for generics/infers in `x` Compare compare_with_paceholders(const Span& sp, const ::HIR::TypeRef& x, t_cb_resolve_type resolve_placeholder) const; }; diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp index 9bb1bcac..7b538480 100644 --- a/src/hir_typeck/expr.cpp +++ b/src/hir_typeck/expr.cpp @@ -1183,6 +1183,10 @@ namespace { (Primitive, ), (Path, + // - Only try resolving if the binding isn't known + if( !e.binding.is_Unbound() ) + return input; + TU_MATCH(::HIR::Path::Data, (e.path.m_data), (e2), (Generic, for(auto& arg : e2.m_params.m_types) @@ -1229,6 +1233,36 @@ namespace { TU_IFLET(::HIR::Path::Data, e3.path.m_data, UfcsKnown, pe, // TODO: Search for equality bounds on this associated type (e3) that match the entire type (e2) // - Does simplification of complex associated types + const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, pe.trait.m_path); + const auto& assoc_ty = trait_ptr.m_types.at(pe.item); + DEBUG("TODO: Search bounds " << assoc_ty.m_params.fmt_bounds()); + auto cb_placeholders = [&](const auto& ty)->const auto&{ + TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e, + if( e.binding == 0xFFFF ) + return *e2.type; + else + TODO(sp, "Handle type pareters when expanding associated bound"); + ) + else { + return ty; + } + }; + for(const auto& bound : assoc_ty.m_params.m_bounds) + { + TU_IFLET(::HIR::GenericBound, bound, TypeEquality, be, + // IF: bound's type matches the input, replace with bounded equality + // `<Self::IntoIter as Iterator>::Item = Self::Item` + if( be.type.compare_with_paceholders(sp, input, cb_placeholders ) ) { + if( monomorphise_type_needed(be.other_type) ) { + TODO(sp, "Monomorphise associated type replacment"); + } + else { + return be.other_type.clone(); + } + } + ) + } + DEBUG("e2 = " << *e2.type << ", input = " << input); ) ) @@ -1312,6 +1346,8 @@ namespace { return new_type; } + // TODO: If there are no ivars in this path, set its binding to Opaque + DEBUG("Couldn't resolve associated type for " << input); ), (UfcsUnknown, @@ -2215,12 +2251,12 @@ namespace { if( monomorphise_type_needed(arg_type) ) TODO(node.span(), "Compare trait type when it contains generics"); auto cmp = arg_type.compare_with_paceholders(node.span(), ty_right, this->context.callback_resolve_infer()); - if( cmp == ::HIR::TypeRef::Compare::Unequal ) { + if( cmp == ::HIR::Compare::Unequal ) { return false; } count += 1; impl_ptr = &impl; - if( cmp == ::HIR::TypeRef::Compare::Equal ) { + if( cmp == ::HIR::Compare::Equal ) { DEBUG("Operator impl exact match - '"<<item_name<<"' - " << arg_type << " == " << ty_right); return true; } |