summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/ast.cpp32
-rw-r--r--src/ast/ast.hpp39
-rw-r--r--src/expand/derive.cpp4
-rw-r--r--src/hir/expr.hpp1
-rw-r--r--src/hir/from_ast.cpp18
-rw-r--r--src/hir/hir.hpp11
-rw-r--r--src/hir_expand/closures.cpp3
-rw-r--r--src/hir_typeck/expr_cs.cpp50
-rw-r--r--src/hir_typeck/helpers.cpp2
-rw-r--r--src/parse/root.cpp3
10 files changed, 109 insertions, 54 deletions
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<Item>(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<AST::Pattern,TypeRef> > 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)