summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-06-06 15:13:46 +0800
committerJohn Hodge <tpg@mutabah.net>2016-06-06 15:13:46 +0800
commit15aabebe2ec4636d51656b786d56083703f2b393 (patch)
treef59561910d2cc4d5cac0e37be43dc94e89e3c175
parent62f8cff1c9113fe2ba90664a63e49a6edb13d371 (diff)
downloadmrust-15aabebe2ec4636d51656b786d56083703f2b393.tar.gz
HIR Typecheck - Method calls being planned, fixed resolution of Generic types
-rw-r--r--src/ast/types.hpp8
-rw-r--r--src/hir/expr.hpp6
-rw-r--r--src/hir/from_ast.cpp17
-rw-r--r--src/hir_typeck/expr.cpp92
-rw-r--r--src/parse/root.cpp12
-rw-r--r--src/resolve/absolute.cpp8
6 files changed, 110 insertions, 33 deletions
diff --git a/src/ast/types.hpp b/src/ast/types.hpp
index 4ffff312..8fbd6c37 100644
--- a/src/ast/types.hpp
+++ b/src/ast/types.hpp
@@ -192,11 +192,11 @@ public:
{}
struct TagArg {};
- TypeRef(TagArg, ::std::string name):
- m_data(TypeData::make_Generic({ name, 0 }))
+ TypeRef(TagArg, ::std::string name, unsigned int binding = ~0u):
+ m_data(TypeData::make_Generic({ name, binding }))
{}
- TypeRef(::std::string name):
- TypeRef(TagArg(), ::std::move(name))
+ TypeRef(::std::string name, unsigned int binding = ~0u):
+ TypeRef(TagArg(), ::std::move(name), binding)
{}
struct TagPath {};
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp
index b15db07c..65cf3735 100644
--- a/src/hir/expr.hpp
+++ b/src/hir/expr.hpp
@@ -328,13 +328,17 @@ struct ExprNode_CallMethod:
::std::string m_method;
::HIR::PathParams m_params;
::std::vector< ::HIR::ExprNodeP> m_args;
+
+ // - Set during typeck to the real path to the method
+ ::HIR::Path m_method_path;
ExprNode_CallMethod(Span sp, ::HIR::ExprNodeP val, ::std::string method_name, ::HIR::PathParams params, ::std::vector< ::HIR::ExprNodeP> args):
ExprNode( mv$(sp) ),
m_val( mv$(val) ),
m_method( mv$(method_name) ),
m_params( mv$(params) ),
- m_args( mv$(args) )
+ m_args( mv$(args) ),
+ m_method_path( ::HIR::SimplePath("",{}) )
{
}
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 0329f3fa..8352ce8d 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -581,7 +581,8 @@
return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Function( mv$(f) ) );
),
(Generic,
- return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Generic({ e.name, 0 }) );
+ assert(e.index < 0x10000);
+ return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_Generic({ e.name, e.index }) );
)
)
throw "BUGCHECK: Reached end of LowerHIR_Type";
@@ -666,7 +667,7 @@
mv$(variants)
};
}
-::HIR::Trait LowerHIR_Trait(const ::AST::Trait& f)
+::HIR::Trait LowerHIR_Trait(::HIR::SimplePath trait_path, const ::AST::Trait& f)
{
::std::string lifetime;
@@ -684,6 +685,16 @@
mv$(lifetime),
mv$(supertraits)
};
+
+ {
+ auto this_trait = ::HIR::GenericPath( mv$(trait_path) );
+ unsigned int i = 0;
+ for(const auto& arg : rv.m_params.m_types) {
+ this_trait.m_params.m_types.push_back( ::HIR::TypeRef(arg.m_name, i) );
+ i ++;
+ }
+ rv.m_params.m_bounds.push_back( ::HIR::GenericBound::make_TraitBound({ ::HIR::TypeRef("Self",0xFFFF), mv$(this_trait) }) );
+ }
for(const auto& item : f.items())
{
@@ -778,7 +789,7 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, bool is_pub, ::H
_add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Enum(e) );
),
(Trait,
- _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Trait(e) );
+ _add_mod_ns_item( mod, item.name, item.is_pub, LowerHIR_Trait(item_path, e) );
),
(Function,
_add_mod_val_item(mod, item.name, item.is_pub, LowerHIR_Function(e));
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 02d751ac..c80207c2 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -826,7 +826,6 @@ namespace {
}
// Adds a rule that two types must be equal
// - NOTE: The ordering does matter, as the righthand side will get unsizing/deref coercions applied if possible
- // TODO: Support coercions
/// \param sp Span for reporting errors
/// \param left Lefthand type (destination for coercions)
/// \param right Righthand type (source for coercions)
@@ -929,7 +928,6 @@ namespace {
(UfcsUnknown,
this->apply_equality(sp, *lpe.type, cb_left, *rpe.type, cb_right, nullptr);
// TODO: If the type is fully known, locate a suitable trait item
- //BUG(sp, "Encountered UfcsUnknown - TODO?");
equality_typeparams(lpe.params, rpe.params);
)
)
@@ -985,7 +983,6 @@ namespace {
if( node_ptr_ptr != nullptr )
{
// Allow cases where `right`: ::core::marker::Unsize<`left`>
- // TODO: HACK: Should use the "unsize" lang item
bool succ = this->find_trait_impls(this->m_crate.get_lang_item_path(sp, "unsize"), *r_e.inner, [&](const auto& args) {
DEBUG("- Found unsizing with args " << args);
return args.m_types[0] == *l_e.inner;
@@ -1074,6 +1071,67 @@ namespace {
// 2. Search crate-level impls
return false;
}
+ /// Locate the named method by applying auto-dereferencing.
+ /// \return Number of times deref was applied (or ~0 if _ was hit)
+ unsigned int autoderef_find_method(const Span& sp, const ::HIR::TypeRef& top_ty, const ::std::string method_name, /* Out -> */::HIR::Path& fcn_path) const
+ {
+ unsigned int deref_count = 0;
+ const auto* current_ty = &top_ty;
+ do {
+ const auto& ty = this->get_type(*current_ty);
+ if( ty.m_data.is_Infer() ) {
+ return ~0u;
+ }
+
+ // 1. Search generic bounds for a match
+ const ::HIR::GenericParams* v[2] = { m_item_params, m_impl_params };
+ for(auto p : v)
+ {
+ if( !p ) continue ;
+ for(const auto& b : p->m_bounds)
+ {
+ TU_IFLET(::HIR::GenericBound, b, TraitBound, e,
+ DEBUG("Bound " << e.type << " : " << e.trait.m_path);
+ // TODO: Match using _ replacement
+ if( e.type == ty ) {
+ DEBUG("- Matches " << ty);
+ }
+ )
+ }
+ }
+
+
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
+ if( e.name == "Self" ) {
+ TODO(sp, "Search for methods on 'Self'");
+ }
+ else {
+ TODO(sp, "Search for methods on parameter #" << e.binding << " '" << e.name << "'");
+ }
+ )
+ else {
+ // 1. Search for inherent methods
+ for(const auto& impl : m_crate.m_type_impls)
+ {
+ if( impl.matches_type(ty) ) {
+ DEBUG("Mactching impl " << impl.m_type);
+ }
+ }
+ // 2. Search for trait methods (using currently in-scope traits)
+ }
+
+ // 3. Dereference and try again
+ deref_count += 1;
+ TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Borrow, e,
+ current_ty = &*e.inner;
+ )
+ else {
+ current_ty = nullptr;
+ }
+ } while( current_ty );
+ // Dereference failed! This is a hard error (hitting _ is checked above and returns ~0)
+ TODO(sp, "Error when no method could be found, but type is known - (: " << top_ty << ")." << method_name);
+ }
public:
unsigned int new_ivar()
@@ -1099,7 +1157,7 @@ namespace {
return rv;
}
- IVar& get_pointed_ivar(unsigned int slot)
+ IVar& get_pointed_ivar(unsigned int slot) const
{
auto index = slot;
unsigned int count = 0;
@@ -1115,7 +1173,7 @@ namespace {
count ++;
}
assert( m_ivars.at(index).deleted == false );
- return m_ivars.at(index);
+ return const_cast<IVar&>(m_ivars.at(index));
}
::HIR::TypeRef& get_type(::HIR::TypeRef& type)
{
@@ -1127,7 +1185,7 @@ namespace {
return type;
}
}
- const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type)
+ const ::HIR::TypeRef& get_type(const ::HIR::TypeRef& type) const
{
TU_IFLET(::HIR::TypeRef::Data, type.m_data, Infer, e,
assert(e.index != ~0u);
@@ -1671,16 +1729,18 @@ namespace {
void visit(::HIR::ExprNode_CallMethod& node) override
{
::HIR::ExprVisitorDef::visit(node);
- const auto& ty = this->context.get_type(node.m_val->m_res_type);
- DEBUG("ty = " << ty);
- // TODO: Using autoderef, locate this method on the type
- //const ::HIR::Function* fcn;
- //MaybePtr< ::HIR::TypeRef> method_type;
- //unsigned int deref_count = this->autoderef_find_method(ty, node.m_name, method_type,fcn);
- //if( deref_count != ~0u ) {
- // // TODO: Add derefs (or record somewhere)
- // //
- //}
+ if( node.m_method_path.m_data.is_Generic() && node.m_method_path.m_data.as_Generic().m_path.m_components.size() == 0 )
+ {
+ const auto& ty = this->context.get_type(node.m_val->m_res_type);
+ DEBUG("ty = " << ty);
+ // TODO: Using autoderef, locate this method on the type
+ ::HIR::Path fcn_path { ::HIR::SimplePath() };
+ unsigned int deref_count = this->context.autoderef_find_method(node.span(), ty, node.m_method, fcn_path);
+ if( deref_count != ~0u ) {
+ // // TODO: Add derefs (or record somewhere)
+ // // TODO: Replace this node with CallPath
+ }
+ }
}
// - Field: Locate field on type
void visit(::HIR::ExprNode_Field& node) override
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 15b792d0..847ffa75 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -273,11 +273,11 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt
if( tok.type() == TOK_RWORD_MUT )
{
GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF);
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), lex.end_span(ps), true, TypeRef("Self"))) );
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), lex.end_span(ps), true, TypeRef("Self", 0xFFFF))) );
}
else
{
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), lex.end_span(ps), false, TypeRef("Self"))) );
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), lex.end_span(ps), false, TypeRef("Self", 0xFFFF))) );
}
DEBUG("TODO: UFCS / self lifetimes");
if( allow_self == false )
@@ -309,7 +309,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt
}
else {
PUTBACK(tok, lex);
- ty = TypeRef("Self");
+ ty = TypeRef("Self", 0xFFFF);
}
args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), ty) );
GET_TOK(tok, lex);
@@ -327,7 +327,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt
}
else {
PUTBACK(tok, lex);
- ty = TypeRef("Self");
+ ty = TypeRef("Self", 0xFFFF);
}
args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), ty) );
GET_TOK(tok, lex);
@@ -634,8 +634,8 @@ AST::Trait Parse_TraitDef(TokenStream& lex, AST::Module& mod, const AST::MetaIte
if( GET_TOK(tok, lex) == TOK_COLON )
{
// Bounded associated type
- TypeRef a_type = TypeRef( Span(), AST::Path(AST::Path::TagUfcs(), TypeRef(TypeRef::TagArg(), "Self"), AST::Path(), {AST::PathNode(name)}) );
- //TypeRef a_type = TypeRef(TypeRef::TagAssoc(), TypeRef(TypeRef::TagArg(), "Self"), TypeRef(), name);
+ TypeRef a_type = TypeRef( Span(), AST::Path(AST::Path::TagUfcs(), TypeRef("Self", 0xFFFF), AST::Path(), {AST::PathNode(name)}) );
+ //TypeRef a_type = TypeRef(TypeRef::TagAssoc(), TypeRef("Self", 0xFFFF), TypeRef(), name);
Parse_TypeBound(lex, params, a_type);
GET_TOK(tok, lex);
}
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 95eef7fa..b3934d1b 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -140,7 +140,9 @@ struct Context
return e->clone();
}
else {
- return ::TypeRef("Self");
+ auto rv = ::TypeRef("Self");
+ rv.m_data.as_Generic().index = 0xFFFF;
+ return rv;
}
)
)
@@ -358,7 +360,7 @@ struct Context
{
if( it2->name == name ) {
::AST::Path rv(name);
- rv.bind_variable( it2->value.index * (it2->value.level == GenericSlot::Level::Method ? 256 : 0) );
+ rv.bind_variable( it2->value.index * (it2->value.level == GenericSlot::Level::Method ? 256 : 1) );
return rv;
}
}
@@ -410,7 +412,7 @@ struct Context
for( auto it2 = e.types.rbegin(); it2 != e.types.rend(); ++ it2 )
{
if( it2->name == name ) {
- return it2->value.index * (it2->value.level == GenericSlot::Level::Method ? 256 : 0);
+ return it2->value.index * (it2->value.level == GenericSlot::Level::Method ? 256 : 1);
}
}
}