summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/hir_typeck/expr.cpp9
-rw-r--r--src/hir_typeck/expr_context.cpp33
-rw-r--r--src/main.cpp10
-rw-r--r--src/resolve/absolute.cpp21
5 files changed, 65 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index 30d7744f..c7e04cec 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ SHELL = bash
ifeq ($(DBGTPL),)
else ifeq ($(DBGTPL),gdb)
- DBG := echo -e "r\nbt 9\nq" | gdb --args
+ DBG := echo -e "r\nbt 10\nq" | gdb --args
else ifeq ($(DBGTPL),valgrind)
DBG := valgrind --leak-check=full --num-callers=35
else
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 0c474e02..e18c9ddd 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1011,6 +1011,7 @@ namespace typeck {
// - If an impl block was found
if( impl_ptr )
{
+ assert(impl_ptr->m_types.count("Output") != 0);
const auto& type = impl_ptr->m_types.at("Output");
if( monomorphise_type_needed(type) ) {
TODO(node.span(), "BinOp output = " << type);
@@ -1116,6 +1117,7 @@ namespace typeck {
{
const auto& val_ty = this->context.get_type( node.m_value->m_res_type );
const auto& target_ty = this->context.get_type( node.m_res_type );
+ TRACE_FUNCTION_F("Cast {" << val_ty << "} as " << target_ty);
TU_MATCH_DEF(::HIR::TypeRef::Data, (target_ty.m_data), (e),
(
ERROR(node.span(), E0000, "Invalid cast");
@@ -1154,11 +1156,13 @@ namespace typeck {
if( e.type != e2.type ) {
// ERROR
}
+ DEBUG("_Cast: Borrow coerce");
this->context.apply_equality(node.span(), *e2.inner, *e.inner);
),
(Pointer,
if( e.type != e2.type ) {
- this->context.apply_equality(node.span(), *e2.inner, *e.inner);
+ //DEBUG("_Cast: Pointer classes mismatch");
+ //this->context.apply_equality(node.span(), *e2.inner, *e.inner);
}
else {
// Nothing
@@ -1416,6 +1420,9 @@ namespace typeck {
(UfcsKnown,
const auto& trait = this->context.m_crate.get_trait_by_path(sp, e.trait.m_path);
fix_param_count(sp, this->context, path, trait.m_params, e.trait.m_params);
+ if( trait.m_values.count(e.item) == 0 ) {
+ BUG(sp, "Method '" << e.item << "' of trait " << e.trait.m_path << " doesn't exist");
+ }
const auto& fcn = trait.m_values.at(e.item).as_Function();
fix_param_count(sp, this->context, path, fcn.m_params, e.params);
cache.m_fcn_params = &fcn.m_params;
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index 1b3d45e4..d59de90c 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -1350,8 +1350,36 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
const auto& e = left_inner_res.m_data.as_TraitObject();
if( right_inner_res.m_data.is_TraitObject() ) {
// TODO: Can Debug+Send be coerced to Debug?
- if( left_inner_res != right_inner_res )
- ERROR(sp, E0000, "Can't coerce between trait objects - " << left_inner_res << " and " << right_inner_res);
+ if( left_inner_res != right_inner_res ) {
+ const auto& lie = left_inner_res .m_data.as_TraitObject();
+ const auto& rie = right_inner_res.m_data.as_TraitObject();
+ // 1. Check/equate the main trait (NOTE: Eventualy this may be a set of data traits)
+ if( lie.m_trait.m_path.m_path != rie.m_trait.m_path.m_path ) {
+ ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t << " (trait mismatch)");
+ }
+ equality_typeparams(lie.m_trait.m_path.m_params, rie.m_trait.m_path.m_params);
+
+ // 2. Ensure that the LHS's marker traits are a strict subset of the RHS
+ // NOTE: This assumes sorting - will false fail if ordering differs
+ unsigned int r_i = 0;
+ for(unsigned int l_i = 0; l_i < lie.m_markers.size(); l_i ++)
+ {
+ while( r_i < rie.m_markers.size() && rie.m_markers[r_i].m_path != lie.m_markers[l_i].m_path ) {
+ r_i += 1;
+ }
+ if( r_i == rie.m_markers.size() ) {
+ ERROR(sp, E0000, "Can't coerce between trait objects - " << left_inner_res << " and " << right_inner_res << " (added marker)");
+ }
+ }
+ // Coercion is possible and valid.
+ // HACK: Uses _Unsize as a coerce
+ auto span = node_ptr->span();
+ node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Unsize( mv$(span), mv$(node_ptr), l_t.clone() ));
+ node_ptr->m_res_type = l_t.clone();
+
+ this->mark_change();
+ return ;
+ }
// - Equal, nothing to do
return ;
}
@@ -1420,6 +1448,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
auto& node_ptr = *node_ptr_ptr;
auto span = node_ptr->span();
+ node_ptr->m_res_type = r_t.clone();
node_ptr = ::HIR::ExprNodeP(new ::HIR::ExprNode_Cast( mv$(span), mv$(node_ptr), l_t.clone() ));
node_ptr->m_res_type = l_t.clone();
diff --git a/src/main.cpp b/src/main.cpp
index 90358661..85307663 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -203,11 +203,11 @@ int main(int argc, char *argv[])
::std::cerr << "Parser Error: " << e.what() << ::std::endl;
return 2;
}
- catch(const ::std::exception& e)
- {
- ::std::cerr << "Misc Error: " << e.what() << ::std::endl;
- return 2;
- }
+ //catch(const ::std::exception& e)
+ //{
+ // ::std::cerr << "Misc Error: " << e.what() << ::std::endl;
+ // return 2;
+ //}
//catch(const char* e)
//{
// ::std::cerr << "Internal Compiler Error: " << e << ::std::endl;
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 3e1e2ff4..34255e99 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -645,7 +645,26 @@ void Resolve_Absolute_Path_BindAbsolute(Context& context, const Span& sp, Contex
if( !n.args().is_empty() ) {
trait_path.nodes().back().args() = mv$(n.args());
}
- auto new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(), mv$(trait_path));
+ // TODO: If the named item can't be found in the trait, fall back to it being a type binding
+ // - What if this item is from a nested trait?
+ ::AST::Path new_path;
+ bool found = false;
+ //switch(mode)
+ //{
+ //case Context::LookupMode::Value: {
+ assert(i+1 < path_abs.nodes.size());
+ auto it = ::std::find_if( e.trait_->items().begin(), e.trait_->items().end(), [&](const auto& x){ return x.name == path_abs.nodes[i+1].name(); } );
+ if( it != e.trait_->items().end() ) {
+ found = true;
+ }
+ // } break;
+ //}
+ if( !found ) {
+ new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(sp, mv$(trait_path)));
+ }
+ else {
+ new_path = ::AST::Path(::AST::Path::TagUfcs(), ::TypeRef(), mv$(trait_path));
+ }
for( unsigned int j = i+1; j < path_abs.nodes.size(); j ++ )
new_path.nodes().push_back( mv$(path_abs.nodes[j]) );