summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2016-06-09 17:04:50 +0800
committerJohn Hodge <tpg@ucc.asn.au>2016-06-09 17:04:50 +0800
commit01d97106b9977f5f0226b4c446616f195fbeaaf4 (patch)
tree27dde34b6c780ae0a5dfdfa32600c3d7522dbaee
parentdbcc52b7a61f16893353572d4b9234967c33a39b (diff)
downloadmrust-01d97106b9977f5f0226b4c446616f195fbeaaf4.tar.gz
HIR Typecheck - Replace associated types with known bounds (IntoIter)
-rw-r--r--src/hir/path.cpp90
-rw-r--r--src/hir/path.hpp12
-rw-r--r--src/hir/type.cpp37
-rw-r--r--src/hir/type.hpp7
-rw-r--r--src/hir_typeck/expr.cpp40
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;
}