#include "rust-hir-type-check-base.h"
#include "rust-coercion.h"
-#include "rust-unify.h"
+#include "rust-type-util.h"
namespace Rust {
namespace Resolver {
TyTy::PointerType *expected,
Mutability to_mutbl)
{
- rust_debug ("coerce_unsafe_ptr(a={%s}, b={%s})",
+ rust_debug ("coerce_unsafe_ptr(receiver={%s}, expected={%s})",
receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
Mutability from_mutbl = Mutability::Imm;
return TypeCoercionRules::CoercionResult::get_error ();
}
- TyTy::PointerType *result
+ TyTy::PointerType *coerced_mutability
= new TyTy::PointerType (receiver->get_ref (),
TyTy::TyVar (element->get_ref ()), to_mutbl);
- if (!result->can_eq (expected, false))
- return CoercionResult::get_error ();
- return CoercionResult{{}, result};
+ TyTy::BaseType *result
+ = unify_site_and (receiver->get_ref (), TyTy::TyWithLocation (expected),
+ TyTy::TyWithLocation (coerced_mutability),
+ Location () /*unify_locus*/, false /*emit_errors*/,
+ true /*commit_if_ok*/, true /*infer*/,
+ true /*cleanup on error*/);
+ bool unsafe_ptr_coerceion_ok = result->get_kind () != TyTy::TypeKind::ERROR;
+ if (unsafe_ptr_coerceion_ok)
+ return CoercionResult{{}, result};
+
+ return TypeCoercionRules::CoercionResult::get_error ();
}
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
// back to a final unity anyway
rust_debug ("coerce_borrowed_pointer -- unify");
TyTy::BaseType *result
- = UnifyRules::Resolve (TyTy::TyWithLocation (receiver),
- TyTy::TyWithLocation (expected), locus,
- true /* commit */, true /* emit_errors */);
+ = unify_site (receiver->get_ref (), TyTy::TyWithLocation (receiver),
+ TyTy::TyWithLocation (expected), locus);
return CoercionResult{{}, result};
}
}
namespace Resolver {
UnifyRules::UnifyRules (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- Location locus, bool commit_flag, bool emit_error)
+ Location locus, bool commit_flag, bool emit_error,
+ bool infer, std::vector<CommitSite> &commits,
+ std::vector<InferenceSite> &infers)
: lhs (lhs), rhs (rhs), locus (locus), commit_flag (commit_flag),
- emit_error (emit_error), mappings (*Analysis::Mappings::get ()),
+ emit_error (emit_error), infer_flag (infer), commits (commits),
+ infers (infers), mappings (*Analysis::Mappings::get ()),
context (*TypeCheckContext::get ())
{}
TyTy::BaseType *
UnifyRules::Resolve (TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
- Location locus, bool commit_flag, bool emit_error)
+ Location locus, bool commit_flag, bool emit_error,
+ bool infer, std::vector<CommitSite> &commits,
+ std::vector<InferenceSite> &infers)
{
- UnifyRules r (lhs, rhs, locus, commit_flag, emit_error);
- TyTy::BaseType *result = r.go ();
+ UnifyRules r (lhs, rhs, locus, commit_flag, emit_error, infer, commits,
+ infers);
+ TyTy::BaseType *result = r.go ();
+ commits.push_back ({lhs.get_ty (), rhs.get_ty (), result});
if (r.commit_flag)
UnifyRules::commit (lhs.get_ty (), rhs.get_ty (), result);
}
}
+ // inject inference vars if required
+ bool got_param = rtype->get_kind () == TyTy::TypeKind::PARAM;
+ bool lhs_is_infer_var = ltype->get_kind () == TyTy::TypeKind::INFER;
+ bool expected_is_concrete = ltype->is_concrete () && !lhs_is_infer_var;
+ bool needs_infer = expected_is_concrete && got_param;
+ if (infer_flag && needs_infer)
+ {
+ TyTy::ParamType *p = static_cast<TyTy::ParamType *> (rtype);
+ TyTy::TyVar iv = TyTy::TyVar::get_implicit_infer_var (rhs.get_locus ());
+ rust_assert (iv.get_tyty ()->get_kind () == TyTy::TypeKind::INFER);
+ TyTy::InferType *i = static_cast<TyTy::InferType *> (iv.get_tyty ());
+
+ infers.push_back ({p->get_ref (), p->get_ty_ref (), p, i});
+
+ // FIXME
+ // this is hacky to set the implicit param lets make this a function
+ p->set_ty_ref (i->get_ref ());
+
+ // set the rtype now to the new inference var
+ rtype = i;
+ }
+
switch (ltype->get_kind ())
{
case TyTy::INFER:
= UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
TyTy::TyWithLocation (other_field_ty),
locus, commit_flag,
- false /* emit_error */);
+ false /* emit_error */, infer_flag,
+ commits, infers);
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
auto res
= UnifyRules::Resolve (TyTy::TyWithLocation (pa),
TyTy::TyWithLocation (pb), locus,
- commit_flag, false /* emit_error */);
+ commit_flag, false /* emit_error */,
+ infer_flag, commits, infers);
if (res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
TyTy::BaseType *base_resolved
= UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
TyTy::TyWithLocation (other_base_type), locus,
- commit_flag, false /* emit_error */);
+ commit_flag, false /* emit_error */,
+ infer_flag, commits, infers);
if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
TyTy::BaseType *base_resolved
= UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
TyTy::TyWithLocation (other_base_type), locus,
- commit_flag, false /* emit_error */);
+ commit_flag, false /* emit_error */,
+ infer_flag, commits, infers);
if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
TyTy::BaseType *element_unify = UnifyRules::Resolve (
TyTy::TyWithLocation (ltype->get_element_type ()),
TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
- false /* emit_error*/);
+ false /* emit_error*/, infer_flag, commits, infers);
if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
{
TyTy::BaseType *element_unify = UnifyRules::Resolve (
TyTy::TyWithLocation (ltype->get_element_type ()),
TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
- false /* emit_error*/);
+ false /* emit_error*/, infer_flag, commits, infers);
if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
{
auto unified_param
= UnifyRules::Resolve (TyTy::TyWithLocation (a),
TyTy::TyWithLocation (b), locus,
- commit_flag, false /* emit_errors */);
+ commit_flag, false /* emit_errors */,
+ infer_flag, commits, infers);
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
}
- auto unified_return
- = UnifyRules::Resolve (TyTy::TyWithLocation (
- ltype->get_return_type ()),
- TyTy::TyWithLocation (type.get_return_type ()),
- locus, commit_flag, false /* emit_errors */);
+ auto unified_return = UnifyRules::Resolve (
+ TyTy::TyWithLocation (ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
+ false /* emit_errors */, infer_flag, commits, infers);
if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
auto unified_param
= UnifyRules::Resolve (TyTy::TyWithLocation (a),
TyTy::TyWithLocation (b), locus,
- commit_flag, false /* emit_errors */);
+ commit_flag, false /* emit_errors */,
+ infer_flag, commits, infers);
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
}
}
- auto unified_return
- = UnifyRules::Resolve (TyTy::TyWithLocation (
- ltype->get_return_type ()),
- TyTy::TyWithLocation (type.get_return_type ()),
- locus, commit_flag, false /* emit_errors */);
+ auto unified_return = UnifyRules::Resolve (
+ TyTy::TyWithLocation (ltype->get_return_type ()),
+ TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
+ false /* emit_errors */, infer_flag, commits, infers);
if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
auto unified_result
= UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type),
TyTy::TyWithLocation (other_ret_type), locus,
- commit_flag, false /*emit_errors*/);
+ commit_flag, false /*emit_errors*/, infer_flag,
+ commits, infers);
if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
auto unified_param
= UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
TyTy::TyWithLocation (other_param), locus,
- commit_flag, false /* emit_errors */);
+ commit_flag, false /* emit_errors */,
+ infer_flag, commits, infers);
if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
TyTy::BaseType *unified_ty
= UnifyRules::Resolve (TyTy::TyWithLocation (bo),
TyTy::TyWithLocation (fo), locus,
- commit_flag, false /* emit_errors */);
+ commit_flag, false /* emit_errors */,
+ infer_flag, commits, infers);
if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
return new TyTy::ErrorType (0);
return new TyTy::ErrorType (0);
}
- TyTy::BaseType *args_res
- = UnifyRules::Resolve (TyTy::TyWithLocation (
- <ype->get_parameters ()),
- TyTy::TyWithLocation (&type.get_parameters ()),
- locus, commit_flag, false /* emit_error */);
+ TyTy::BaseType *args_res = UnifyRules::Resolve (
+ TyTy::TyWithLocation (<ype->get_parameters ()),
+ TyTy::TyWithLocation (&type.get_parameters ()), locus, commit_flag,
+ false /* emit_error */, infer_flag, commits, infers);
if (args_res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);
TyTy::BaseType *res = UnifyRules::Resolve (
TyTy::TyWithLocation (<ype->get_result_type ()),
TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
- false /* emit_error */);
+ false /* emit_error */, infer_flag, commits, infers);
if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
{
return new TyTy::ErrorType (0);