summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-07 17:42:27 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-07 17:42:27 +0800
commit6b11184b3335331b2e28b5e6cce5525f501e23ce (patch)
tree8228ad86a17d69c7e36eb90f7e3b93074cba9d3a
parent2d7d7d8571a788ca43439a5d75df818eaa8dd5d3 (diff)
downloadmrust-6b11184b3335331b2e28b5e6cce5525f501e23ce.tar.gz
HIR Typecheck - Successful inferrence of literals (no i32 default yet)
-rw-r--r--src/hir/type.cpp139
-rw-r--r--src/hir/type.hpp8
-rw-r--r--src/hir_typeck/expr.cpp45
3 files changed, 179 insertions, 13 deletions
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index acd5ab1c..a3ed3597 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -325,3 +325,142 @@ 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
+{
+ assert( !this->m_data.is_Infer() );
+ const auto& right = (x.m_data.is_Infer() ? resolve_placeholder(x) : (x.m_data.is_Generic() ? resolve_placeholder(x) : x));
+
+ // If righthand side is infer, it's a fuzzy match (or not a match)
+ TU_IFLET(::HIR::TypeRef::Data, right.m_data, Infer, e,
+ switch( e.ty_class )
+ {
+ case ::HIR::InferClass::None:
+ return Compare::Fuzzy;
+ case ::HIR::InferClass::Integer:
+ TU_IFLET( ::HIR::TypeRef::Data, this->m_data, Primitive, le,
+ switch(le)
+ {
+ case ::HIR::CoreType::I8: case ::HIR::CoreType::U8:
+ case ::HIR::CoreType::I16: case ::HIR::CoreType::U16:
+ case ::HIR::CoreType::I32: case ::HIR::CoreType::U32:
+ case ::HIR::CoreType::I64: case ::HIR::CoreType::U64:
+ case ::HIR::CoreType::Isize: case ::HIR::CoreType::Usize:
+ return Compare::Fuzzy;
+ default:
+ return Compare::Unequal;
+ }
+ )
+ else {
+ return Compare::Unequal;
+ }
+ case ::HIR::InferClass::Float:
+ TU_IFLET( ::HIR::TypeRef::Data, this->m_data, Primitive, le,
+ switch(le)
+ {
+ case ::HIR::CoreType::F32:
+ case ::HIR::CoreType::F64:
+ return Compare::Fuzzy;
+ default:
+ return Compare::Unequal;
+ }
+ )
+ else {
+ return Compare::Unequal;
+ }
+ }
+ throw "";
+ )
+
+ if( this->m_data.tag() != right.m_data.tag() ) {
+ return Compare::Unequal;
+ }
+ TU_MATCH(::HIR::TypeRef::Data, (this->m_data, right.m_data), (le, re),
+ (Infer, assert(!"infer");),
+ (Diverge,
+ return Compare::Equal;
+ ),
+ (Primitive,
+ 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;
+ )
+ )
+ ),
+ (Generic,
+ if( le.binding != re.binding )
+ return Compare::Unequal;
+ return Compare::Equal;
+ ),
+ (TraitObject,
+ TODO(sp, "Compare " << *this << " and " << right);
+ ),
+ (Array,
+ if( le.size_val != re.size_val )
+ return Compare::Unequal;
+ return le.inner->compare_with_paceholders(sp, *re.inner, resolve_placeholder);
+ ),
+ (Slice,
+ return le.inner->compare_with_paceholders(sp, *re.inner, resolve_placeholder);
+ ),
+ (Tuple,
+ if( le.size() != re.size() )
+ return Compare::Unequal;
+ auto rv = Compare::Equal;
+ for( unsigned int i = 0; i < le.size(); i ++ )
+ {
+ auto rv2 = le[i].compare_with_paceholders( sp, re[i], resolve_placeholder );
+ if( rv2 == Compare::Unequal )
+ return Compare::Unequal;
+ if( rv2 == Compare::Fuzzy )
+ rv = Compare::Fuzzy;
+ }
+ return rv;
+ ),
+ (Borrow,
+ if( le.type != re.type )
+ return Compare::Unequal;
+ return le.inner->compare_with_paceholders(sp, *re.inner, resolve_placeholder);
+ ),
+ (Pointer,
+ if( le.type != re.type )
+ return Compare::Unequal;
+ return le.inner->compare_with_paceholders(sp, *re.inner, resolve_placeholder);
+ ),
+ (Function,
+ TODO(sp, "Compare " << *this << " and " << right);
+ )
+ )
+ throw "";
+}
diff --git a/src/hir/type.hpp b/src/hir/type.hpp
index 01254270..75cf4485 100644
--- a/src/hir/type.hpp
+++ b/src/hir/type.hpp
@@ -169,6 +169,14 @@ public:
// Match generics in `this` with types from `x`
// 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, ::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, ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> resolve_placeholder) const;
};
extern ::std::ostream& operator<<(::std::ostream& os, const ::HIR::TypeRef& ty);
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 06332d49..f044cae8 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1356,6 +1356,15 @@ namespace {
}
public:
+ ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> callback_resolve_infer() {
+ return [&](const auto& ty)->const auto& {
+ if( ty.m_data.is_Infer() )
+ return this->get_type(ty);
+ else
+ return ty;
+ };
+ }
+
unsigned int new_ivar()
{
m_ivars.push_back( IVar() );
@@ -1924,23 +1933,28 @@ namespace {
const ::HIR::TraitImpl* impl_ptr = nullptr;
unsigned int count = 0;
const auto& ops_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
- bool found_exact = this->context.m_crate.find_trait_impls(ops_trait, ty_left, [&](const auto& ty)->const auto&{
- if( ty.m_data.is_Infer() )
- return this->context.get_type(ty);
- else
- return ty;
- },
+ bool found_exact = this->context.m_crate.find_trait_impls(ops_trait, ty_left, this->context.callback_resolve_infer(),
[&](const auto& impl) {
+ // TODO: Check how concretely the types matched
assert( impl.m_trait_args.m_types.size() == 1 );
const auto& arg_type = impl.m_trait_args.m_types[0];
- DEBUG("TODO: Handle operator overload '"<<item_name<<"' - " << arg_type << " == " << ty_right);
- // TODO: Filter out completly incompatible implementations (e.g. &-ptr with integers)
- if( arg_type == ty_right ) {
- impl_ptr = &impl;
- return true;
+ // TODO: What if the trait arguments depend on a generic parameter?
+ 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 ) {
+ return false;
}
count += 1;
- return false;
+ impl_ptr = &impl;
+ if( cmp == ::HIR::TypeRef::Compare::Equal ) {
+ DEBUG("Operator impl exact match - '"<<item_name<<"' - " << arg_type << " == " << ty_right);
+ return true;
+ }
+ else {
+ DEBUG("Operator fuzzy exact match - '"<<item_name<<"' - " << arg_type << " == " << ty_right);
+ return false;
+ }
}
);
// If the above returned success, get output type
@@ -1952,7 +1966,12 @@ namespace {
if( has_output )
{
const auto& type = impl_ptr->m_types.at("Output");
- DEBUG("TODO: BinOp output = " << type);
+ if( monomorphise_type_needed(type) ) {
+ TODO(node.span(), "BinOp output = " << type);
+ }
+ else {
+ this->context.apply_equality(node.span(), node.m_res_type, type);
+ }
}
else
{