summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/hir/from_ast.cpp89
-rw-r--r--src/hir/from_ast.hpp2
-rw-r--r--src/hir/generic_params.hpp10
-rw-r--r--src/hir/hir.hpp4
-rw-r--r--src/hir/path.cpp57
-rw-r--r--src/hir/path.hpp8
-rw-r--r--src/hir/type.cpp2
-rw-r--r--src/hir/type.hpp2
-rw-r--r--src/hir/visitor.cpp12
-rw-r--r--src/hir/visitor.hpp1
-rw-r--r--src/hir_conv/resolve_ufcs.cpp4
-rw-r--r--src/hir_typeck/expr.cpp42
-rw-r--r--src/hir_typeck/expr.hpp13
-rw-r--r--src/hir_typeck/expr_context.cpp170
-rw-r--r--src/resolve/absolute.cpp6
15 files changed, 309 insertions, 113 deletions
diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp
index d7f95d81..8a975c25 100644
--- a/src/hir/from_ast.cpp
+++ b/src/hir/from_ast.cpp
@@ -10,7 +10,8 @@
::HIR::Module LowerHIR_Module(const ::AST::Module& module, ::HIR::SimplePath path);
::HIR::Function LowerHIR_Function(const ::AST::Function& f);
::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);
+::HIR::PathParams LowerHIR_PathParams(const Span& sp, const ::AST::PathParams& src_params, bool allow_assoc);
+::HIR::TraitPath LowerHIR_TraitPath(const Span& sp, const ::AST::Path& path);
const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
@@ -50,42 +51,11 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
),
(IsTrait,
auto type = LowerHIR_Type(e.type);
- // Iterate associated types
- for(const auto& assoc : e.trait.nodes().back().args().m_assoc) {
- struct H {
- static ::HIR::GenericPath get_trait_path_with_type(const Span& sp, const ::AST::Path& trait_p, const ::std::string& name) {
- const auto& tr = *trait_p.binding().as_Trait().trait_;
- auto it = ::std::find_if( tr.items().begin(), tr.items().end(), [&](const auto& x){return x.name == name;} );
- if( it != tr.items().end() )
- return LowerHIR_GenericPath(sp, trait_p);
-
- for(const auto& st : tr.supertraits())
- {
- auto rv = H::get_trait_path_with_type(sp, st.ent, name);
- if( rv.m_path.m_components.size() ) {
- // TODO: Fix parameters based on self parameters
- // - HACK!
- rv.m_params = LowerHIR_PathParams(sp, trait_p.nodes().back().args());
- return rv;
- }
- }
-
- return ::HIR::GenericPath();
- }
- };
- auto left_type = ::HIR::TypeRef( ::HIR::Path( ::HIR::Path::Data::make_UfcsKnown({
- box$( type.clone() ),
- H::get_trait_path_with_type(bound.span, e.trait, assoc.first),
- assoc.first,
- {}
- }) ) );
- 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 } }));
+ rv.m_bounds.push_back(::HIR::GenericBound::make_TraitBound({ mv$(type), LowerHIR_TraitPath(bound.span, e.trait) }));
+ rv.m_bounds.back().as_TraitBound().trait.m_hrls = e.hrls;
),
(MaybeTrait,
if( ! e.type.m_data.is_Generic() )
@@ -437,7 +407,7 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
throw "BUG: Encountered non-Absolute path when creating ::HIR::GenericPath";
}
}
-::HIR::PathParams LowerHIR_PathParams(const Span& sp, const ::AST::PathParams& src_params)
+::HIR::PathParams LowerHIR_PathParams(const Span& sp, const ::AST::PathParams& src_params, bool allow_assoc)
{
::HIR::PathParams params;
@@ -450,14 +420,18 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
}
// Leave 'm_assoc' alone?
+ if( !allow_assoc && src_params.m_assoc.size() > 0 )
+ {
+ BUG(sp, "Encountered path parameters with associated type bounds where they are not allowed");
+ }
return params;
}
-::HIR::GenericPath LowerHIR_GenericPath(const Span& sp, const ::AST::Path& path)
+::HIR::GenericPath LowerHIR_GenericPath(const Span& sp, const ::AST::Path& path, bool allow_assoc)
{
TU_IFLET(::AST::Path::Class, path.m_class, Absolute, e,
auto simpepath = LowerHIR_SimplePath(sp, path, true);
- ::HIR::PathParams params = LowerHIR_PathParams(sp, e.nodes.back().args());
+ ::HIR::PathParams params = LowerHIR_PathParams(sp, e.nodes.back().args(), allow_assoc);
auto rv = ::HIR::GenericPath(mv$(simpepath), mv$(params));
DEBUG(path << " => " << rv);
return rv;
@@ -466,6 +440,22 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
BUG(sp, "Encountered non-Absolute path when creating ::HIR::GenericPath - " << path);
}
}
+::HIR::TraitPath LowerHIR_TraitPath(const Span& sp, const ::AST::Path& path)
+{
+ ::HIR::TraitPath rv {
+ LowerHIR_GenericPath(sp, path, true),
+ {},
+ {},
+ nullptr
+ };
+
+ for(const auto& assoc : path.nodes().back().args().m_assoc)
+ {
+ rv.m_type_bounds.insert(::std::make_pair( assoc.first, LowerHIR_Type(assoc.second) ));
+ }
+
+ return rv;
+}
::HIR::Path LowerHIR_Path(const Span& sp, const ::AST::Path& path)
{
TU_MATCH(::AST::Path::Class, (path.m_class), (e),
@@ -490,7 +480,8 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
(UFCS,
if( e.nodes.size() != 1 )
TODO(sp, "Handle UFCS with multiple nodes - " << path);
- auto params = LowerHIR_PathParams(sp, e.nodes.front().args());
+ // - No associated type bounds allowed in UFCS paths
+ auto params = LowerHIR_PathParams(sp, e.nodes.front().args(), false);
if( ! e.trait )
{
auto type = box$( LowerHIR_Type(*e.type) );
@@ -624,10 +615,11 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
v.m_markers.push_back( LowerHIR_GenericPath(ty.span(), t) );
}
else {
- if( v.m_trait.m_path.m_components.size() > 0 ) {
+ // TraitPath -> GenericPath -> SimplePath
+ if( v.m_trait.m_path.m_path.m_components.size() > 0 ) {
ERROR(ty.span(), E0000, "Multiple data traits in trait object - " << ty);
}
- v.m_trait = LowerHIR_GenericPath(ty.span(), t);
+ v.m_trait = LowerHIR_TraitPath(ty.span(), t);
}
}
return ::HIR::TypeRef( ::HIR::TypeRef::Data::make_TraitObject( mv$(v) ) );
@@ -737,23 +729,10 @@ const ::HIR::SimplePath path_Sized = ::HIR::SimplePath("", {"marker", "Sized"});
auto params = LowerHIR_GenericParams(f.params(), &trait_reqires_sized);
::std::string lifetime;
- ::std::vector< ::HIR::GenericPath> supertraits;
+ ::std::vector< ::HIR::TraitPath> supertraits;
for(const auto& st : f.supertraits()) {
if( st.ent.is_valid() ) {
- supertraits.push_back( LowerHIR_GenericPath(st.sp, st.ent) );
- const auto& atype_bounds = st.ent.nodes().back().args().m_assoc;
- for(const auto& atype : atype_bounds)
- {
- params.m_bounds.push_back( ::HIR::GenericBound::make_TypeEquality({
- ::HIR::TypeRef(::HIR::Path(::HIR::Path::Data::make_UfcsKnown({
- box$( ::HIR::TypeRef("Self",0xFFFF) ),
- supertraits.back().clone(),
- atype.first,
- {}
- }))),
- LowerHIR_Type(atype.second)
- }) );
- }
+ supertraits.push_back( LowerHIR_TraitPath(st.sp, st.ent) );
}
else {
lifetime = "static";
diff --git a/src/hir/from_ast.hpp b/src/hir/from_ast.hpp
index 0822c835..f0795fcf 100644
--- a/src/hir/from_ast.hpp
+++ b/src/hir/from_ast.hpp
@@ -4,7 +4,7 @@
extern ::HIR::ExprPtr LowerHIR_ExprNode(const ::AST::ExprNode& e);
extern ::HIR::Path LowerHIR_Path(const Span& sp, const ::AST::Path& path);
-extern ::HIR::GenericPath LowerHIR_GenericPath(const Span& sp, const ::AST::Path& path);
+extern ::HIR::GenericPath LowerHIR_GenericPath(const Span& sp, const ::AST::Path& path, bool allow_assoc=false);
extern ::HIR::TypeRef LowerHIR_Type(const ::TypeRef& ty);
extern ::HIR::Pattern LowerHIR_Pattern(const ::AST::Pattern& pat);
diff --git a/src/hir/generic_params.hpp b/src/hir/generic_params.hpp
index 1870b904..52ba2976 100644
--- a/src/hir/generic_params.hpp
+++ b/src/hir/generic_params.hpp
@@ -27,11 +27,11 @@ TAGGED_UNION(GenericBound, Lifetime,
(TraitBound, struct {
::HIR::TypeRef type;
::HIR::TraitPath trait;
- }),
- //(NotTrait, struct {
- // ::HIR::TypeRef type;
- // ::HIR::GenricPath trait;
- // }),
+ })/*,
+ (NotTrait, struct {
+ ::HIR::TypeRef type;
+ ::HIR::GenricPath trait;
+ })*/,
(TypeEquality, struct {
::HIR::TypeRef type;
::HIR::TypeRef other_type;
diff --git a/src/hir/hir.hpp b/src/hir/hir.hpp
index 1b0b091f..fb27c44d 100644
--- a/src/hir/hir.hpp
+++ b/src/hir/hir.hpp
@@ -151,14 +151,14 @@ struct Trait
{
GenericParams m_params;
::std::string m_lifetime;
- ::std::vector< ::HIR::GenericPath > m_parent_traits;
+ ::std::vector< ::HIR::TraitPath > m_parent_traits;
bool m_is_marker;
::std::unordered_map< ::std::string, AssociatedType > m_types;
::std::unordered_map< ::std::string, TraitValueItem > m_values;
- Trait( GenericParams gps, ::std::string lifetime, ::std::vector< ::HIR::GenericPath> parents):
+ Trait( GenericParams gps, ::std::string lifetime, ::std::vector< ::HIR::TraitPath> parents):
m_params( mv$(gps) ),
m_lifetime( mv$(lifetime) ),
m_parent_traits( mv$(parents) )
diff --git a/src/hir/path.cpp b/src/hir/path.cpp
index 3cc1d817..fb153d7d 100644
--- a/src/hir/path.cpp
+++ b/src/hir/path.cpp
@@ -50,6 +50,31 @@ namespace HIR {
os << x.m_path << x.m_params;
return os;
}
+ ::std::ostream& operator<<(::std::ostream& os, const TraitPath& x)
+ {
+ if( x.m_hrls.size() > 0 ) {
+ os << "for<";
+ for(const auto& lft : x.m_hrls)
+ os << "'" << lft << ",";
+ os << "> ";
+ }
+ os << x.m_path.m_path;
+ bool has_args = ( x.m_path.m_params.m_types.size() > 0 || x.m_type_bounds.size() > 0 );
+
+ if(has_args) {
+ os << "<";
+ }
+ for(const auto& ty : x.m_path.m_params.m_types) {
+ os << ty << ",";
+ }
+ for(const auto& assoc : x.m_type_bounds) {
+ os << assoc.first << "=" << assoc.second << ",";
+ }
+ if(has_args) {
+ os << ">";
+ }
+ return os;
+ }
::std::ostream& operator<<(::std::ostream& os, const Path& x)
{
TU_MATCH(::HIR::Path::Data, (x.m_data), (e),
@@ -118,6 +143,38 @@ bool ::HIR::GenericPath::operator==(const GenericPath& x) const
return m_params == x.m_params;
}
+::HIR::TraitPath HIR::TraitPath::clone() const
+{
+ ::HIR::TraitPath rv {
+ m_path.clone(),
+ m_hrls,
+ {},
+ m_trait_ptr
+ };
+
+ for( const auto& assoc : m_type_bounds )
+ rv.m_type_bounds.insert(::std::make_pair( assoc.first, assoc.second.clone() ));
+
+ return rv;
+}
+bool ::HIR::TraitPath::operator==(const ::HIR::TraitPath& x) const
+{
+ if( m_path != x.m_path )
+ return false;
+ if( m_hrls != x.m_hrls )
+ return false;
+
+ if( m_type_bounds.size() != x.m_type_bounds.size() )
+ return false;
+
+ for(auto it_l = m_type_bounds.begin(), it_r = x.m_type_bounds.begin(); it_l != m_type_bounds.end(); it_l++, it_r++ ) {
+ if( it_l->first != it_r->first )
+ return false;
+ if( it_l->second != it_r->second )
+ return false;
+ }
+ return true;
+}
::HIR::Path::Path(::HIR::GenericPath gp):
m_data( ::HIR::Path::Data::make_Generic( mv$(gp) ) )
diff --git a/src/hir/path.hpp b/src/hir/path.hpp
index 50973b85..a4603fe3 100644
--- a/src/hir/path.hpp
+++ b/src/hir/path.hpp
@@ -100,7 +100,15 @@ class TraitPath
public:
GenericPath m_path;
::std::vector< ::std::string> m_hrls;
+ ::std::map< ::std::string, ::HIR::TypeRef> m_type_bounds;
+
const ::HIR::Trait* m_trait_ptr;
+
+ TraitPath clone() const;
+ bool operator==(const TraitPath& x) const;
+ bool operator!=(const TraitPath& x) const { return !(*this == x); }
+
+ friend ::std::ostream& operator<<(::std::ostream& os, const TraitPath& x);
};
class Path
diff --git a/src/hir/type.cpp b/src/hir/type.cpp
index f78c45ad..b57dcc7c 100644
--- a/src/hir/type.cpp
+++ b/src/hir/type.cpp
@@ -250,7 +250,7 @@ bool ::HIR::TypeRef::operator==(const ::HIR::TypeRef& x) const
(Closure,
if( te.node != xe.node )
return false;
- assert( te.m_rettype == xe.m_rettype );
+ //assert( te.m_rettype == xe.m_rettype );
return true;
)
)
diff --git a/src/hir/type.hpp b/src/hir/type.hpp
index e5ccf0ce..8a090b26 100644
--- a/src/hir/type.hpp
+++ b/src/hir/type.hpp
@@ -100,7 +100,7 @@ public:
unsigned int binding;
}),
(TraitObject, struct {
- ::HIR::GenericPath m_trait; // TODO: Use TraitPath?
+ ::HIR::TraitPath m_trait;
::std::vector< ::HIR::GenericPath > m_markers;
::HIR::LifetimeRef m_lifetime;
}),
diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp
index a2432971..cb168347 100644
--- a/src/hir/visitor.cpp
+++ b/src/hir/visitor.cpp
@@ -141,7 +141,7 @@ void ::HIR::Visitor::visit_trait(::HIR::PathChain p, ::HIR::Trait& item)
TRACE_FUNCTION;
this->visit_params(item.m_params);
for(auto& par : item.m_parent_traits) {
- this->visit_generic_path(par, ::HIR::Visitor::PathContext::TYPE);
+ this->visit_trait_path(par);
}
for(auto& i : item.m_types) {
DEBUG("type " << i.first);
@@ -245,7 +245,7 @@ void ::HIR::Visitor::visit_params(::HIR::GenericParams& params)
),
(TraitBound,
this->visit_type(e.type);
- this->visit_generic_path(e.trait.m_path, ::HIR::Visitor::PathContext::TYPE);
+ this->visit_trait_path(e.trait);
),
//(NotTrait, struct {
// ::HIR::TypeRef type;
@@ -273,7 +273,7 @@ void ::HIR::Visitor::visit_type(::HIR::TypeRef& ty)
(Generic,
),
(TraitObject,
- this->visit_generic_path(e.m_trait, ::HIR::Visitor::PathContext::TYPE);
+ this->visit_trait_path(e.m_trait);
for(auto& trait : e.m_markers) {
this->visit_generic_path(trait, ::HIR::Visitor::PathContext::TYPE);
}
@@ -383,6 +383,12 @@ void ::HIR::Visitor::visit_pattern_val(::HIR::Pattern::Value& val)
)
)
}
+void ::HIR::Visitor::visit_trait_path(::HIR::TraitPath& p)
+{
+ this->visit_generic_path(p.m_path, ::HIR::Visitor::PathContext::TYPE);
+ for(auto& assoc : p.m_type_bounds)
+ this->visit_type(assoc.second);
+}
void ::HIR::Visitor::visit_path(::HIR::Path& p, ::HIR::Visitor::PathContext pc)
{
TU_MATCH(::HIR::Path::Data, (p.m_data), (e),
diff --git a/src/hir/visitor.hpp b/src/hir/visitor.hpp
index fb71ba35..8e0d6d39 100644
--- a/src/hir/visitor.hpp
+++ b/src/hir/visitor.hpp
@@ -81,6 +81,7 @@ public:
VALUE,
};
+ virtual void visit_trait_path(::HIR::TraitPath& p);
virtual void visit_path(::HIR::Path& p, PathContext );
virtual void visit_path_params(::HIR::PathParams& p);
virtual void visit_generic_path(::HIR::GenericPath& p, PathContext );
diff --git a/src/hir_conv/resolve_ufcs.cpp b/src/hir_conv/resolve_ufcs.cpp
index 6cd5891c..daa075ba 100644
--- a/src/hir_conv/resolve_ufcs.cpp
+++ b/src/hir_conv/resolve_ufcs.cpp
@@ -196,7 +196,7 @@ namespace {
// Search supertraits (recursively)
for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ )
{
- const auto& par_trait_path = trait.m_parent_traits[i];
+ const auto& par_trait_path = trait.m_parent_traits[i].m_path;
//const auto& par_trait_ent = *trait.m_parent_trait_ptrs[i];
const auto& par_trait_ent = this->find_trait(par_trait_path.m_path);
if( locate_in_trait_and_set(pc, par_trait_path, par_trait_ent, pd) ) {
@@ -231,7 +231,7 @@ namespace {
// Search supertraits (recursively)
for( unsigned int i = 0; i < trait.m_parent_traits.size(); i ++ )
{
- const auto& par_trait_path = trait.m_parent_traits[i];
+ const auto& par_trait_path = trait.m_parent_traits[i].m_path;
//const auto& par_trait_ent = *trait.m_parent_trait_ptrs[i];
const auto& par_trait_ent = this->find_trait(par_trait_path.m_path);
// TODO: Modify path parameters based on the current trait's params
diff --git a/src/hir_typeck/expr.cpp b/src/hir_typeck/expr.cpp
index a41dfe93..00d6e096 100644
--- a/src/hir_typeck/expr.cpp
+++ b/src/hir_typeck/expr.cpp
@@ -37,6 +37,14 @@ namespace typeck {
)
throw "";
}
+ bool monomorphise_traitpath_needed(const ::HIR::TraitPath& tpl)
+ {
+ if( monomorphise_pathparams_needed(tpl.m_path.m_params) ) return true;
+ for(const auto& assoc : tpl.m_type_bounds)
+ if( monomorphise_type_needed(assoc.second) )
+ return true;
+ return false;
+ }
bool monomorphise_type_needed(const ::HIR::TypeRef& tpl)
{
TU_MATCH(::HIR::TypeRef::Data, (tpl.m_data), (e),
@@ -56,9 +64,11 @@ namespace typeck {
return true;
),
(TraitObject,
- if( monomorphise_pathparams_needed(e.m_trait.m_params) ) return true;
+ if( monomorphise_traitpath_needed(e.m_trait) )
+ return true;
for(const auto& trait : e.m_markers)
- if( monomorphise_pathparams_needed(trait.m_params) ) return true;
+ if( monomorphise_pathparams_needed(trait.m_params) )
+ return true;
return false;
),
(Array,
@@ -101,6 +111,20 @@ namespace typeck {
{
return ::HIR::GenericPath( tpl.m_path, monomorphise_path_params_with(sp, tpl.m_params, callback, allow_infer) );
}
+ ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer)
+ {
+ ::HIR::TraitPath rv {
+ monomorphise_genericpath_with(sp, tpl.m_path, callback, allow_infer),
+ tpl.m_hrls,
+ {},
+ tpl.m_trait_ptr
+ };
+
+ for(const auto& assoc : tpl.m_type_bounds)
+ rv.m_type_bounds.insert(::std::make_pair( assoc.first, monomorphise_type_with(sp, assoc.second, callback, allow_infer) ));
+
+ return rv;
+ }
::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer)
{
TRACE_FUNCTION_F("tpl = " << tpl);
@@ -145,7 +169,7 @@ namespace typeck {
),
(TraitObject,
::HIR::TypeRef::Data::Data_TraitObject rv;
- rv.m_trait = monomorphise_genericpath_with(sp, e.m_trait, callback, allow_infer);
+ rv.m_trait = monomorphise_traitpath_with(sp, e.m_trait, callback, allow_infer);
for(const auto& trait : e.m_markers)
{
rv.m_markers.push_back( monomorphise_genericpath_with(sp, trait, callback, allow_infer) );
@@ -700,7 +724,7 @@ namespace typeck {
const auto& ops_trait = this->context.m_crate.get_lang_item_path(node.span(), item_name);
DEBUG("Searching for impl " << ops_trait << "< " << ty_right << "> for " << ty_left);
bool found_bound = this->context.find_trait_impls_bound(sp, ops_trait, ty_left,
- [&](const auto& args) {
+ [&](const auto& args, const auto& assoc) {
assert(args.m_types.size() == 1);
const auto& arg_type = args.m_types[0];
// TODO: if arg_type mentions Self?
@@ -1316,6 +1340,11 @@ namespace typeck {
DEBUG("- No impl of " << be.trait.m_path << " for " << real_type);
continue ;
}
+ for( const auto& assoc : be.trait.m_type_bounds ) {
+ auto ty = ::HIR::TypeRef( ::HIR::Path(::HIR::Path::Data::Data_UfcsKnown { box$(real_type.clone()), be.trait.m_path.clone(), assoc.first, {} }) );
+ this->context.apply_equality( sp, ty, [](const auto&x)->const auto&{return x;}, assoc.second, cache.m_monomorph_cb, nullptr );
+ }
+
),
(TypeEquality,
#if 0
@@ -1359,7 +1388,7 @@ namespace typeck {
::HIR::TypeRef fcn_ret;
// Locate impl of FnOnce
const auto& lang_FnOnce = this->context.m_crate.get_lang_item_path(node.span(), "fn_once");
- auto was_bounded = this->context.find_trait_impls_bound(node.span(), lang_FnOnce, ty, [&](const auto& args) {
+ auto was_bounded = this->context.find_trait_impls_bound(node.span(), lang_FnOnce, ty, [&](const auto& args, const auto& assoc) {
const auto& tup = args.m_types[0];
if( !tup.m_data.is_Tuple() )
ERROR(node.span(), E0000, "FnOnce expects a tuple argument, got " << tup);
@@ -1384,7 +1413,7 @@ namespace typeck {
else
{
// Didn't find anything. Error?
- TODO(node.span(), "Unable to find an implementation of Fn* for " << ty);
+ ERROR(node.span(), E0000, "Unable to find an implementation of Fn* for " << ty);
}
node.m_arg_types = mv$( fcn_args_tup.m_data.as_Tuple() );
@@ -1476,6 +1505,7 @@ namespace typeck {
BUG(sp, "Unknown target PathValue encountered with Generic path");
case ::HIR::ExprNode_PathValue::FUNCTION: {
//const auto& f = this->context.m_crate.get_fcn_by_path(sp, e.m_path);
+ //TODO(sp, "Function address values");
} break;
case ::HIR::ExprNode_PathValue::STATIC: {
const auto& v = this->context.m_crate.get_static_by_path(sp, e.m_path);
diff --git a/src/hir_typeck/expr.hpp b/src/hir_typeck/expr.hpp
index 5fa558a3..a3a5147b 100644
--- a/src/hir_typeck/expr.hpp
+++ b/src/hir_typeck/expr.hpp
@@ -15,6 +15,7 @@ extern bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl);
extern bool monomorphise_path_needed(const ::HIR::Path& tpl);
extern ::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer);
+extern ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer);
extern ::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer=true);
extern ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params, const ::HIR::TypeRef& tpl);
@@ -128,14 +129,18 @@ public:
/// Searches for a trait impl that matches the provided trait name and type
bool find_trait_impls(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const;
+
+ typedef ::std::function<bool(const ::HIR::PathParams&, const ::std::map< ::std::string,::HIR::TypeRef>&)> t_cb_trait_impl;
+
/// Locate a named trait in the provied trait (either itself or as a parent trait)
bool find_named_trait_in_trait(const Span& sp,
- const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr,
- const ::HIR::PathParams& pp, const ::HIR::TypeRef& self_type,
- ::std::function<bool(const ::HIR::PathParams&)> callback
+ const ::HIR::SimplePath& des,
+ const ::HIR::Trait& trait_ptr, const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& pp,
+ const ::HIR::TypeRef& self_type,
+ t_cb_trait_impl callback
) const;
/// Search for a trait implementation in current bounds
- bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const;
+ bool find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const;
/// Search for a trait implementation in the crate
bool find_trait_impls_crate(const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const;
diff --git a/src/hir_typeck/expr_context.cpp b/src/hir_typeck/expr_context.cpp
index eea61da7..4c0ae071 100644
--- a/src/hir_typeck/expr_context.cpp
+++ b/src/hir_typeck/expr_context.cpp
@@ -641,6 +641,9 @@ const ::HIR::TypeRef& typeck::TypecheckContext::expand_associated_types_to(const
TU_IFLET(::HIR::TypeRef::Data, t.m_data, Path, e,
if( e.path.m_data.is_Generic() )
return t;
+ else if( !e.binding.is_Unbound() ) {
+ return t;
+ }
else {
tmp_t = this->expand_associated_types(sp, t.clone());
DEBUG("Expanded " << t << " into " << tmp_t);
@@ -661,6 +664,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
const auto& l_t1 = left .m_data.is_Generic() ? cb_left (left ) : this->get_type(left );
const auto& r_t1 = right.m_data.is_Generic() ? cb_right(right) : this->get_type(right);
if( l_t1 == r_t1 ) {
+ DEBUG(l_t1 << " == " << r_t1);
return ;
}
@@ -669,6 +673,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
::HIR::TypeRef right_tmp;
const auto& r_t = this->expand_associated_types_to(sp, r_t1, right_tmp);
if( l_t == r_t ) {
+ DEBUG(l_t << " == " << r_t);
return ;
}
@@ -681,14 +686,14 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
else {
// Righthand side is infer, alias it to the left
// TODO: that `true` should be `false` if the callback isn't unity (for bug checking)
- this->set_ivar_to(r_e.index, monomorphise_type_with(sp, left, cb_left, true));
+ this->set_ivar_to(r_e.index, this->expand_associated_types(sp, monomorphise_type_with(sp, left, cb_left, true)));
}
)
else {
TU_IFLET(::HIR::TypeRef::Data, l_t.m_data, Infer, l_e,
// Lefthand side is infer, alias it to the right
// TODO: that `true` should be `false` if the callback isn't unity (for bug checking)
- this->set_ivar_to(l_e.index, monomorphise_type_with(sp, right, cb_right, true));
+ this->set_ivar_to(l_e.index, this->expand_associated_types(sp, monomorphise_type_with(sp, right, cb_right, true)));
)
else {
// If generic replacement happened, clear the callback
@@ -803,10 +808,16 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
}
),
(TraitObject,
- if( l_e.m_trait.m_path != r_e.m_trait.m_path ) {
+ if( l_e.m_trait.m_path.m_path != r_e.m_trait.m_path.m_path ) {
ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t);
}
- equality_typeparams(l_e.m_trait.m_params, r_e.m_trait.m_params);
+ equality_typeparams(l_e.m_trait.m_path.m_params, r_e.m_trait.m_path.m_params);
+ for(auto it_l = l_e.m_trait.m_type_bounds.begin(), it_r = r_e.m_trait.m_type_bounds.begin(); it_l != l_e.m_trait.m_type_bounds.end(); it_l++, it_r++ ) {
+ if( it_l->first != it_r->first ) {
+ ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t << " - associated bounds differ");
+ }
+ this->apply_equality(sp, it_l->second, cb_left, it_r->second, cb_right, nullptr);
+ }
// TODO: Possibly allow inferrence reducing the set?
if( l_e.m_markers.size() != r_e.m_markers.size() ) {
ERROR(sp, E0000, "Type mismatch between " << l_t << " and " << r_t << " - trait counts differ");
@@ -886,7 +897,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
}
// 1. Search for an implementation of the data trait for this type
- bool succ = this->find_trait_impls(e.m_trait.m_path, right_inner_res, [&](const auto& args) {
+ bool succ = this->find_trait_impls(e.m_trait.m_path.m_path, right_inner_res, [&](const auto& args) {
if( args.m_types.size() > 0 )
TODO(sp, "Handle unsizing to traits with params");
return true;
@@ -902,6 +913,10 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
// return true;
// });
}
+ for(const auto& assoc : e.m_trait.m_type_bounds)
+ {
+ TODO(sp, "Check for associated type ("<<assoc.first<<") validity when unsizing to " << left_inner_res << " from " << right_inner_res);
+ }
// Valid unsize, insert unsize operation
auto span = node_ptr->span();
@@ -969,7 +984,7 @@ void typeck::TypecheckContext::apply_equality(const Span& sp, const ::HIR::TypeR
// -------------------------------------------------------------------------------------------------------------------
bool typeck::TypecheckContext::check_trait_bound(const Span& sp, const ::HIR::TypeRef& type, const ::HIR::GenericPath& trait, ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)> placeholder) const
{
- if( this->find_trait_impls_bound(sp, trait.m_path, placeholder(type), [&](const auto& args){
+ if( this->find_trait_impls_bound(sp, trait.m_path, placeholder(type), [&](const auto& args, const auto& _){
DEBUG("TODO: Check args for " << trait.m_path << args << " against " << trait);
return true;
})
@@ -1036,7 +1051,7 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
)
// 1. Search generic params
- if( find_trait_impls_bound(sp, trait, type, callback) )
+ if( find_trait_impls_bound(sp, trait, type, [&callback](const auto& pp, const auto& _) { return callback(pp); }) )
return true;
// 2. Search crate-level impls
return find_trait_impls_crate(trait, type, callback);
@@ -1112,28 +1127,92 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
// 1. Bounds
bool rv;
+ bool assume_opaque = true;
rv = this->iterate_bounds([&](const auto& b) {
- TU_IFLET(::HIR::GenericBound, b, TypeEquality, be,
+ TU_MATCH_DEF(::HIR::GenericBound, (b), (be),
+ (
+ ),
+ (TraitBound,
+ DEBUG("Trait bound - " << be.type << " : " << be.trait);
+ // 1. Check if the type matches
+ // - TODO: This should be a fuzzier match?
+ if( be.type != *e2.type )
+ return false;
+ // 2. Check if the trait (or any supertrait) includes e2.trait
+ if( be.trait.m_path == e2.trait ) {
+ auto it = be.trait.m_type_bounds.find(e2.item);
+ // 1. Check if the bounds include the desired item
+ if( it == be.trait.m_type_bounds.end() ) {
+ // If not, assume it's opaque and return as such
+ // TODO: What happens if there's two bounds that overlap? 'F: FnMut<()>, F: FnOnce<(), Output=Bar>'
+ DEBUG("Found impl for " << input << " but no bound on item, assuming opaque");
+ }
+ else {
+ assume_opaque = false;
+ input = it->second.clone();
+ }
+ return true;
+ }
+
+ bool found_supertrait = this->find_named_trait_in_trait(sp,
+ e2.trait.m_path,
+ *be.trait.m_trait_ptr, be.trait.m_path.m_path, be.trait.m_path.m_params, *e2.type,
+ [&e2,&input,&assume_opaque](const auto& x, const auto& assoc){
+ auto it = assoc.find(e2.item);
+ if( it != assoc.end() ) {
+ assume_opaque = false;
+ DEBUG("Found associated type " << input << " = " << it->second);
+ input = it->second.clone();
+ }
+ return true;
+ }
+ );
+ if( found_supertrait ) {
+ auto it = be.trait.m_type_bounds.find(e2.item);
+ // 1. Check if the bounds include the desired item
+ if( it == be.trait.m_type_bounds.end() ) {
+ // If not, assume it's opaque and return as such
+ // TODO: What happens if there's two bounds that overlap? 'F: FnMut<()>, F: FnOnce<(), Output=Bar>'
+ if( assume_opaque )
+ DEBUG("Found impl for " << input << " but no bound on item, assuming opaque");
+ }
+ else {
+ assume_opaque = false;
+ input = it->second.clone();
+ }
+ return true;
+ }
+
+ // - Didn't match
+ ),
+ (TypeEquality,
DEBUG("Equality - " << be.type << " = " << be.other_type);
if( input == be.type ) {
input = be.other_type.clone();
return true;
}
+ )
)
return false;
});
if( rv ) {
+ if( assume_opaque ) {
+ DEBUG("Assuming that " << input << " is an opaque name");
+ input.m_data.as_Path().binding = ::HIR::TypeRef::TypePathBinding::make_Opaque({});
+ }
return input;
}
+ // If the type of this UfcsKnown is ALSO a UfcsKnown - Check if it's bounded by this trait with equality
// Use bounds on other associated types too (if `e2.type` was resolved to a fixed associated type)
- TU_IFLET(::HIR::TypeRef::Data, e2.type->m_data, Path, e3,
- TU_IFLET(::HIR::Path::Data, e3.path.m_data, UfcsKnown, pe,
+ TU_IFLET(::HIR::TypeRef::Data, e2.type->m_data, Path, te_inner,
+ TU_IFLET(::HIR::Path::Data, te_inner.path.m_data, UfcsKnown, pe_inner,
// TODO: Search for equality bounds on this associated type (e3) that match the entire type (e2)
// - Does simplification of complex associated types
- const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, pe.trait.m_path);
- const auto& assoc_ty = trait_ptr.m_types.at(pe.item);
- DEBUG("TODO: Search bounds " << assoc_ty.m_params.fmt_bounds());
+ const auto& trait_ptr = this->m_crate.get_trait_by_path(sp, pe_inner.trait.m_path);
+ const auto& assoc_ty = trait_ptr.m_types.at(pe_inner.item);
+ DEBUG("TODO: Search bounds on associated type - " << assoc_ty.m_params.fmt_bounds());
+
// Resolve where Self=e2.type, for the associated type check.
auto cb_placeholders_type = [&](const auto& ty)->const auto&{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
@@ -1146,13 +1225,13 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
return ty;
}
};
- // Resolve where Self=pe.type (i.e. for the trait this inner UFCS is on)
+ // Resolve where Self=pe_inner.type (i.e. for the trait this inner UFCS is on)
auto cb_placeholders_trait = [&](const auto& ty)->const auto&{
TU_IFLET(::HIR::TypeRef::Data, ty.m_data, Generic, e,
if( e.binding == 0xFFFF )
- return *pe.type;
+ return *pe_inner.type;
else {
- // TODO: Look in pe.trait.m_params
+ // TODO: Look in pe_inner.trait.m_params
TODO(sp, "Handle type params when expanding associated bound (#" << e.binding << " " << e.name);
}
)
@@ -1162,12 +1241,30 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
};
for(const auto& bound : assoc_ty.m_params.m_bounds)
{
- TU_IFLET(::HIR::GenericBound, bound, TypeEquality, be,
+ TU_MATCH_DEF(::HIR::GenericBound, (bound), (be),
+ (
+ ),
+ (TraitBound,
+ // If the bound is for Self and the outer trait
+ // - TODO: Parameters?
+ if( be.type == ::HIR::TypeRef("Self", 0xFFFF) && be.trait.m_path == e2.trait ) {
+ auto it = be.trait.m_type_bounds.find( e2.item );
+ if( it != be.trait.m_type_bounds.end() ) {
+ if( monomorphise_type_needed(it->second) ) {
+ return monomorphise_type_with(sp, it->second, cb_placeholders_trait);
+ }
+ else {
+ return it->second.clone();
+ }
+ }
+ }
+ ),
+ (TypeEquality,
// IF: bound's type matches the input, replace with bounded equality
// `<Self::IntoIter as Iterator>::Item = Self::Item`
if( be.type.compare_with_paceholders(sp, input, cb_placeholders_type ) ) {
DEBUG("Match of " << be.type << " with " << input);
- DEBUG("- Replace `input` with " << be.other_type << ", Self=" << *pe.type);
+ DEBUG("- Replace `input` with " << be.other_type << ", Self=" << *pe_inner.type);
if( monomorphise_type_needed(be.other_type) ) {
return monomorphise_type_with(sp, be.other_type, cb_placeholders_trait);
}
@@ -1175,6 +1272,7 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
return be.other_type.clone();
}
}
+ )
)
}
DEBUG("e2 = " << *e2.type << ", input = " << input);
@@ -1315,16 +1413,19 @@ bool typeck::TypecheckContext::find_trait_impls(const ::HIR::SimplePath& trait,
//
// -------------------------------------------------------------------------------------------------------------------
bool typeck::TypecheckContext::find_named_trait_in_trait(const Span& sp,
- const ::HIR::SimplePath& des, const ::HIR::Trait& trait_ptr,
- const ::HIR::PathParams& pp, const ::HIR::TypeRef& target_type,
- ::std::function<bool(const ::HIR::PathParams&)> callback
+ const ::HIR::SimplePath& des,
+ const ::HIR::Trait& trait_ptr, const ::HIR::SimplePath& trait_path, const ::HIR::PathParams& pp,
+ const ::HIR::TypeRef& target_type,
+ t_cb_trait_impl callback
) const
{
- TRACE_FUNCTION_F(des << pp);
- assert( pp.m_types.size() == trait_ptr.m_params.m_types.size() );
+ TRACE_FUNCTION_F(des << " from " << trait_path << pp);
+ if( pp.m_types.size() != trait_ptr.m_params.m_types.size() ) {
+ BUG(sp, "Incorrect number of parameters for trait");
+ }
for( const auto& pt : trait_ptr.m_parent_traits )
{
- auto pt_pp = monomorphise_path_params_with(Span(), pt.m_params.clone(), [&](const auto& gt)->const auto& {
+ auto pt_mono = monomorphise_traitpath_with(sp, pt, [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
if( ge.binding == 0xFFFF ) {
return target_type;
@@ -1335,27 +1436,27 @@ bool typeck::TypecheckContext::find_named_trait_in_trait(const Span& sp,
return pp.m_types[ge.binding];
}
}, false);
-
- if( pt.m_path == des ) {
- //TODO(Span(), "Fix arguments for a parent trait and call callback - " << pt << " with paramset " << trait_ptr.m_params.fmt_args() << " = " << pt_pp);
- callback( pt_pp );
+
+ DEBUG(pt << " => " << pt_mono);
+ if( pt.m_path.m_path == des ) {
+ callback( pt_mono.m_path.m_params, pt_mono.m_type_bounds );
return true;
}
}
return false;
}
-bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, ::std::function<bool(const ::HIR::PathParams&)> callback) const
+bool typeck::TypecheckContext::find_trait_impls_bound(const Span& sp, const ::HIR::SimplePath& trait, const ::HIR::TypeRef& type, t_cb_trait_impl callback) const
{
return this->iterate_bounds([&](const auto& b) {
TU_IFLET(::HIR::GenericBound, b, TraitBound, e,
if( e.type != type )
return false;
if( e.trait.m_path.m_path == trait ) {
- if( callback(e.trait.m_path.m_params) ) {
+ if( callback(e.trait.m_path.m_params, e.trait.m_type_bounds) ) {
return true;
}
}
- if( this->find_named_trait_in_trait(sp, trait, *e.trait.m_trait_ptr, e.trait.m_path.m_params, type, callback) ) {
+ if( this->find_named_trait_in_trait(sp, trait, *e.trait.m_trait_ptr, e.trait.m_path.m_path, e.trait.m_path.m_params, type, callback) ) {
return true;
}
)
@@ -1390,8 +1491,8 @@ bool typeck::TypecheckContext::trait_contains_method(const Span& sp, const ::HIR
// TODO: Prevent infinite recursion
for(const auto& st : trait_ptr.m_parent_traits)
{
- auto& st_ptr = this->m_crate.get_trait_by_path(sp, st.m_path);
- if( trait_contains_method(sp, st, st_ptr, name, out_path) ) {
+ auto& st_ptr = this->m_crate.get_trait_by_path(sp, st.m_path.m_path);
+ if( trait_contains_method(sp, st.m_path, st_ptr, name, out_path) ) {
out_path.m_params = monomorphise_path_params_with(sp, mv$(out_path.m_params), [&](const auto& gt)->const auto& {
const auto& ge = gt.m_data.as_Generic();
assert(ge.binding < 256);
@@ -1616,6 +1717,9 @@ void typeck::TypecheckContext::set_ivar_to(unsigned int slot, ::HIR::TypeRef typ
root_ivar.alias = l_e.index;
root_ivar.type.reset();
)
+ else if( *root_ivar.type == type ) {
+ return ;
+ }
else {
// Otherwise, store left in right's slot
DEBUG("Set IVar " << slot << " = " << type);
diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp
index 2a5b5561..0fd1a8d7 100644
--- a/src/resolve/absolute.cpp
+++ b/src/resolve/absolute.cpp
@@ -900,6 +900,12 @@ void Resolve_Absolute_Type(Context& context, TypeRef& type)
}
assert( ufcs.nodes.size() == 1);
)
+
+ TU_IFLET(::AST::PathBinding, e.path.binding(), Trait, be,
+ auto ty = ::TypeRef( type.span(), {}, ::make_vec1(mv$(e.path)) );
+ type = mv$(ty);
+ return ;
+ )
),
(TraitObject,
//context.push_lifetimes( e.hrls );