diff options
author | John Hodge <tpg@mutabah.net> | 2016-06-06 15:13:46 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2016-06-06 15:13:46 +0800 |
commit | 15aabebe2ec4636d51656b786d56083703f2b393 (patch) | |
tree | f59561910d2cc4d5cac0e37be43dc94e89e3c175 /src | |
parent | 62f8cff1c9113fe2ba90664a63e49a6edb13d371 (diff) | |
download | mrust-15aabebe2ec4636d51656b786d56083703f2b393.tar.gz |
HIR Typecheck - Method calls being planned, fixed resolution of Generic types
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/types.hpp | 8 | ||||
-rw-r--r-- | src/hir/expr.hpp | 6 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 17 | ||||
-rw-r--r-- | src/hir_typeck/expr.cpp | 92 | ||||
-rw-r--r-- | src/parse/root.cpp | 12 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 8 |
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); } } } |