summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/crate.hpp2
-rw-r--r--src/expand/lang_item.cpp22
-rw-r--r--src/hir/expr.hpp3
-rw-r--r--src/hir/from_ast.cpp61
-rw-r--r--src/hir/generic_params.cpp25
-rw-r--r--src/hir/hir.cpp31
-rw-r--r--src/hir/hir.hpp3
-rw-r--r--src/hir_typeck/expr.cpp141
-rw-r--r--src/parse/root.cpp6
-rw-r--r--src/resolve/absolute.cpp17
10 files changed, 240 insertions, 71 deletions
diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp
index 79a5d57f..24106bfa 100644
--- a/src/ast/crate.hpp
+++ b/src/ast/crate.hpp
@@ -19,7 +19,7 @@ public:
::AST::MetaItems m_attrs;
- AST::Path m_lang_item_PhantomFn;
+ ::std::map< ::std::string, ::AST::Path> m_lang_items;
public:
Module m_root_module;
::std::map< ::std::string, ExternCrate> m_extern_crates;
diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp
index c34642db..6d90370a 100644
--- a/src/expand/lang_item.cpp
+++ b/src/expand/lang_item.cpp
@@ -11,17 +11,18 @@
#include "../ast/crate.hpp"
-void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type)
+void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type)
{
if(name == "phantom_fn") {
- crate.m_lang_item_PhantomFn = AST::Path(path);
- crate.m_lang_item_PhantomFn.nodes().back().args().m_types = { TypeRef("A"), TypeRef("B") };
+ // - Just save path
}
else if( name == "send" ) {
// Don't care, Send is fully library in mrustc
+ // - Needed for `static`
}
else if( name == "sync" ) {
// Don't care, Sync is fully library in mrustc
+ // - Needed for `static`
}
else if( name == "sized" ) {
DEBUG("Bind 'sized' to " << path);
@@ -90,10 +91,13 @@ void handle_lang_item(AST::Crate& crate, const AST::Path& path, const ::std::str
else if( name == "str_eq" ) { }
else {
- throw CompileError::Generic(FMT("Unknown lang item '" << name << "'"));
+ ERROR(sp, E0000, "Unknown language item '" << name << "'");
}
-
+ auto rv = crate.m_lang_items.insert( ::std::make_pair( name, ::AST::Path(path) ) );
+ if( !rv.second ) {
+ ERROR(sp, E0000, "Duplicate definition of language item '" << name << "'");
+ }
}
class Decorator_LangItem:
@@ -108,13 +112,13 @@ public:
TODO(sp, "Unknown item type with #[lang=\""<<attr<<"\"] attached at " << path);
),
(Function,
- handle_lang_item(crate, path, attr.string(), AST::ITEM_FN);
+ handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_FN);
),
(Struct,
- handle_lang_item(crate, path, attr.string(), AST::ITEM_STRUCT);
+ handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_STRUCT);
),
(Trait,
- handle_lang_item(crate, path, attr.string(), AST::ITEM_TRAIT);
+ handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_TRAIT);
)
)
}
@@ -137,6 +141,8 @@ public:
else {
ERROR(sp, E0000, "Unknown lang item '" << name << "' on impl");
}
+
+ // TODO: Somehow annotate these impls to allow them to provide inherents?
}
};
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp
index 4862651d..d50191f4 100644
--- a/src/hir/expr.hpp
+++ b/src/hir/expr.hpp
@@ -487,6 +487,8 @@ struct ExprNode_StructLiteral:
::HIR::ExprNodeP m_base_value;
t_values m_values;
+ ::std::vector< ::HIR::TypeRef> m_value_types;
+
ExprNode_StructLiteral(Span sp, ::HIR::GenericPath path, ::HIR::ExprNodeP base_value, t_values values):
ExprNode( mv$(sp) ),
m_path( mv$(path) ),
@@ -494,6 +496,7 @@ struct ExprNode_StructLiteral:
m_values( mv$(values) )
{
// TODO: set m_res_type based on path?
+ // - Defer, because it requires binding ivars between m_path and m_res_type
}
NODE_METHODS();
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index 3f297e89..1693684f 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -12,8 +12,10 @@
::HIR::SimplePath LowerHIR_SimplePath(const Span& sp, const ::AST::Path& path, bool allow_final_generic = false);
::HIR::PathParams LowerHIR_PathParams(const Span& sp, const ::AST::PathParams& src_params);
+const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
+
// --------------------------------------------------------------------
-::HIR::GenericParams LowerHIR_GenericParams(const ::AST::GenericParams& gp)
+::HIR::GenericParams LowerHIR_GenericParams(const ::AST::GenericParams& gp, bool* self_is_sized)
{
::HIR::GenericParams rv;
@@ -80,23 +82,41 @@
rv.m_bounds.push_back(::HIR::GenericBound::make_TypeEquality({ mv$(left_type), LowerHIR_Type(assoc.second) }));
}
+ // TODO: Check for `Sized`
+
auto trait_path = LowerHIR_GenericPath(bound.span, e.trait);
rv.m_bounds.push_back(::HIR::GenericBound::make_TraitBound({ mv$(type), ::HIR::TraitPath { mv$(trait_path), e.hrls } }));
),
(MaybeTrait,
if( ! e.type.m_data.is_Generic() )
BUG(bound.span, "MaybeTrait on non-param");
- const auto& param_name = e.type.m_data.as_Generic().name;
- unsigned param_idx = ::std::find_if( rv.m_types.begin(), rv.m_types.end(), [&](const auto& x) { return x.m_name == param_name; } ) - rv.m_types.begin();
- if( param_idx >= rv.m_types.size() ) {
- BUG(bound.span, "MaybeTrait on parameter not in parameter list");
+ const auto& ge = e.type.m_data.as_Generic();
+ const auto& param_name = ge.name;
+ unsigned param_idx;
+ if( ge.index == 0xFFFF ) {
+ if( !self_is_sized ) {
+ BUG(bound.span, "MaybeTrait on parameter on Self when not allowed");
+ }
+ param_idx = 0xFFFF;
+ }
+ else {
+ param_idx = ::std::find_if( rv.m_types.begin(), rv.m_types.end(), [&](const auto& x) { return x.m_name == param_name; } ) - rv.m_types.begin();
+ if( param_idx >= rv.m_types.size() ) {
+ BUG(bound.span, "MaybeTrait on parameter not in parameter list (#" << ge.index << " " << param_name << ")");
+ }
}
// Compare with list of known default traits (just Sized atm) and set a marker
- const auto path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
auto trait = LowerHIR_GenericPath(bound.span, e.trait);
if( trait.m_path == path_Sized ) {
- rv.m_types[param_idx].m_is_sized = false;
+ if( param_idx == 0xFFFF ) {
+ assert( self_is_sized );
+ *self_is_sized = false;
+ }
+ else {
+ assert( param_idx < rv.m_types.size() );
+ rv.m_types[param_idx].m_is_sized = false;
+ }
}
else {
ERROR(bound.span, E0000, "MaybeTrait on unknown trait " << trait.m_path);
@@ -627,7 +647,7 @@
::HIR::TypeAlias LowerHIR_TypeAlias(const ::AST::TypeAlias& ta)
{
return ::HIR::TypeAlias {
- LowerHIR_GenericParams(ta.params()),
+ LowerHIR_GenericParams(ta.params(), nullptr),
LowerHIR_Type(ta.type())
};
}
@@ -659,7 +679,7 @@
)
return ::HIR::Struct {
- LowerHIR_GenericParams(ent.params()),
+ LowerHIR_GenericParams(ent.params(), nullptr),
// TODO: Get repr from attributes
::HIR::Struct::Repr::Rust,
mv$(data)
@@ -697,7 +717,7 @@
}
return ::HIR::Enum {
- LowerHIR_GenericParams(f.params()),
+ LowerHIR_GenericParams(f.params(), nullptr),
// TODO: Get repr from attributes
::HIR::Enum::Repr::Rust,
mv$(variants)
@@ -716,8 +736,9 @@
lifetime = "static";
}
}
+ bool trait_reqires_sized = false;
::HIR::Trait rv {
- LowerHIR_GenericParams(f.params()),
+ LowerHIR_GenericParams(f.params(), &trait_reqires_sized),
mv$(lifetime),
mv$(supertraits)
};
@@ -739,9 +760,11 @@
BUG(item.data.span, "Encountered unexpected item type in trait");
),
(Type,
+ bool is_sized = true;
+ auto gps = LowerHIR_GenericParams(i.params(), &is_sized);
rv.m_types.insert( ::std::make_pair(item.name, ::HIR::AssociatedType {
- LowerHIR_GenericParams(i.params()),
- LowerHIR_Type(i.type())
+ mv$(gps),
+ LowerHIR_Type(i.type())
}) );
),
(Function,
@@ -776,7 +799,7 @@
// TODO: ABI and unsafety/constness
return ::HIR::Function {
"rust", false, false,
- LowerHIR_GenericParams(f.params()),
+ LowerHIR_GenericParams(f.params(), nullptr), // TODO: If this is a method, then it can add the Self: Sized bound
mv$(args),
LowerHIR_Type( f.rettype() ),
LowerHIR_Expr( f.code() )
@@ -886,7 +909,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
//
for( const auto& impl : ast_mod.impls() )
{
- auto params = LowerHIR_GenericParams(impl.def().params());
+ auto params = LowerHIR_GenericParams(impl.def().params(), nullptr);
auto type = LowerHIR_Type(impl.def().type());
if( impl.def().trait().ent.is_valid() )
@@ -967,7 +990,7 @@ void LowerHIR_Module_Impls(const ::AST::Module& ast_mod, ::HIR::Crate& hir_crat
}
for( const auto& impl : ast_mod.neg_impls() )
{
- auto params = LowerHIR_GenericParams(impl.params());
+ auto params = LowerHIR_GenericParams(impl.params(), nullptr);
auto type = LowerHIR_Type(impl.type());
auto trait = LowerHIR_GenericPath(impl.trait().sp, impl.trait().ent);
auto trait_name = mv$(trait.m_path);
@@ -1028,6 +1051,12 @@ public:
LowerHIR_Module_Impls(crate.m_root_module, rv);
+ auto sp = Span();
+ for( const auto& lang_item_path : crate.m_lang_items )
+ {
+ rv.m_lang_items.insert( ::std::make_pair(lang_item_path.first, LowerHIR_SimplePath(sp, lang_item_path.second)) );
+ }
+
// Set all pointers in the HIR to the correct (now fixed) locations
IndexVisitor(rv).visit_crate( rv );
diff --git a/src/hir/generic_params.cpp b/src/hir/generic_params.cpp
index b2b72148..40608cea 100644
--- a/src/hir/generic_params.cpp
+++ b/src/hir/generic_params.cpp
@@ -25,6 +25,31 @@ namespace HIR {
}
::std::ostream& operator<<(::std::ostream& os, const ::HIR::GenericParams::PrintBounds& x)
{
+ if( x.gp.m_bounds.size() > 0 )
+ {
+ os << " where ";
+ bool comma_needed = false;
+ for(const auto& b : x.gp.m_bounds)
+ {
+ if(comma_needed)
+ os << ", ";
+ TU_MATCH(::HIR::GenericBound, (b), (e),
+ (Lifetime,
+ os << "'" << e.test << ": '" << e.valid_for;
+ ),
+ (TypeLifetime,
+ os << e.type << ": '" << e.valid_for;
+ ),
+ (TraitBound,
+ os << e.type << ": " << e.trait.m_path;
+ ),
+ (TypeEquality,
+ os << e.type << " = " << e.other_type;
+ )
+ )
+ comma_needed = true;
+ }
+ }
return os;
}
}
diff --git a/src/hir/hir.cpp b/src/hir/hir.cpp
index 1dce63f8..d9f85a53 100644
--- a/src/hir/hir.cpp
+++ b/src/hir/hir.cpp
@@ -153,33 +153,12 @@ bool ::HIR::MarkerImpl::matches_type(const ::HIR::TypeRef& type, ::HIR::t_cb_res
const ::HIR::SimplePath& ::HIR::Crate::get_lang_item_path(const Span& sp, const char* name) const
{
- if( ::std::strcmp(name, "index") == 0 ) {
- static ::HIR::SimplePath lang_index { "", {"ops", "Index"} };
- return lang_index;
- }
- else if( ::std::strcmp(name, "unsize") == 0 ) {
- static ::HIR::SimplePath lang_unsize { "", {"marker", "Unsize"} };
- return lang_unsize;
- }
- else if( ::std::strcmp(name, "add") == 0 ) {
- static ::HIR::SimplePath lang_path { "", {"ops", "Add"} };
- return lang_path;
- }
- else if( ::std::strcmp(name, "ord") == 0 ) {
- static ::HIR::SimplePath lang_path { "", {"cmp", "PartialOrd"} };
- return lang_path;
- }
- else if( ::std::strcmp(name, "eq") == 0 ) {
- static ::HIR::SimplePath lang_path { "", {"cmp", "PartialEq"} };
- return lang_path;
- }
- else if( ::std::strcmp(name, "fn_once") == 0 ) {
- static ::HIR::SimplePath lang_path { "", {"ops", "FnOnce"} };
- return lang_path;
- }
- else {
- ERROR(sp, E0000, "Unknown language item '" << name << "' encountered");
+ // TODO: have map stored in crate populated by (or from) the #[lang] attribute handler
+ auto it = this->m_lang_items.find( name );
+ if( it == this->m_lang_items.end() ) {
+ ERROR(sp, E0000, "Undefined language item '" << name << "' required");
}
+ return it->second;
}
const ::HIR::TypeItem& ::HIR::Crate::get_typeitem_by_path(const Span& sp, const ::HIR::SimplePath& path) const
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index 3447aaa0..a938579a 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -263,6 +263,9 @@ public:
/// Macros exported by this crate
::std::unordered_map< ::std::string, ::MacroRules > m_exported_macros;
+ /// Language items avaliable through this crate (includes ones from loaded externs)
+ ::std::unordered_map< ::std::string, ::HIR::SimplePath> m_lang_items;
+
const ::HIR::SimplePath& get_lang_item_path(const Span& sp, const char* name) const;
const ::HIR::TypeItem& get_typeitem_by_path(const Span& sp, const ::HIR::SimplePath& path) const;
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index 9e7b4b5a..c952de4f 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -1491,6 +1491,33 @@ namespace {
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
// No match, keep trying.
)
+ else if( ty.m_data.is_Path() && ty.m_data.as_Path().path.m_data.is_UfcsKnown() )
+ {
+ const auto& e = ty.m_data.as_Path().path.m_data.as_UfcsKnown();
+ // UFCS known - Assuming that it's reached the maximum resolvable level (i.e. a type within is generic), search for trait bounds on the type
+ const auto& trait = this->m_crate.get_trait_by_path(sp, e.trait.m_path);
+ const auto& assoc_ty = trait.m_types.at( e.item );
+ // NOTE: The bounds here have 'Self' = the type
+ for(const auto& bound : assoc_ty.m_params.m_bounds )
+ {
+ TU_IFLET(::HIR::GenericBound, bound, TraitBound, be,
+ assert(be.trait.m_trait_ptr);
+ ::HIR::GenericPath final_trait_path;
+ if( !this->trait_contains_method(sp, be.trait.m_path, *be.trait.m_trait_ptr, method_name, final_trait_path) )
+ continue ;
+ DEBUG("- Found trait " << final_trait_path);
+
+ // Found the method, return the UFCS path for it
+ fcn_path = ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
+ box$( ty.clone() ),
+ mv$(final_trait_path),
+ method_name,
+ {}
+ }) );
+ return deref_count;
+ )
+ }
+ }
else {
// 2. Search for inherent methods
for(const auto& impl : m_crate.m_type_impls)
@@ -1872,22 +1899,23 @@ namespace {
node.m_res_type = this->context.get_var_type(node.span(), node.m_slot).clone();
}
- void visit(::HIR::ExprNode_CallPath& node) override
- {
- TU_MATCH(::HIR::Path::Data, (node.m_path.m_data), (e),
+ void visit_generic_path(const Span& sp, ::HIR::GenericPath& gp) {
+ for(auto& ty : gp.m_params.m_types)
+ this->context.add_ivars(ty);
+ }
+ void visit_path(const Span& sp, ::HIR::Path& path) {
+ TU_MATCH(::HIR::Path::Data, (path.m_data), (e),
(Generic,
- for(auto& ty : e.m_params.m_types)
- this->context.add_ivars(ty);
+ this->visit_generic_path(sp, e);
),
(UfcsKnown,
this->context.add_ivars(*e.type);
- for(auto& ty : e.trait.m_params.m_types)
- this->context.add_ivars(ty);
+ this->visit_generic_path(sp, e.trait);
for(auto& ty : e.params.m_types)
this->context.add_ivars(ty);
),
(UfcsUnknown,
- TODO(node.span(), "Hit a UfcsUnknown (" << node.m_path << ") - Is this an error?");
+ TODO(sp, "Hit a UfcsUnknown (" << path << ") - Is this an error?");
),
(UfcsInherent,
this->context.add_ivars(*e.type);
@@ -1895,6 +1923,21 @@ namespace {
this->context.add_ivars(ty);
)
)
+ }
+ void visit(::HIR::ExprNode_PathValue& node) override {
+ this->visit_path(node.span(), node.m_path);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_CallPath& node) override {
+ this->visit_path(node.span(), node.m_path);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_StructLiteral& node) override {
+ this->visit_generic_path(node.span(), node.m_path);
+ ::HIR::ExprVisitorDef::visit(node);
+ }
+ void visit(::HIR::ExprNode_TupleVariant& node) override {
+ this->visit_generic_path(node.span(), node.m_path);
::HIR::ExprVisitorDef::visit(node);
}
};
@@ -1912,7 +1955,6 @@ namespace {
{
}
- // TODO: Add a new method called for all ExprNodeP, which will save the pointer someho
void visit_node_ptr(::std::unique_ptr< ::HIR::ExprNode>& node_ptr) {
m_node_ptr_ptr = &node_ptr;
::HIR::ExprVisitorDef::visit_node_ptr(node_ptr);
@@ -1970,6 +2012,7 @@ namespace {
void visit(::HIR::ExprNode_Assign& node) override
{
TRACE_FUNCTION_F("... = ...");
+ // Plain assignment can't be overloaded, requires equal types
if( node.m_op == ::HIR::ExprNode_Assign::Op::None ) {
this->context.apply_equality(node.span(),
node.m_slot->m_res_type, node.m_value->m_res_type,
@@ -1977,7 +2020,39 @@ namespace {
);
}
else {
- // TODO: Look for overload
+ const auto& ty_left = this->context.get_type(node.m_slot->m_res_type );
+ const auto& ty_right = this->context.get_type(node.m_value->m_res_type);
+
+ bool isprim_l = ty_left .m_data.is_Primitive() || (ty_left .m_data.is_Infer() && ty_left .m_data.as_Infer().ty_class != ::HIR::InferClass::None);
+ bool isprim_r = ty_right.m_data.is_Primitive() || (ty_right.m_data.is_Infer() && ty_right.m_data.as_Infer().ty_class != ::HIR::InferClass::None);
+ // SHORTCUT - If both sides are primitives (either confirmed or literals)
+ if( isprim_l && isprim_r ) {
+ // - The only option is for them both to be the same type (because primitives can't have multiple overloads)
+ // TODO: Check that this operation is valid to peform. (e.g. not doing f32_val <<= f32_val)
+ // TODO: Aren't the bitwise shift operators valid with any integer type count?
+ this->context.apply_equality(node.span(), node.m_slot->m_res_type, node.m_value->m_res_type);
+ }
+ else {
+ const char *lang_item = nullptr;
+ switch( node.m_op )
+ {
+ case ::HIR::ExprNode_Assign::Op::None: throw "";
+ case ::HIR::ExprNode_Assign::Op::Add: lang_item = "add_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Sub: lang_item = "sub_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Mul: lang_item = "mul_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Div: lang_item = "div_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Mod: lang_item = "rem_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::And: lang_item = "bitand_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Or : lang_item = "bitor_assign" ; break;
+ case ::HIR::ExprNode_Assign::Op::Xor: lang_item = "bitxor_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shr: lang_item = "shl_assign"; break;
+ case ::HIR::ExprNode_Assign::Op::Shl: lang_item = "shr_assign"; break;
+ }
+ assert(lang_item);
+ const auto& trait_path = this->context.m_crate.get_lang_item_path(node.span(), lang_item);
+ // TODO: Look for implementation of ops trait
+ TODO(node.span(), "Search for implementation of " << trait_path << "<" << ty_right << "> for " << ty_left);
+ }
}
::HIR::ExprVisitorDef::visit(node);
}
@@ -1997,7 +2072,7 @@ namespace {
return ;
}
- // TODO: Inferrence rules when untyped integer literals are in play
+ // NOTE: Inferrence rules when untyped integer literals are in play
// - `impl Add<Foo> for u32` is valid, and makes `1 + Foo` work
// - But `[][0] + Foo` doesn't
// - Adding `impl Add<Foo> for u64` leads to "`Add<Foo>` is not implemented for `i32`"
@@ -2738,6 +2813,50 @@ namespace {
// - Struct literal: Semi-known types
void visit(::HIR::ExprNode_StructLiteral& node) override
{
+ const Span& sp = node.span();
+ // TODO: what if this is an enum struct variant constructor?
+
+ auto& val_types = node.m_value_types;
+
+ if( val_types.size() == 0 )
+ {
+ const auto& str = this->context.m_crate.get_struct_by_path(node.span(), node.m_path.m_path);
+ this->fix_param_count(node.span(), node.m_path.clone(), str.m_params, node.m_path.m_params);
+
+ this->context.apply_equality(node.span(), node.m_res_type, ::HIR::TypeRef(node.m_path.clone()));
+
+ if( !str.m_data.is_Named() )
+ ERROR(sp, E0000, "Struct literal constructor for non-struct-like struct");
+ const auto& flds_def = str.m_data.as_Named();
+
+ for(auto& field : node.m_values)
+ {
+ auto fld_def_it = ::std::find_if( flds_def.begin(), flds_def.end(), [&](const auto& x){ return x.first == field.first; } );
+ if( fld_def_it == flds_def.end() ) {
+ ERROR(sp, E0000, "Struct " << node.m_path << " doesn't have a field " << field.first);
+ }
+ const ::HIR::TypeRef& field_type = fld_def_it->second.ent;
+
+ if( monomorphise_type_needed(field_type) ) {
+ val_types.push_back( monomorphise_type(sp, str.m_params, node.m_path.m_params, field_type) );
+ }
+ else {
+ // SAFE: Can't have _ as monomorphise_type_needed checks for that
+ val_types.push_back( field_type.clone() );
+ }
+ }
+ }
+
+ for( unsigned int i = 0; i < node.m_values.size(); i ++ )
+ {
+ auto& field = node.m_values[i];
+ this->context.apply_equality(sp, val_types[i], field.second->m_res_type, &field.second);
+ }
+
+ if( node.m_base_value ) {
+ this->context.apply_equality(node.span(), node.m_res_type, node.m_base_value->m_res_type);
+ }
+
::HIR::ExprVisitorDef::visit(node);
}
// - Tuple literal:
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 5bd32225..a64105c7 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -629,14 +629,13 @@ AST::Trait Parse_TraitDef(TokenStream& lex, AST::Module& mod, const AST::MetaIte
break; }
// Associated type
case TOK_RWORD_TYPE: {
+ auto atype_params = ::AST::GenericParams { };
GET_CHECK_TOK(tok, lex, TOK_IDENT);
::std::string name = tok.str();
if( GET_TOK(tok, lex) == TOK_COLON )
{
// Bounded associated type
- 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);
+ Parse_TypeBound(lex, atype_params, TypeRef("Self", 0xFFFF));
GET_TOK(tok, lex);
}
if( tok.type() == TOK_RWORD_WHERE ) {
@@ -651,6 +650,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, AST::Module& mod, const AST::MetaIte
CHECK_TOK(tok, TOK_SEMICOLON);
trait.add_type( ::std::move(name), ::std::move(default_type) );
+ trait.items().back().data.as_Type().params() = mv$(atype_params);
break; }
// Functions (possibly unsafe)
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 4c1eb927..f224d5f9 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -75,7 +75,7 @@ struct Context
auto& data = e.as_Generic();
if( has_self ) {
- assert( level == GenericSlot::Level::Top );
+ //assert( level == GenericSlot::Level::Top );
data.types.push_back( Named<GenericSlot> { "Self", GenericSlot { level, 0xFFFF } } );
m_name_context.push_back( Ent::make_ConcreteSelf(nullptr) );
}
@@ -91,10 +91,15 @@ struct Context
m_name_context.push_back(mv$(e));
}
- void pop(const ::AST::GenericParams& ) {
+ void pop(const ::AST::GenericParams& , bool has_self=false) {
if( !m_name_context.back().is_Generic() )
BUG(Span(), "resolve/absolute.cpp - Context::pop(GenericParams) - Mismatched pop");
m_name_context.pop_back();
+ if(has_self) {
+ if( !m_name_context.back().is_ConcreteSelf() )
+ BUG(Span(), "resolve/absolute.cpp - Context::pop(GenericParams) - Mismatched pop");
+ m_name_context.pop_back();
+ }
}
void push(const ::AST::Module& mod) {
m_name_context.push_back( Ent::make_Module({ &mod }) );
@@ -1194,12 +1199,12 @@ void Resolve_Absolute_ImplItems(Context& item_context, ::AST::NamedList< ::AST:
DEBUG("Type - " << i.name);
assert( e.params().ty_params().size() == 0 );
assert( e.params().lft_params().size() == 0 );
- //item_context.push( e.params(), GenericSlot::Level::Method );
+ item_context.push( e.params(), GenericSlot::Level::Method, true );
Resolve_Absolute_Generic(item_context, e.params());
Resolve_Absolute_Type( item_context, e.type() );
- //item_context.pop( e.params() );
+ item_context.pop( e.params(), true );
),
(Function,
DEBUG("Function - " << i.name);
@@ -1295,7 +1300,7 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
Resolve_Absolute_ImplItems(item_context, e.items());
- item_context.pop( e.params() );
+ item_context.pop( e.params(), true );
),
(Type,
DEBUG("Type - " << i.name);
@@ -1304,7 +1309,7 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod )
Resolve_Absolute_Type( item_context, e.type() );
- item_context.pop( e.params() );
+ item_context.pop( e.params(), true );
),
(Struct,
DEBUG("Struct - " << i.name);