From 2f9acf36cfd475dc48b7a46e4cdff1b284529a79 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Mon, 22 Aug 2016 20:03:11 +0800 Subject: AST+HIR - Save decoded receiver type for methods --- src/ast/ast.cpp | 32 +++++++++++++++++++++++++++++ src/ast/ast.hpp | 39 ++++++++++++++++++++++------------- src/expand/derive.cpp | 4 ++++ src/hir/expr.hpp | 1 + src/hir/from_ast.cpp | 18 ++++++++++++++++ src/hir/hir.hpp | 11 ++++++++++ src/hir_expand/closures.cpp | 3 +++ src/hir_typeck/expr_cs.cpp | 50 ++++++++++----------------------------------- src/hir_typeck/helpers.cpp | 2 ++ src/parse/root.cpp | 3 ++- 10 files changed, 109 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index b9394702..29ddf07f 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -302,6 +302,38 @@ Module::ItemRef Module::find_item(const ::std::string& needle, bool allow_leaves } +Function::Function(Span sp, GenericParams params, TypeRef ret_type, Arglist args): + m_span(sp), + m_params( move(params) ), + m_rettype( move(ret_type) ), + m_args( move(args) ) +{ + if( m_args.size() > 0 && m_args.front().first.binding().m_name == "self" ) { + const auto& ty = m_args.front().second; + TU_MATCH_DEF( ::TypeData, (ty.m_data), (e), + ( + // Whups! + ERROR(sp, E0000, "Invalid receiver type - " << ty); + ), + (Borrow, + if(e.is_mut) { + m_receiver = Receiver::BorrowUnique; + } + else { + m_receiver = Receiver::BorrowShared; + } + ), + // NOTE: This only applies for `self/&self/&mut self` syntax, NOT the `self: Self` syntax + (Generic, + if( e.index != 0xFFFF ) { + ERROR(sp, E0000, "Invalid receiver type - " << ty); + } + m_receiver = Receiver::Value; + ) + ) + } +} + void Trait::add_type(::std::string name, TypeRef type) { m_items.push_back( Named(mv$(name), Item::make_Type({TypeAlias(GenericParams(), mv$(type))}), true) ); } diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 93b68604..b5fd07ea 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -147,38 +147,49 @@ class Function { public: typedef ::std::vector< ::std::pair > Arglist; + + enum class Receiver { + Free, + Value, + BorrowOwned, + BorrowUnique, + BorrowShared, + //RawMut, + //RawConst, + //Box, + }; private: - ::std::string m_lifetime; + Span m_span; + //::std::string m_lifetime; + Receiver m_receiver; GenericParams m_params; Expr m_code; TypeRef m_rettype; Arglist m_args; public: - Function() + Function(): + m_receiver(Receiver::Free) {} Function(const Function&) = delete; - Function(Function&&) noexcept = default; + Function& operator=(const Function&) = delete; + Function(Function&&) = default; Function& operator=(Function&&) = default; - Function(GenericParams params, TypeRef ret_type, Arglist args): - m_params( move(params) ), - m_rettype( move(ret_type) ), - m_args( move(args) ) - { - } + Function(Span sp, GenericParams params, TypeRef ret_type, Arglist args); void set_code(Expr code) { m_code = ::std::move(code); } - void set_self_lifetime(::std::string s) { m_lifetime = s; } const GenericParams& params() const { return m_params; } + GenericParams& params() { return m_params; } const Expr& code() const { return m_code; } + Expr& code() { return m_code; } const TypeRef& rettype() const { return m_rettype; } + TypeRef& rettype() { return m_rettype; } const Arglist& args() const { return m_args; } + Arglist& args() { return m_args; } + + Receiver receiver() const { return m_receiver; } - GenericParams& params() { return m_params; } - Expr& code() { return m_code; } - TypeRef& rettype() { return m_rettype; } - Arglist& args() { return m_args; } }; class Trait diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp index 310ad104..09fd4bbc 100644 --- a/src/expand/derive.cpp +++ b/src/expand/derive.cpp @@ -234,6 +234,7 @@ class Deriver_Debug: DEBUG("node = " << *node); AST::Function fcn( + sp, AST::GenericParams(), ret_type, vec$( @@ -409,6 +410,7 @@ class Deriver_PartialEq: const AST::Path trait_path("", { AST::PathNode("cmp", {}), AST::PathNode("PartialEq", {}) }); AST::Function fcn( + sp, AST::GenericParams(), TypeRef(sp, CORETYPE_BOOL), vec$( @@ -591,6 +593,7 @@ class Deriver_Eq: const AST::Path trait_path = this->get_trait_path(); AST::Function fcn( + sp, AST::GenericParams(), TypeRef(TypeRef::TagUnit(), sp), vec$( @@ -727,6 +730,7 @@ class Deriver_Clone: const AST::Path trait_path = this->get_trait_path(); AST::Function fcn( + sp, AST::GenericParams(), TypeRef("Self", 0xFFFF), vec$( diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp index 4b385c99..3a7839a8 100644 --- a/src/hir/expr.hpp +++ b/src/hir/expr.hpp @@ -416,6 +416,7 @@ struct ExprCallCache ::std::vector< ::HIR::TypeRef> m_arg_types; const ::HIR::GenericParams* m_fcn_params; const ::HIR::GenericParams* m_top_params; + const ::HIR::Function* m_fcn; ::HIR::PathParams m_ty_impl_params; diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 4fe9759c..6a43b790 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -891,13 +891,31 @@ namespace { } ::HIR::Function LowerHIR_Function(::HIR::ItemPath p, const ::AST::Function& f) { + static Span sp; + DEBUG(p); ::std::vector< ::std::pair< ::HIR::Pattern, ::HIR::TypeRef > > args; for(const auto& arg : f.args()) args.push_back( ::std::make_pair( LowerHIR_Pattern(arg.first), LowerHIR_Type(arg.second) ) ); + auto receiver = ::HIR::Function::Receiver::Free; + + switch( f.receiver() ) + { + #define _(N) case ::AST::Function::Receiver::N: receiver = ::HIR::Function::Receiver::N; break; + _(Free) + _(Value) + _(BorrowOwned) + _(BorrowUnique) + _(BorrowShared) + //case ::AST::Function::Receiver::Box: + // break; + #undef _ + } + // TODO: ABI and unsafety/constness return ::HIR::Function { + receiver, "rust", false, false, LowerHIR_GenericParams(f.params(), nullptr), // TODO: If this is a method, then it can add the Self: Sized bound mv$(args), diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp index 2eaf508d..d2a3631b 100644 --- a/src/hir/hir.hpp +++ b/src/hir/hir.hpp @@ -76,6 +76,17 @@ struct Constant class Function { public: + enum class Receiver { + Free, + Value, + BorrowOwned, + BorrowUnique, + BorrowShared, + //PointerMut, + //PointerConst, + }; + + Receiver m_receiver; ::std::string m_abi; bool m_unsafe; bool m_const; diff --git a/src/hir_expand/closures.cpp b/src/hir_expand/closures.cpp index 03b5e8f2..a6246a2c 100644 --- a/src/hir_expand/closures.cpp +++ b/src/hir_expand/closures.cpp @@ -166,6 +166,7 @@ namespace { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( ::std::string("call_once"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + ::HIR::Function::Receiver::Value, "rust", false, false, {}, make_vec2( @@ -197,6 +198,7 @@ namespace { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( ::std::string("call_mut"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + ::HIR::Function::Receiver::BorrowUnique, "rust", false, false, {}, make_vec2( @@ -229,6 +231,7 @@ namespace { mv$(params), mv$(trait_params), mv$(closure_type), make_map1( ::std::string("call"), ::HIR::TraitImpl::ImplEnt< ::HIR::Function> { false, ::HIR::Function { + ::HIR::Function::Receiver::BorrowShared, "rust", false, false, {}, make_vec2( diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp index b0ff5b9d..53bab500 100644 --- a/src/hir_typeck/expr_cs.cpp +++ b/src/hir_typeck/expr_cs.cpp @@ -297,6 +297,7 @@ namespace { ) assert( fcn_ptr ); + cache.m_fcn = fcn_ptr; const auto& fcn = *fcn_ptr; // --- Monomorphise the argument/return types (into current context) @@ -1870,55 +1871,26 @@ namespace { // Autoref { - // TODO: Get the receiver type without Self having been expanded. - // - Or some other indication of how Self is being taken - const auto& receiver_type = node.m_cache.m_arg_types.front(); - enum class Receiver { - Unknown, - Value, - Shared, - Unique, - Owned, - //Box, - } receiver_class = Receiver::Unknown; - if( this->context.m_ivars.types_equal(receiver_type, node.m_value->m_res_type) ) { - receiver_class = Receiver::Value; - } - else TU_IFLET(::HIR::TypeRef::Data, receiver_type.m_data, Borrow, e, - if( this->context.m_ivars.types_equal(*e.inner, node.m_value->m_res_type) ) { - switch(e.type) - { - case ::HIR::BorrowType::Shared: receiver_class = Receiver::Shared; break; - case ::HIR::BorrowType::Unique: receiver_class = Receiver::Unique; break; - case ::HIR::BorrowType::Owned : receiver_class = Receiver::Owned ; break; - } - } - else { - receiver_class = Receiver::Unknown; - } - ) - else { - receiver_class = Receiver::Unknown; - } + auto receiver_class = node.m_cache.m_fcn->m_receiver; auto& node_ptr = node.m_value; auto span = node_ptr->span(); switch(receiver_class) { - case Receiver::Unknown: - BUG(sp, "Unknown receiver type - " << receiver_type << ", Self = " << node.m_value->m_res_type); - case Receiver::Value: + case ::HIR::Function::Receiver::Free: + BUG(sp, "Method call resolved to a free function - " << node.m_method_path); + case ::HIR::Function::Receiver::Value: // by value - nothing needs to be added break; - case Receiver::Shared: - case Receiver::Unique: - case Receiver::Owned: { + case ::HIR::Function::Receiver::BorrowShared: + case ::HIR::Function::Receiver::BorrowUnique: + case ::HIR::Function::Receiver::BorrowOwned: { ::HIR::BorrowType bt; switch(receiver_class) { - case Receiver::Shared: bt = ::HIR::BorrowType::Shared; break; - case Receiver::Unique: bt = ::HIR::BorrowType::Unique; break; - case Receiver::Owned: TODO(sp, "Construct &move uni-op"); + case ::HIR::Function::Receiver::BorrowShared: bt = ::HIR::BorrowType::Shared; break; + case ::HIR::Function::Receiver::BorrowUnique: bt = ::HIR::BorrowType::Unique; break; + case ::HIR::Function::Receiver::BorrowOwned: bt = ::HIR::BorrowType::Owned; break; default: throw ""; } // - Add correct borrow operation diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp index d04d108a..24c83296 100644 --- a/src/hir_typeck/helpers.cpp +++ b/src/hir_typeck/helpers.cpp @@ -2106,6 +2106,7 @@ bool TraitResolution::find_method(const Span& sp, const HIR::t_trait_list& trait if( !this->trait_contains_method(sp, e.trait.m_path, *e.trait.m_trait_ptr, method_name, final_trait_path) ) continue ; DEBUG("- Found trait " << final_trait_path); + // TODO: Check that the receiver isn't by-value if `allow_move` is false // Found the method, return the UFCS path for it fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({ @@ -2130,6 +2131,7 @@ bool TraitResolution::find_method(const Span& sp, const HIR::t_trait_list& trait if( it->second.is_Function() ) { const auto& v = it->second.as_Function(); if( v.m_args.size() > 0 && v.m_args[0].first.m_binding.m_name == "self" ) { + // TODO: Check that the receiver isn't by-value if `allow_move` is false fcn_path = ::HIR::Path( ::HIR::Path::Data::Data_UfcsKnown({ box$( ty.clone() ), e.m_trait.m_path.clone(), diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 1ee1a13d..dfc8a1d9 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -233,6 +233,7 @@ void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params) AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems& attrs, bool allow_self, bool can_be_prototype) { TRACE_FUNCTION; + ProtoSpan ps = lex.start_span(); Token tok; @@ -387,7 +388,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaIt PUTBACK(tok, lex); } - return AST::Function(::std::move(params), ::std::move(ret_type), ::std::move(args)); + return AST::Function(lex.end_span(ps), mv$(params), mv$(ret_type), mv$(args)); } AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, AST::MetaItems& attrs, bool allow_self) -- cgit v1.2.3