summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expand/derive.cpp2
-rw-r--r--src/hir/from_ast.cpp20
-rw-r--r--src/hir_typeck/expr.cpp93
-rw-r--r--src/hir_typeck/expr.hpp8
-rw-r--r--src/hir_typeck/expr_context.cpp28
-rw-r--r--src/hir_typeck/outer.cpp2
-rw-r--r--src/resolve/absolute.cpp4
7 files changed, 128 insertions, 29 deletions
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index fdb8088b..aec3de51 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -112,7 +112,7 @@ public:
AST::GenericParams(),
ret_type,
vec$(
- ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self")) ),
+ ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), sp, false, TypeRef("Self", 0xFFFF)) ),
::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "f"), f_type )
)
);
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 4b52cd22..d7f95d81 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -733,20 +733,34 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
}
::HIR::Trait LowerHIR_Trait(::HIR::SimplePath trait_path, const ::AST::Trait& f)
{
- ::std::string lifetime;
+ bool trait_reqires_sized = false;
+ auto params = LowerHIR_GenericParams(f.params(), &trait_reqires_sized);
+ ::std::string lifetime;
::std::vector< ::HIR::GenericPath> supertraits;
for(const auto& st : f.supertraits()) {
if( st.ent.is_valid() ) {
supertraits.push_back( LowerHIR_GenericPath(st.sp, st.ent) );
+ const auto& atype_bounds = st.ent.nodes().back().args().m_assoc;
+ for(const auto& atype : atype_bounds)
+ {
+ params.m_bounds.push_back( ::HIR::GenericBound::make_TypeEquality({
+ ::HIR::TypeRef(::HIR::Path(::HIR::Path::Data::make_UfcsKnown({
+ box$( ::HIR::TypeRef("Self",0xFFFF) ),
+ supertraits.back().clone(),
+ atype.first,
+ {}
+ }))),
+ LowerHIR_Type(atype.second)
+ }) );
+ }
}
else {
lifetime = "static";
}
}
- bool trait_reqires_sized = false;
::HIR::Trait rv {
- LowerHIR_GenericParams(f.params(), &trait_reqires_sized),
+ mv$(params),
mv$(lifetime),
mv$(supertraits)
};
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 269d0850..a41dfe93 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -353,6 +353,7 @@ namespace typeck {
::HIR::ExprVisitorDef::visit(node);
this->context.apply_equality( node.span(), node.m_res_type, ::HIR::TypeRef::new_array(node.m_val->m_res_type.clone(), node.m_size_val) );
+ this->context.apply_equality( node.span(), node.m_size->m_res_type, ::HIR::TypeRef(::HIR::CoreType::Usize) );
}
void visit(::HIR::ExprNode_Tuple& node) override
{
@@ -557,6 +558,7 @@ namespace typeck {
// - BinOp: Look for overload or primitive
void visit(::HIR::ExprNode_BinOp& node) override
{
+ const auto& sp = node.span();
::HIR::ExprVisitorDef::visit(node);
const auto& ty_left = this->context.get_type(node.m_left->m_res_type );
const auto& ty_right = this->context.get_type(node.m_right->m_res_type);
@@ -693,15 +695,40 @@ namespace typeck {
// Search for ops trait impl
const ::HIR::TraitImpl* impl_ptr = nullptr;
+ ::HIR::TypeRef possible_right_type;
unsigned int count = 0;
const auto& ops_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
- DEBUG("Searching for impl " << ops_trait << "< " << ty_left << "> for " << ty_right);
- bool found_exact = this->context.m_crate.find_trait_impls(ops_trait, ty_left, this->context.callback_resolve_infer(),
+ DEBUG("Searching for impl " << ops_trait << "< " << ty_right << "> for " << ty_left);
+ bool found_bound = this->context.find_trait_impls_bound(sp, ops_trait, ty_left,
+ [&](const auto& args) {
+ assert(args.m_types.size() == 1);
+ const auto& arg_type = args.m_types[0];
+ // TODO: if arg_type mentions Self?
+ auto cmp = arg_type.compare_with_paceholders(node.span(), ty_right, this->context.callback_resolve_infer());
+ if( cmp == ::HIR::Compare::Unequal ) {
+ DEBUG("- (fail) bounded impl " << ops_trait << "<" << arg_type << ">");
+ return false;
+ }
+ count += 1;
+ if( cmp == ::HIR::Compare::Equal ) {
+ return true;
+ }
+ else {
+ if( possible_right_type == ::HIR::TypeRef() ) {
+ DEBUG("- Set possibility for " << ty_right << " - " << arg_type);
+ possible_right_type = arg_type.clone();
+ }
+
+ return false;
+ }
+ });
+ // - Only set found_exact if either found_bound returned true, XOR this returns true
+ bool found_exact = found_bound ^ 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];
+ // TODO: Abstract the below code into a method on TypecheckContext
// 1. Match arg_type with ty_right into impl block params
bool fail = false;
::std::vector< const ::HIR::TypeRef*> impl_params;
@@ -725,7 +752,8 @@ namespace typeck {
DEBUG("- (fail) impl" << impl.m_params.fmt_args() << " " << ops_trait << "<" << arg_type << "> for " << impl.m_type);
return false;
}
- // TODO: handle a generic somehow
+
+ // TODO: handle a generic righthand type by using the above parameters
if( monomorphise_type_needed(arg_type) ) {
return true;
//TODO(node.span(), "Compare ops trait type when it contains generics - " << arg_type << " == " << ty_right);
@@ -742,23 +770,47 @@ namespace typeck {
}
else {
DEBUG("Operator impl fuzzy match - '"<<item_name<<"' - " << arg_type << " == " << ty_right);
+ if( possible_right_type == ::HIR::TypeRef() ) {
+ DEBUG("- Set possibility for " << ty_right << " - " << arg_type);
+ possible_right_type = arg_type.clone();
+ }
return false;
}
}
);
// If there wasn't an exact match, BUT there was one partial match - assume the partial match is what we want
if( !found_exact && count == 1 ) {
- assert(impl_ptr);
- this->context.apply_equality(node.span(), impl_ptr->m_trait_args.m_types[0], ty_right);
+ assert( possible_right_type != ::HIR::TypeRef() );
+ this->context.apply_equality(node.span(), possible_right_type, ty_right);
}
- if( impl_ptr ) {
+ if( count > 0 ) {
+ // - If the output type is variable
if( has_output )
{
- const auto& type = impl_ptr->m_types.at("Output");
- if( monomorphise_type_needed(type) ) {
- TODO(node.span(), "BinOp output = " << type);
+ // - If an impl block was found
+ if( impl_ptr )
+ {
+ const auto& type = impl_ptr->m_types.at("Output");
+ if( monomorphise_type_needed(type) ) {
+ TODO(node.span(), "BinOp output = " << type);
+ }
+ else {
+ this->context.apply_equality(node.span(), node.m_res_type, type);
+ }
}
- else {
+ else
+ {
+ const auto& ty_right = this->context.get_type(node.m_right->m_res_type);
+
+ ::HIR::PathParams tpp;
+ DEBUG("- ty_right = " << ty_right);
+ tpp.m_types.push_back( ty_right.clone() );
+ auto type = ::HIR::TypeRef( ::HIR::Path::Data::make_UfcsKnown({
+ box$( ty_left.clone() ),
+ ::HIR::GenericPath( ops_trait, mv$(tpp) ),
+ "Output",
+ {}
+ }) );
this->context.apply_equality(node.span(), node.m_res_type, type);
}
}
@@ -910,9 +962,13 @@ namespace typeck {
void visit(::HIR::ExprNode_Deref& node) override
{
const auto& ty = this->context.get_type( node.m_value->m_res_type );
+ TRACE_FUNCTION_FR("Deref *{" << ty << "}", this->context.get_type(node.m_res_type));
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e,
this->context.apply_equality(node.span(), node.m_res_type, *e.inner);
)
+ else TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Array, e,
+ this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef::new_slice(e.inner->clone()));
+ )
else {
// TODO: Search for Deref impl
}
@@ -1571,10 +1627,12 @@ namespace typeck {
context(context)
{
}
- void visit_node(::HIR::ExprNode& node) override {
- DEBUG(typeid(node).name() << " : " << node.m_res_type);
- this->check_type_resolved(node.span(), node.m_res_type, node.m_res_type);
- DEBUG(typeid(node).name() << " : = " << node.m_res_type);
+ void visit_node_ptr(::HIR::ExprNodeP& node) override {
+ const char* node_ty = typeid(*node).name();
+ TRACE_FUNCTION_FR(node_ty << " : " << node->m_res_type, node_ty);
+ this->check_type_resolved(node->span(), node->m_res_type, node->m_res_type);
+ DEBUG(node_ty << " : = " << node->m_res_type);
+ ::HIR::ExprVisitorDef::visit_node_ptr(node);
}
private:
@@ -1660,14 +1718,17 @@ void Typecheck_Code(typeck::TypecheckContext context, const ::HIR::TypeRef& resu
unsigned int count = 0;
do {
count += 1;
+ assert(count < 1000);
DEBUG("==== PASS " << count << " ====");
visitor.visit_node_ptr(root_ptr);
- assert(count < 1000);
+ context.compact_ivars();
} while( context.take_changed() );
+ DEBUG("==== STOPPED: " << count << " passes ====");
}
// 3. Check that there's no unresolved types left
expr = ::HIR::ExprPtr( mv$(root_ptr) );
+ context.compact_ivars();
context.dump();
{
DEBUG("==== VALIDATE ====");
diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp
index 83469264..5fa558a3 100644
--- a/src/hir_typeck/expr.hpp
+++ b/src/hir_typeck/expr.hpp
@@ -80,6 +80,8 @@ public:
m_has_changed = true;
}
+ void compact_ivars();
+
/// 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);
@@ -127,7 +129,11 @@ public:
/// Searches for a trait impl that matches the provided trait name and type
bool find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const;
/// Locate a named trait in the provied trait (either itself or as a parent trait)
- bool find_named_trait_in_trait(const Span& sp, const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr, const ::HIR::PathParams& pp, ::std::function<bool(const ::HIR::PathParams&)> callback) const;
+ bool find_named_trait_in_trait(const Span& sp,
+ const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr,
+ const ::HIR::PathParams& pp, const ::HIR::TypeRef& self_type,
+ ::std::function<bool(const ::HIR::PathParams&)> callback
+ ) const;
/// Search for a trait implementation in current bounds
bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const;
/// Search for a trait implementation in the crate
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index 13e52674..eea61da7 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -23,6 +23,20 @@ void typeck::TypecheckContext::dump() const
i ++;
}
}
+void typeck::TypecheckContext::compact_ivars()
+{
+ TRACE_FUNCTION;
+ unsigned int i = 0;
+ for(auto& v : m_ivars)
+ {
+ if( !v.is_alias() ) {
+ auto nt = this->expand_associated_types(Span(), v.type->clone());
+ DEBUG("- " << i << " " << *v.type << " -> " << nt);
+ *v.type = mv$(nt);
+ }
+ i ++;
+ }
+}
void typeck::TypecheckContext::add_local(unsigned int index, const ::std::string& name, ::HIR::TypeRef type)
{
@@ -1037,7 +1051,12 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e),
(Infer,
auto& ty = this->get_type(input);
- return ty.clone();
+ if( ty != input ) {
+ return expand_associated_types(sp, ty.clone());
+ }
+ else {
+ return input;
+ }
),
(Diverge,
),
@@ -1297,17 +1316,18 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
// -------------------------------------------------------------------------------------------------------------------
bool typeck::TypecheckContext::find_named_trait_in_trait(const Span& sp,
const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr,
- const ::HIR::PathParams& pp,
+ const ::HIR::PathParams& pp, const ::HIR::TypeRef& target_type,
::std::function<bool(const ::HIR::PathParams&)> callback
) const
{
+ TRACE_FUNCTION_F(des << pp);
assert( pp.m_types.size() == trait_ptr.m_params.m_types.size() );
for( const auto& pt : trait_ptr.m_parent_traits )
{
auto pt_pp = monomorphise_path_params_with(Span(), pt.m_params.clone(), [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
- return gt;
+ return target_type;
}
else {
if( ge.binding >= pp.m_types.size() )
@@ -1335,7 +1355,7 @@ bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HI
return true;
}
}
- if( this->find_named_trait_in_trait(sp, trait, *e.trait.m_trait_ptr, e.trait.m_path.m_params, callback) ) {
+ if( this->find_named_trait_in_trait(sp, trait, *e.trait.m_trait_ptr, e.trait.m_path.m_params, type, callback) ) {
return true;
}
)
diff --git a/src/hir_typeck/outer.cpp b/src/hir_typeck/outer.cpp
index 211f9007..8f33f120 100644
--- a/src/hir_typeck/outer.cpp
+++ b/src/hir_typeck/outer.cpp
@@ -266,7 +266,7 @@ namespace {
void visit_trait(::HIR::PathChain p, ::HIR::Trait& item) override
{
- ::HIR::TypeRef tr { "Self", 0 };
+ ::HIR::TypeRef tr { "Self", 0xFFFF };
m_self_types.push_back(&tr);
::HIR::Visitor::visit_trait(p, item);
m_self_types.pop_back();
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 84a6b191..2a5b5561 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -154,9 +154,7 @@ struct Context
return e->clone();
}
else {
- auto rv = ::TypeRef("Self");
- rv.m_data.as_Generic().index = 0xFFFF;
- return rv;
+ return ::TypeRef("Self", 0xFFFF);
}
)
)