diff --git a/src/hir/visitor.cpp b/src/hir/visitor.cpp index 639ea7cf1..aa1084660 100644 --- a/src/hir/visitor.cpp +++ b/src/hir/visitor.cpp @@ -7,6 +7,7 @@ */ #include #include +#include ::HIR::Visitor::~Visitor() { @@ -125,6 +126,9 @@ void ::HIR::Visitor::visit_type_impl(::HIR::TypeImpl& impl) { ::HIR::ItemPath p { impl.m_type }; TRACE_FUNCTION_F("impl.m_type=" << impl.m_type); + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, impl.m_params); + } this->visit_params(impl.m_params); this->visit_type(impl.m_type); @@ -136,11 +140,17 @@ void ::HIR::Visitor::visit_type_impl(::HIR::TypeImpl& impl) DEBUG("const " << ent.first); this->visit_constant(p + ent.first, ent.second.data); } + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR::TraitImpl& impl) { ::HIR::ItemPath p( impl.m_type, trait_path, impl.m_trait_args ); TRACE_FUNCTION_F("impl" << impl.m_params.fmt_args() << " " << trait_path << impl.m_trait_args << " for " << impl.m_type ); + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, impl.m_params); + } this->visit_params(impl.m_params); // - HACK: Create a generic path to visit (so that proper checks are performed) { @@ -166,27 +176,51 @@ void ::HIR::Visitor::visit_trait_impl(const ::HIR::SimplePath& trait_path, ::HIR DEBUG("type " << ent.first); this->visit_type(ent.second.data); } + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_marker_impl(const ::HIR::SimplePath& trait_path, ::HIR::MarkerImpl& impl) { + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, impl.m_params); + } this->visit_params(impl.m_params); this->visit_path_params(impl.m_trait_args); this->visit_type(impl.m_type); + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_type_alias(::HIR::ItemPath p, ::HIR::TypeAlias& item) { + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, item.m_params); + } this->visit_params(item.m_params); this->visit_type(item.m_type); + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_trait_alias(::HIR::ItemPath p, ::HIR::TraitAlias& item) { + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, item.m_params); + } this->visit_params(item.m_params); for(auto& p : item.m_traits) this->visit_trait_path(p); + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) { + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, item.m_params); + } ::HIR::SimplePath trait_sp = p.get_simple_path(); ItemPath trait_ip(trait_sp); TRACE_FUNCTION; @@ -221,9 +255,15 @@ void ::HIR::Visitor::visit_trait(::HIR::ItemPath p, ::HIR::Trait& item) ) ) } + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_struct(::HIR::ItemPath p, ::HIR::Struct& item) { + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, item.m_params); + } this->visit_params(item.m_params); TU_MATCH_HDRA( (item.m_data), {) TU_ARMA(Unit, e) { @@ -239,9 +279,15 @@ void ::HIR::Visitor::visit_struct(::HIR::ItemPath p, ::HIR::Struct& item) } } } + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) { + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::None, item.m_params); + } this->visit_params(item.m_params); TU_MATCH_HDRA( (item.m_data), {) TU_ARMA(Value, e) { @@ -257,13 +303,22 @@ void ::HIR::Visitor::visit_enum(::HIR::ItemPath p, ::HIR::Enum& item) } } } + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_union(::HIR::ItemPath p, ::HIR::Union& item) { TRACE_FUNCTION_F(p); + if( m_resolve ) { + m_resolve->set_impl_generics_raw(MetadataType::Unknown, item.m_params); + } this->visit_params(item.m_params); for(auto& var : item.m_variants) this->visit_type(var.second.ent); + if( m_resolve ) { + m_resolve->clear_impl_generics(); + } } void ::HIR::Visitor::visit_associatedtype(ItemPath p, ::HIR::AssociatedType& item) { @@ -275,6 +330,9 @@ void ::HIR::Visitor::visit_associatedtype(ItemPath p, ::HIR::AssociatedType& ite void ::HIR::Visitor::visit_function(::HIR::ItemPath p, ::HIR::Function& item) { TRACE_FUNCTION_F(p); + if( m_resolve ) { + m_resolve->set_item_generics_raw(item.m_params); + } this->visit_params(item.m_params); for(auto& arg : item.m_args) { @@ -283,19 +341,34 @@ void ::HIR::Visitor::visit_function(::HIR::ItemPath p, ::HIR::Function& item) } this->visit_type(item.m_return); this->visit_expr(item.m_code); + if( m_resolve ) { + m_resolve->clear_item_generics(); + } } void ::HIR::Visitor::visit_static(::HIR::ItemPath p, ::HIR::Static& item) { TRACE_FUNCTION_F(p); + if( m_resolve ) { + m_resolve->set_item_generics_raw(item.m_params); + } this->visit_type(item.m_type); this->visit_expr(item.m_value); + if( m_resolve ) { + m_resolve->clear_item_generics(); + } } void ::HIR::Visitor::visit_constant(::HIR::ItemPath p, ::HIR::Constant& item) { TRACE_FUNCTION_F(p); + if( m_resolve ) { + m_resolve->set_item_generics_raw(item.m_params); + } this->visit_params(item.m_params); this->visit_type(item.m_type); this->visit_expr(item.m_value); + if( m_resolve ) { + m_resolve->clear_item_generics(); + } } void ::HIR::Visitor::visit_params(::HIR::GenericParams& params) diff --git a/src/hir/visitor.hpp b/src/hir/visitor.hpp index 68285c3fc..5cdc0aaff 100644 --- a/src/hir/visitor.hpp +++ b/src/hir/visitor.hpp @@ -13,12 +13,16 @@ #include #include +class StaticTraitResolve; + namespace HIR { // TODO: Split into Visitor and ItemVisitor class Visitor { + StaticTraitResolve* m_resolve; public: + Visitor(::StaticTraitResolve* resolve=nullptr): m_resolve(resolve) {} virtual ~Visitor(); virtual void visit_crate(::HIR::Crate& crate); diff --git a/src/hir_expand/erased_types.cpp b/src/hir_expand/erased_types.cpp index 6a857565c..859173727 100644 --- a/src/hir_expand/erased_types.cpp +++ b/src/hir_expand/erased_types.cpp @@ -53,6 +53,55 @@ namespace { ty = mv$(new_ty); } + void visit_type(const Span& sp, const StaticTraitResolve& resolve, ::HIR::TypeRef& ty) { + TRACE_FUNCTION_FR(ty, ty); + class V: + public ::HIR::Visitor + { + const Span& sp; + const StaticTraitResolve& m_resolve; + bool clear_opaque; + public: + V(const Span& sp, const StaticTraitResolve& resolve) + : sp(sp) + , m_resolve(resolve) + , clear_opaque(false) + {} + + void visit_type(::HIR::TypeRef& ty) override + { + static const Span sp; + auto saved_clear_opaque = this->clear_opaque; + this->clear_opaque = false; + if( ty.data().is_ErasedType() ) + { + TRACE_FUNCTION_FR(ty, ty); + + expand_erased_type(sp, m_resolve, ty); + + // Recurse (TODO: Cleanly prevent infinite recursion - TRACE_FUNCTION does crude prevention) + this->visit_type(ty); + this->clear_opaque = true; + } + else + { + ::HIR::Visitor::visit_type(ty); + // If there was an erased type anywhere within this type, then clear an Opaque binding so EAT runs again + if( auto* p = ty.data_mut().opt_Path() ) { + // NOTE: This is both an optimisation, and avoids issues (if all types are cleared, the alias list in + // `StaticTraitResolve` ends up with un-expanded ATYs which leads to expansion not happening when it shoud. + if( this->clear_opaque && p->binding.is_Opaque() ) { + p->binding = HIR::TypePathBinding::make_Unbound({}); + } + } + } + this->clear_opaque |= saved_clear_opaque; + } + } v(sp, resolve); + v.visit_type(ty); + resolve.expand_associated_types(sp, ty); + } + class ExprVisitor_Extract: public ::HIR::ExprVisitorDef { @@ -83,20 +132,7 @@ namespace { void visit_type(::HIR::TypeRef& ty) override { static Span sp; - - if( ty.data().is_ErasedType() ) - { - TRACE_FUNCTION_FR(ty, ty); - - expand_erased_type(sp, m_resolve, ty); - - // Recurse (TODO: Cleanly prevent infinite recursion - TRACE_FUNCTION does crude prevention) - visit_type(ty); - } - else - { - ::HIR::ExprVisitorDef::visit_type(ty); - } + ::visit_type(sp, m_resolve, ty); } }; @@ -104,10 +140,10 @@ namespace { public ::HIR::Visitor { StaticTraitResolve m_resolve; - const ::HIR::ItemPath* m_fcn_path = nullptr; public: - OuterVisitor(const ::HIR::Crate& crate): - m_resolve(crate) + OuterVisitor(const ::HIR::Crate& crate) + : ::HIR::Visitor(&m_resolve) + , m_resolve(crate) {} void visit_expr(::HIR::ExprPtr& exp) override @@ -118,39 +154,21 @@ namespace { ev.visit_root( exp ); } } - - void visit_function(::HIR::ItemPath p, ::HIR::Function& fcn) override - { - m_fcn_path = &p; - ::HIR::Visitor::visit_function(p, fcn); - m_fcn_path = nullptr; - } }; class OuterVisitor_Fixup: public ::HIR::Visitor { StaticTraitResolve m_resolve; public: - OuterVisitor_Fixup(const ::HIR::Crate& crate): - m_resolve(crate) + OuterVisitor_Fixup(const ::HIR::Crate& crate) + : ::HIR::Visitor(&m_resolve) + , m_resolve(crate) {} void visit_type(::HIR::TypeRef& ty) override { - static const Span sp; - if( ty.data().is_ErasedType() ) - { - TRACE_FUNCTION_FR(ty, ty); - - expand_erased_type(sp, m_resolve, ty); - - // Recurse (TODO: Cleanly prevent infinite recursion - TRACE_FUNCTION does crude prevention) - visit_type(ty); - } - else - { - ::HIR::Visitor::visit_type(ty); - } + static Span sp; + ::visit_type(sp, m_resolve, ty); } }; }